Dify框架后端接口API文档

工作流编排对话型应用 API 文档

概述

工作流编排对话型应用 API 支持会话持久化,可将之前的聊天记录作为上下文进行回答,适用于聊天、客服 AI 等场景。


基础信息

基础 URL

复制代码
http://aiagent.xxxx.net/v1

鉴权方式

Service API 使用 API-Key 进行鉴权。

请求头示例:

复制代码
Authorization: Bearer {API_KEY}

注意: 强烈建议开发者把 API-Key 放在后端存储,而非分享或者放在客户端存储,以免 API-Key 泄露,导致财产损失。


API 接口列表

1. 发送对话消息

接口信息
  • 方法: POST

  • 路径: /chat-messages

  • 描述: 创建会话消息,支持流式和阻塞两种响应模式

请求参数

Body 参数 (application/json):

字段名 类型 必填 描述
query string 用户输入/提问内容
inputs object 允许传入 App 定义的各变量值。包含多组键值对,每组的键对应一个特定变量,每组的值则是该变量的具体值。默认 {}
response_mode string 响应模式: • streaming - 流式模式(推荐),基于 SSE 实现类似打字机输出方式 • blocking - 阻塞模式,等待执行完毕后返回结果(注意:请求若流程较长可能会被中断,Cloudflare 限制 100 秒超时)
user string 用户标识,用于定义终端用户的身份,方便检索、统计。由开发者定义规则,需保证用户标识在应用内唯一。服务 API 不会共享 WebApp 创建的对话
conversation_id string 会话 ID,需要基于之前的聊天记录继续对话时,必须传之前消息的 conversation_id
files array[object] 文件列表,适用于传入文件结合文本理解并回答问题,仅当模型支持 Vision/Video 能力时可用
auto_generate_name bool 自动生成标题,默认 true。若设置为 false,则可通过调用会话重命名接口并设置 auto_generatetrue 实现异步生成标题
workflow_id string 工作流ID,用于指定特定版本,如果不提供则使用默认的已发布版本
trace_id string 链路追踪ID。适用于与业务系统已有的 trace 组件打通,实现端到端分布式追踪等场景。支持三种传递方式(优先级从高到低): 1. HTTP Header X-Trace-Id 2. URL 查询参数 trace_id 3. 请求体字段 trace_id

files 对象结构:

复制代码
{
  "type": "string", // 支持类型:document, image, audio, video, custom
  "transfer_method": "string", // 传递方式:remote_url, local_file
  "url": "string", // 文件地址(仅当传递方式为 remote_url 时)
  "upload_file_id": "string" // 上传文件 ID(仅当传递方式为 local_file 时)
}
响应格式

1. 阻塞模式响应 (response_mode: "blocking")

Content-Type: application/json

复制代码
interface ChatCompletionResponse {
  event: "message"; // 固定值
  task_id: string; // 任务 ID,用于请求跟踪和停止响应接口
  id: string; // 唯一ID
  message_id: string; // 消息唯一 ID
  conversation_id: string; // 会话 ID
  mode: "chat"; // App 模式,固定为 chat
  answer: string; // 完整回复内容
  metadata: {
    usage: Usage; // 模型用量信息
    retriever_resources: RetrieverResource[]; // 引用和归属分段列表
  };
  created_at: number; // 消息创建时间戳
}

interface Usage {
  prompt_tokens: number; // 提示词 tokens
  prompt_unit_price: string; // 提示词单价
  prompt_price_unit: string; // 提示词价格单位
  prompt_price: string; // 提示词价格
  completion_tokens: number; // 补全 tokens
  completion_unit_price: string; // 补全单价
  completion_price_unit: string; // 补全价格单位
  completion_price: string; // 补全价格
  total_tokens: number; // 总 tokens
  total_price: string; // 总价格
  currency: string; // 货币,如 USD / RMB
  latency: number; // 延迟
}

interface RetrieverResource {
  position: number; // 位置
  dataset_id: string; // 数据集 ID
  dataset_name: string; // 数据集名称
  document_id: string; // 文档 ID
  document_name: string; // 文档名称
  segment_id: string; // 分段 ID
  score: number; // 相似度分数
  content: string; // 内容
}

2. 流式模式响应 (response_mode: "streaming")

Content-Type: text/event-stream

流式返回格式为 SSE (Server-Sent Events),每个事件以 data: 开头,以 \n\n 结束。事件类型如下:

事件类型 描述
workflow_started workflow 开始执行
node_started node 开始执行
node_finished node 执行结束
workflow_finished workflow 执行结束
message LLM 返回文本块事件
message_file 文件事件,表示有新文件需要展示
message_end 消息结束事件
tts_message TTS 音频流事件
tts_message_end TTS 音频流结束事件
message_replace 消息内容替换事件(开启内容审查时)
error 流式输出过程中出现的异常
ping 每 10s 一次的 ping 事件,保持连接存活

各事件具体结构:

复制代码
// message 事件
interface MessageEvent {
  event: "message";
  task_id: string;
  message_id: string;
  conversation_id: string;
  answer: string; // LLM 返回文本块内容
  created_at: number;
}

// message_end 事件
interface MessageEndEvent {
  event: "message_end";
  id: string;
  conversation_id: string;
  metadata: {
    usage: Usage;
    retriever_resources: RetrieverResource[];
  };
}

// workflow_started 事件
interface WorkflowStartedEvent {
  event: "workflow_started";
  task_id: string;
  workflow_run_id: string;
  data: {
    id: string; // workflow 执行 ID
    workflow_id: string; // 关联 Workflow ID
    created_at: number; // 开始时间
  };
}

// error 事件
interface ErrorEvent {
  event: "error";
  task_id: string;
  message_id: string;
  status: number; // HTTP 状态码
  code: string; // 错误码
  message: string; // 错误消息
}
错误码
状态码 错误码 描述
404 - 对话不存在
400 invalid_param 传入参数异常
400 app_unavailable App 配置不可用
400 provider_not_initialize 无可用模型凭据配置
400 provider_quota_exceeded 模型调用额度不足
400 model_currently_not_support 当前模型不可用
400 workflow_not_found 指定的工作流版本未找到
400 draft_workflow_error 无法使用草稿工作流版本
400 workflow_id_format_error 工作流ID格式错误,需要UUID格式
400 completion_request_error 文本生成失败
500 - 服务内部异常
TypeScript 调用示例
复制代码
// 流式模式调用
async function sendChatMessageStreaming(query: string, conversationId?: string): Promise<void> {
  const response = await fetch('http://aiagent.ygwl.net/v1/chat-messages', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      query,
      inputs: {},
      response_mode: 'streaming',
      user: USER_ID,
      conversation_id: conversationId || '',
      files: []
    })
  });

  if (!response.body) return;

  const reader = response.body.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const chunk = decoder.decode(value);
    const lines = chunk.split('\n\n').filter(line => line.trim());

    for (const line of lines) {
      if (line.startsWith('data: ')) {
        const data = line.substring(6);
        try {
          const event = JSON.parse(data);
          handleEvent(event);
        } catch (e) {
          console.error('Parse error:', e);
        }
      }
    }
  }
}

function handleEvent(event: any) {
  switch (event.event) {
    case 'message':
      console.log('收到消息块:', event.answer);
      break;
    case 'message_end':
      console.log('消息结束,用量:', event.metadata.usage);
      break;
    case 'workflow_started':
      console.log('工作流开始:', event.data.workflow_id);
      break;
    case 'error':
      console.error('错误:', event.message);
      break;
    // ... 处理其他事件类型
  }
}

// 阻塞模式调用
async function sendChatMessageBlocking(query: string, conversationId?: string): Promise<ChatCompletionResponse> {
  const response = await fetch('http://aiagent.ygwl.net/v1/chat-messages', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      query,
      inputs: {},
      response_mode: 'blocking',
      user: USER_ID,
      conversation_id: conversationId || '',
      files: []
    })
  });

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }

  return response.json();
}

2. 上传文件

接口信息
  • 方法: POST

  • 路径: /files/upload

  • 描述: 上传文件并在发送消息时使用,可实现图文多模态理解。上传的文件仅供当前终端用户使用。

  • Content-Type: multipart/form-data

请求参数

Form Data 参数:

字段名 类型 必填 描述
file file 要上传的文件
user string 用户标识,必须和发送消息接口传入 user 保持一致
响应格式
复制代码
interface FileUploadResponse {
  id: string; // UUID,文件 ID
  name: string; // 文件名
  size: number; // 文件大小(byte)
  extension: string; // 文件后缀
  mime_type: string; // 文件 mime-type
  created_by: string; // 上传人 ID
  created_at: number; // 上传时间戳
}
错误码
状态码 错误码 描述
400 no_file_uploaded 必须提供文件
400 too_many_files 目前只接受一个文件
400 unsupported_preview 该文件不支持预览
400 unsupported_estimate 该文件不支持估算
413 file_too_large 文件太大
415 unsupported_file_type 不支持的扩展名,当前只接受文档类文件
503 s3_connection_failed 无法连接到 S3 服务
503 s3_permission_denied 无权限上传文件到 S3
503 s3_file_too_large 文件超出 S3 大小限制
TypeScript 调用示例
复制代码
async function uploadFile(file: File, userId: string): Promise<FileUploadResponse> {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('user', userId);

  const response = await fetch('http://aiagent.ygwl.net/v1/files/upload', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    },
    body: formData
  });

  if (!response.ok) {
    throw new Error(`上传失败: ${response.status}`);
  }

  return response.json();
}

// 使用示例
const fileInput = document.getElementById('file-input') as HTMLInputElement;
fileInput.addEventListener('change', async (e) => {
  const file = (e.target as HTMLInputElement).files?.[0];
  if (file) {
    try {
      const result = await uploadFile(file, 'user-123');
      console.log('文件上传成功:', result);
      // 在后续的聊天消息中使用 result.id
    } catch (error) {
      console.error('文件上传失败:', error);
    }
  }
});

3. 文件预览

接口信息
  • 方法: GET

  • 路径: /files/:file_id/preview

  • 描述: 预览或下载已上传的文件

路径参数
参数名 类型 必填 描述
file_id string 要预览的文件的唯一标识符,从文件上传 API 响应中获得
查询参数
参数名 类型 必填 描述
as_attachment boolean 是否强制将文件作为附件下载。默认为 false(在浏览器中预览)
响应

返回文件内容,响应头根据文件类型设置:

  • Content-Type: 根据文件 MIME 类型设置

  • Content-Length: 文件大小(字节)

  • Content-Disposition: 如果 as_attachment=true 则设置为 "attachment"

  • Cache-Control: 缓存控制头

  • Accept-Ranges: 对于音频/视频文件设置为 "bytes"

错误码
状态码 错误码 描述
400 invalid_param 参数输入异常
403 file_access_denied 文件访问被拒绝或文件不属于当前应用程序
404 file_not_found 文件未找到或已被删除
500 - 服务内部错误
TypeScript 调用示例
复制代码
// 预览文件
async function previewFile(fileId: string): Promise<void> {
  const url = `http://aiagent.ygwl.net/v1/files/${fileId}/preview`;
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`预览失败: ${response.status}`);
  }

  const blob = await response.blob();
  const objectUrl = URL.createObjectURL(blob);
  
  // 在浏览器中打开预览
  window.open(objectUrl);
}

// 下载文件
async function downloadFile(fileId: string, fileName?: string): Promise<void> {
  const url = `http://aiagent.ygwl.net/v1/files/${fileId}/preview?as_attachment=true`;
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`下载失败: ${response.status}`);
  }

  const blob = await response.blob();
  const downloadUrl = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = downloadUrl;
  a.download = fileName || 'downloaded_file';
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(downloadUrl);
}

4. 停止响应

接口信息
  • 方法: POST

  • 路径: /chat-messages/:task_id/stop

  • 描述: 停止流式响应,仅支持流式模式

路径参数
参数名 类型 必填 描述
task_id string 任务 ID,可在流式返回 Chunk 中获取
请求体参数
字段名 类型 必填 描述
user string 用户标识,必须和发送消息接口传入 user 保持一致
响应格式
复制代码
interface StopResponse {
  result: "success"; // 固定值
}
TypeScript 调用示例
复制代码
async function stopResponse(taskId: string, userId: string): Promise<StopResponse> {
  const response = await fetch(`http://aiagent.ygwl.net/v1/chat-messages/${taskId}/stop`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      user: userId
    })
  });

  if (!response.ok) {
    throw new Error(`停止失败: ${response.status}`);
  }

  return response.json();
}

5. 消息反馈(点赞)

接口信息
  • 方法: POST

  • 路径: /messages/:message_id/feedbacks

  • 描述: 消息终端用户反馈、点赞

路径参数
参数名 类型 必填 描述
message_id string 消息 ID
请求体参数
字段名 类型 必填 描述
rating string 点赞类型:like(点赞), dislike(点踩), null(撤销点赞)
user string 用户标识
content string 消息反馈的具体信息
响应格式
复制代码
interface FeedbackResponse {
  result: "success"; // 固定值
}
TypeScript 调用示例
复制代码
async function submitFeedback(
  messageId: string, 
  rating: 'like' | 'dislike' | null, 
  userId: string,
  content?: string
): Promise<FeedbackResponse> {
  const response = await fetch(`http://aiagent.ygwl.net/v1/messages/${messageId}/feedbacks`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      rating: rating === null ? 'null' : rating,
      user: userId,
      content: content || ''
    })
  });

  if (!response.ok) {
    throw new Error(`反馈提交失败: ${response.status}`);
  }

  return response.json();
}

6. 获取APP的消息点赞和反馈

接口信息
  • 方法: GET

  • 路径: /app/feedbacks

  • 描述: 获取应用的终端用户反馈、点赞

查询参数
参数名 类型 必填 描述
page string 分页,默认值:1
limit string 每页数量,默认值:20
响应格式
复制代码
interface AppFeedbacksResponse {
  data: Array<{
    id: string;
    app_id: string;
    conversation_id: string;
    message_id: string;
    rating: "like" | "dislike";
    content: string;
    from_source: string;
    from_end_user_id: string;
    from_account_id: string | null;
    created_at: string;
    updated_at: string;
  }>;
}
TypeScript 调用示例
复制代码
async function getAppFeedbacks(page: number = 1, limit: number = 20): Promise<AppFeedbacksResponse> {
  const url = `http://aiagent.ygwl.net/v1/app/feedbacks?page=${page}&limit=${limit}`;
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    }
  });

  if (!response.ok) {
    throw new Error(`获取反馈失败: ${response.status}`);
  }

  return response.json();
}

7. 获取下一轮建议问题列表

接口信息
  • 方法: GET

  • 路径: /messages/:message_id/suggested

  • 描述: 获取下一轮建议问题列表

路径参数
参数名 类型 必填 描述
message_id string 消息 ID
查询参数
参数名 类型 必填 描述
user string 用户标识
响应格式
复制代码
interface SuggestedQuestionsResponse {
  result: "success";
  data: string[]; // 建议问题列表
}
TypeScript 调用示例
复制代码
async function getSuggestedQuestions(messageId: string, userId: string): Promise<SuggestedQuestionsResponse> {
  const url = `http://aiagent.ygwl.net/v1/messages/${messageId}/suggested?user=${userId}`;
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    }
  });

  if (!response.ok) {
    throw new Error(`获取建议问题失败: ${response.status}`);
  }

  return response.json();
}

8. 获取会话历史消息

接口信息
  • 方法: GET

  • 路径: /messages

  • 描述: 滚动加载形式返回历史聊天记录,第一页返回最新 limit 条(倒序返回)

查询参数
参数名 类型 必填 描述
conversation_id string 会话 ID
user string 用户标识
first_id string 当前页第一条聊天记录的 ID,默认 null
limit number 一次请求返回多少条聊天记录,默认 20 条
响应格式
复制代码
interface MessagesResponse {
  limit: number; // 返回条数
  has_more: boolean; // 是否存在下一页
  data: Array<{
    id: string; // 消息 ID
    conversation_id: string; // 会话 ID
    inputs: Record<string, any>; // 用户输入参数
    query: string; // 用户输入 / 提问内容
    message_files: Array<{
      id: string;
      type: "image"; // 文件类型,目前仅 image
      url: string; // 文件预览地址
      belongs_to: "user" | "assistant"; // 文件归属方
    }>;
    answer: string; // 回答消息内容
    created_at: number; // 创建时间戳
    feedback: {
      rating: "like" | "dislike";
    } | null; // 反馈信息
    retriever_resources: RetrieverResource[]; // 引用和归属分段列表
  }>;
}
TypeScript 调用示例
复制代码
async function getMessages(
  conversationId: string, 
  userId: string, 
  firstId?: string, 
  limit: number = 20
): Promise<MessagesResponse> {
  let url = `http://aiagent.ygwl.net/v1/messages?user=${userId}&conversation_id=${conversationId}&limit=${limit}`;
  if (firstId) {
    url += `&first_id=${firstId}`;
  }

  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`获取消息失败: ${response.status}`);
  }

  return response.json();
}

// 分页加载示例
async function loadMoreMessages(
  conversationId: string, 
  userId: string, 
  lastMessageId?: string
): Promise<MessagesResponse> {
  return getMessages(conversationId, userId, lastMessageId);
}

9. 获取会话列表

接口信息
  • 方法: GET

  • 路径: /conversations

  • 描述: 获取当前用户的会话列表,默认返回最近的 20 条

查询参数
参数名 类型 必填 描述
user string 用户标识
last_id string 当前页最后面一条记录的 ID,默认 null
limit number 一次请求返回多少条记录,默认 20 条,最大 100 条,最小 1 条
sort_by string 排序字段,默认 -updated_at(按更新时间倒序排列) 可选值:created_at, -created_at, updated_at, -updated_at
响应格式
复制代码
interface ConversationsResponse {
  limit: number;
  has_more: boolean;
  data: Array<{
    id: string; // 会话 ID
    name: string; // 会话名称,默认由大语言模型生成
    inputs: Record<string, any>; // 用户输入参数
    status: string; // 会话状态
    introduction: string; // 开场白
    created_at: number; // 创建时间戳
    updated_at: number; // 更新时间戳
  }>;
}
TypeScript 调用示例
复制代码
async function getConversations(
  userId: string, 
  lastId?: string, 
  limit: number = 20,
  sortBy: string = '-updated_at'
): Promise<ConversationsResponse> {
  let url = `http://aiagent.ygwl.net/v1/conversations?user=${userId}&limit=${limit}&sort_by=${sortBy}`;
  if (lastId) {
    url += `&last_id=${lastId}`;
  }

  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`获取会话列表失败: ${response.status}`);
  }

  return response.json();
}

10. 删除会话

接口信息
  • 方法: DELETE

  • 路径: /conversations/:conversation_id

  • 描述: 删除会话

路径参数
参数名 类型 必填 描述
conversation_id string 会话 ID
请求体参数
字段名 类型 必填 描述
user string 用户标识
响应

状态码:204 No Content

TypeScript 调用示例
复制代码
async function deleteConversation(conversationId: string, userId: string): Promise<void> {
  const response = await fetch(`http://aiagent.ygwl.net/v1/conversations/${conversationId}`, {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      user: userId
    })
  });

  if (!response.ok) {
    throw new Error(`删除会话失败: ${response.status}`);
  }
}

11. 会话重命名

接口信息
  • 方法: POST

  • 路径: /conversations/:conversation_id/name

  • 描述: 对会话进行重命名,会话名称用于显示在支持多会话的客户端上

路径参数
参数名 类型 必填 描述
conversation_id string 会话 ID
请求体参数
字段名 类型 必填 描述
name string 名称,若 auto_generatetrue 时,该参数可不传
auto_generate boolean 自动生成标题,默认 false
user string 用户标识
响应格式
复制代码
interface RenameConversationResponse {
  id: string; // 会话 ID
  name: string; // 会话名称
  inputs: Record<string, any>; // 用户输入参数
  status: string; // 会话状态
  introduction: string; // 开场白
  created_at: number; // 创建时间戳
  updated_at: number; // 更新时间戳
}
TypeScript 调用示例
复制代码
async function renameConversation(
  conversationId: string, 
  userId: string, 
  options: {
    name?: string;
    autoGenerate?: boolean;
  }
): Promise<RenameConversationResponse> {
  const response = await fetch(`http://aiagent.ygwl.net/v1/conversations/${conversationId}/name`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      name: options.name || '',
      auto_generate: options.autoGenerate || false,
      user: userId
    })
  });

  if (!response.ok) {
    throw new Error(`重命名会话失败: ${response.status}`);
  }

  return response.json();
}

12. 获取对话变量

接口信息
  • 方法: GET

  • 路径: /conversations/:conversation_id/variables

  • 描述: 从特定对话中检索变量,用于提取对话过程中捕获的结构化数据

路径参数
参数名 类型 必填 描述
conversation_id string 要从中检索变量的对话ID
查询参数
参数名 类型 必填 描述
user string 用户标识
last_id string 当前页最后面一条记录的 ID,默认 null
limit number 一次请求返回多少条记录,默认 20 条,最大 100 条,最小 1 条
响应格式
复制代码
interface ConversationVariablesResponse {
  limit: number;
  has_more: boolean;
  data: Array<{
    id: string; // 变量 ID
    name: string; // 变量名称
    value_type: string; // 变量类型(字符串、数字、布尔等)
    value: string; // 变量值
    description: string; // 变量描述
    created_at: number; // 创建时间戳
    updated_at: number; // 最后更新时间戳
  }>;
}
错误码
状态码 错误码 描述
404 conversation_not_exists 对话不存在
TypeScript 调用示例
复制代码
async function getConversationVariables(
  conversationId: string, 
  userId: string, 
  lastId?: string, 
  limit: number = 20
): Promise<ConversationVariablesResponse> {
  let url = `http://aiagent.ygwl.net/v1/conversations/${conversationId}/variables?user=${userId}&limit=${limit}`;
  if (lastId) {
    url += `&last_id=${lastId}`;
  }

  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`获取对话变量失败: ${response.status}`);
  }

  return response.json();
}

// 根据变量名过滤
async function getConversationVariableByName(
  conversationId: string, 
  userId: string, 
  variableName: string
): Promise<ConversationVariablesResponse> {
  const url = `http://aiagent.ygwl.net/v1/conversations/${conversationId}/variables?user=${userId}&variable_name=${variableName}`;
  
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`获取变量失败: ${response.status}`);
  }

  return response.json();
}

13. 更新对话变量

接口信息
  • 方法: PUT

  • 路径: /conversations/:conversation_id/variables/:variable_id

  • 描述: 更新特定对话变量的值

路径参数
参数名 类型 必填 描述
conversation_id string 包含要更新变量的对话ID
variable_id string 要更新的变量ID
请求体参数
字段名 类型 必填 描述
value any 变量的新值,必须匹配变量的预期类型
user string 用户标识
响应格式
复制代码
interface UpdateVariableResponse {
  id: string; // 变量ID
  name: string; // 变量名称
  value_type: string; // 变量类型
  value: any; // 更新后的变量值
  description: string; // 变量描述
  created_at: number; // 创建时间戳
  updated_at: number; // 最后更新时间戳
}
错误码
状态码 错误码 描述
400 Type mismatch: variable expects {expected_type}, but got {actual_type} type 值类型与变量的预期类型不匹配
404 conversation_not_exists 对话不存在
404 conversation_variable_not_exists 变量不存在
TypeScript 调用示例
复制代码
async function updateConversationVariable(
  conversationId: string, 
  variableId: string, 
  userId: string, 
  value: any
): Promise<UpdateVariableResponse> {
  const response = await fetch(`http://aiagent.ygwl.net/v1/conversations/${conversationId}/variables/${variableId}`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      value,
      user: userId
    })
  });

  if (!response.ok) {
    const error = await response.json().catch(() => ({}));
    throw new Error(`更新变量失败: ${response.status} - ${error.message || '未知错误'}`);
  }

  return response.json();
}

// 使用示例
// 更新字符串变量
await updateConversationVariable('conv-id', 'var-id', 'user-123', '新的字符串值');

// 更新数字变量
await updateConversationVariable('conv-id', 'var-id', 'user-123', 123);

// 更新对象变量
await updateConversationVariable('conv-id', 'var-id', 'user-123', { key: 'value' });

14. 语音转文字

接口信息
  • 方法: POST

  • 路径: /audio-to-text

  • 描述: 语音转文字

  • Content-Type: multipart/form-data

请求参数

Form Data 参数:

字段名 类型 必填 描述
file file 语音文件。支持格式:mp3, mp4, mpeg, mpga, m4a, wav, webm。文件大小限制:15MB
user string 用户标识
响应格式
复制代码
interface AudioToTextResponse {
  text: string; // 输出文字
}
TypeScript 调用示例
复制代码
async function audioToText(file: File, userId: string): Promise<AudioToTextResponse> {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('user', userId);

  const response = await fetch('http://aiagent.ygwl.net/v1/audio-to-text', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    },
    body: formData
  });

  if (!response.ok) {
    throw new Error(`语音转文字失败: ${response.status}`);
  }

  return response.json();
}

// 使用示例
const audioFile = new File([audioBlob], 'audio.mp3', { type: 'audio/mp3' });
const result = await audioToText(audioFile, 'user-123');
console.log('识别结果:', result.text);

15. 文字转语音

接口信息
  • 方法: POST

  • 路径: /text-to-audio

  • 描述: 文字转语音

  • 响应 Content-Type: audio/wav

请求体参数
字段名 类型 必填 描述
message_id string Dify 生成的文本消息 ID,后台会通过 message_id 查找相应的内容直接合成语音。如果同时传 message_id 和 text,优先使用 message_id
text string 语音生成内容。如果没有传 message_id,则会使用这个字段的内容
user string 用户标识
响应

返回音频文件流,Content-Type 为 audio/wav

TypeScript 调用示例
复制代码
async function textToAudio(
  options: {
    messageId?: string;
    text?: string;
    userId: string;
  }
): Promise<Blob> {
  const response = await fetch('http://aiagent.ygwl.net/v1/text-to-audio', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      message_id: options.messageId || '',
      text: options.text || '',
      user: options.userId
    })
  });

  if (!response.ok) {
    throw new Error(`文字转语音失败: ${response.status}`);
  }

  return response.blob();
}

// 使用示例
async function playTextAsAudio(text: string, userId: string) {
  try {
    const audioBlob = await textToAudio({
      text,
      userId
    });
    
    const audioUrl = URL.createObjectURL(audioBlob);
    const audio = new Audio(audioUrl);
    audio.play();
    
    // 清理
    audio.onended = () => {
      URL.revokeObjectURL(audioUrl);
    };
  } catch (error) {
    console.error('播放音频失败:', error);
  }
}

// 下载音频文件
async function downloadTextAsAudio(text: string, userId: string, fileName: string = 'audio.wav') {
  try {
    const audioBlob = await textToAudio({
      text,
      userId
    });
    
    const downloadUrl = URL.createObjectURL(audioBlob);
    const a = document.createElement('a');
    a.href = downloadUrl;
    a.download = fileName;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(downloadUrl);
  } catch (error) {
    console.error('下载音频失败:', error);
  }
}

16. 获取应用基本信息

接口信息
  • 方法: GET

  • 路径: /info

  • 描述: 获取应用的基本信息

响应格式
复制代码
interface AppInfoResponse {
  name: string; // 应用名称
  description: string; // 应用描述
  tags: string[]; // 应用标签
  mode: string; // 应用模式,如 advanced-chat
  author_name: string; // 作者名称
}
TypeScript 调用示例
复制代码
async function getAppInfo(): Promise<AppInfoResponse> {
  const response = await fetch('http://aiagent.ygwl.net/v1/info', {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`获取应用信息失败: ${response.status}`);
  }

  return response.json();
}

17. 获取应用参数

接口信息
  • 方法: GET

  • 路径: /parameters

  • 描述: 用于进入页面一开始,获取功能开关、输入参数名称、类型及默认值等使用

响应格式
复制代码
interface AppParametersResponse {
  introduction: string; // 开场白
  suggested_questions: string[]; // 开场推荐问题列表
  suggested_questions_after_answer: {
    enabled: boolean; // 是否开启
  };
  speech_to_text: {
    enabled: boolean; // 是否开启
  };
  text_to_speech: {
    enabled: boolean; // 是否开启
    voice: string; // 语音类型
    language: string; // 语言
    autoPlay: "enabled" | "disabled"; // 自动播放
  };
  retriever_resource: {
    enabled: boolean; // 是否开启
  };
  annotation_reply: {
    enabled: boolean; // 是否开启
  };
  user_input_form: Array<{
    "text-input"?: {
      label: string; // 控件展示标签名
      variable: string; // 控件 ID
      required: boolean; // 是否必填
      default: string; // 默认值
      max_length?: number; // 最大长度
    };
    paragraph?: {
      label: string;
      variable: string;
      required: boolean;
      default: string;
    };
    select?: {
      label: string;
      variable: string;
      required: boolean;
      default: string;
      options: string[]; // 选项值
    };
  }>;
  file_upload: {
    document: {
      enabled: boolean; // 是否启用
      number_limits: number; // 文档数量限制,默认为 3
      transfer_methods: ("remote_url" | "local_file")[]; // 传输方式列表
    };
    image: {
      enabled: boolean;
      number_limits: number;
      transfer_methods: ("remote_url" | "local_file")[];
    };
    audio: {
      enabled: boolean;
      number_limits: number;
      transfer_methods: ("remote_url" | "local_file")[];
    };
    video: {
      enabled: boolean;
      number_limits: number;
      transfer_methods: ("remote_url" | "local_file")[];
    };
    custom: {
      enabled: boolean;
      number_limits: number;
      transfer_methods: ("remote_url" | "local_file")[];
    };
  };
  system_parameters: {
    file_size_limit: number; // 文档上传大小限制 (MB)
    image_file_size_limit: number; // 图片文件上传大小限制 (MB)
    audio_file_size_limit: number; // 音频文件上传大小限制 (MB)
    video_file_size_limit: number; // 视频文件上传大小限制 (MB)
  };
}
TypeScript 调用示例
复制代码
async function getAppParameters(): Promise<AppParametersResponse> {
  const response = await fetch('http://aiagent.ygwl.net/v1/parameters', {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`获取应用参数失败: ${response.status}`);
  }

  return response.json();
}

// 使用示例:根据参数配置动态生成表单
async function renderInputForm() {
  const params = await getAppParameters();
  
  params.user_input_form.forEach((formItem) => {
    if (formItem['text-input']) {
      const input = document.createElement('input');
      input.type = 'text';
      input.name = formItem['text-input'].variable;
      input.placeholder = formItem['text-input'].label;
      input.required = formItem['text-input'].required;
      input.maxLength = formItem['text-input'].max_length || 255;
      // 添加到表单...
    }
    // 处理其他类型的表单控件...
  });
}

18. 获取应用Meta信息

接口信息
  • 方法: GET

  • 路径: /meta

  • 描述: 用于获取工具 icon

响应格式
复制代码
interface AppMetaResponse {
  tool_icons: {
    [toolName: string]: 
      | string // 图标 URL
      | {
          background: string; // hex 格式的背景色
          content: string; // emoji
        };
  };
}
TypeScript 调用示例
复制代码
async function getAppMeta(): Promise<AppMetaResponse> {
  const response = await fetch('http://aiagent.ygwl.net/v1/meta', {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`获取应用Meta失败: ${response.status}`);
  }

  return response.json();
}

19. 获取应用 WebApp 设置

接口信息
  • 方法: GET

  • 路径: /site

  • 描述: 用于获取应用的 WebApp 设置

响应格式
复制代码
interface AppSiteResponse {
  title: string; // WebApp 名称
  chat_color_theme: string; // 聊天颜色主题,hex 格式
  chat_color_theme_inverted: boolean; // 聊天颜色主题是否反转
  icon_type: "emoji" | "image"; // 图标类型
  icon: string; // 图标,如果是 emoji 类型,则是 emoji 表情符号,如果是 image 类型,则是图片 URL
  icon_background: string; // hex 格式的背景色
  icon_url: string | null; // 图标 URL
  description: string; // 描述
  copyright: string; // 版权信息
  privacy_policy: string; // 隐私政策链接
  custom_disclaimer: string; // 自定义免责声明
  default_language: string; // 默认语言
  show_workflow_steps: boolean; // 是否显示工作流详情
  use_icon_as_answer_icon: boolean; // 是否使用 WebApp 图标替换聊天中的 🤖
}
TypeScript 调用示例
复制代码
async function getAppSite(): Promise<AppSiteResponse> {
  const response = await fetch('http://aiagent.ygwl.net/v1/site', {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`获取应用站点设置失败: ${response.status}`);
  }

  return response.json();
}

20. 标注管理接口

20.1 获取标注列表
接口信息
  • 方法: GET

  • 路径: /apps/annotations

  • 描述: 获取标注列表

查询参数
参数名 类型 必填 描述
page string 页码
limit string 每页数量
响应格式
复制代码
interface AnnotationsResponse {
  data: Array<{
    id: string;
    question: string;
    answer: string;
    hit_count: number;
    created_at: number;
  }>;
  has_more: boolean;
  limit: number;
  total: number;
  page: number;
}
20.2 创建标注
接口信息
  • 方法: POST

  • 路径: /apps/annotations

  • 描述: 创建标注

请求体参数
字段名 类型 必填 描述
question string 问题
answer string 答案内容
响应格式
复制代码
interface CreateAnnotationResponse {
  id: string;
  question: string;
  answer: string;
  hit_count: number;
  created_at: number;
}
20.3 更新标注
接口信息
  • 方法: PUT

  • 路径: /apps/annotations/:annotation_id

  • 描述: 更新标注

路径参数
参数名 类型 必填 描述
annotation_id string 标注 ID
请求体参数
字段名 类型 必填 描述
question string 问题
answer string 答案内容
响应格式
复制代码
interface UpdateAnnotationResponse {
  id: string;
  question: string;
  answer: string;
  hit_count: number;
  created_at: number;
}
20.4 删除标注
接口信息
  • 方法: DELETE

  • 路径: /apps/annotations/:annotation_id

  • 描述: 删除标注

路径参数
参数名 类型 必填 描述
annotation_id string 标注 ID
响应

状态码:204 No Content

20.5 标注回复初始设置
接口信息
  • 方法: POST

  • 路径: /apps/annotation-reply/:action

  • 描述: 标注回复初始设置

路径参数
参数名 类型 必填 描述
action string 动作,只能是 enabledisable
请求体参数
字段名 类型 必填 描述
embedding_provider_name string 指定的嵌入模型提供商,必须先在系统内设定好接入的模型
embedding_model_name string 指定的嵌入模型
score_threshold number 相似度阈值,当相似度大于该阈值时,系统会自动回复,否则不回复
响应格式
复制代码
interface AnnotationReplySetupResponse {
  job_id: string; // 任务 ID
  job_status: "waiting"; // 任务状态
}

注意: 该接口是异步执行,返回 job_id,需要通过查询 job 状态接口获取最终的执行结果。

20.6 查询标注回复初始设置任务状态
接口信息
  • 方法: GET

  • 路径: /apps/annotation-reply/:action/status/:job_id

  • 描述: 查询标注回复初始设置任务状态

路径参数
参数名 类型 必填 描述
action string 动作,必须是和标注回复初始设置接口的动作一致
job_id string 任务 ID,从标注回复初始设置接口返回的 job_id
TypeScript 调用示例
复制代码
// 获取标注列表
async function getAnnotations(page: number = 1, limit: number = 20): Promise<AnnotationsResponse> {
  const response = await fetch(`http://aiagent.ygwl.net/v1/apps/annotations?page=${page}&limit=${limit}`, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`获取标注列表失败: ${response.status}`);
  }

  return response.json();
}

// 创建标注
async function createAnnotation(question: string, answer: string): Promise<CreateAnnotationResponse> {
  const response = await fetch('http://aiagent.ygwl.net/v1/apps/annotations', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      question,
      answer
    })
  });

  if (!response.ok) {
    throw new Error(`创建标注失败: ${response.status}`);
  }

  return response.json();
}

// 更新标注
async function updateAnnotation(
  annotationId: string, 
  question: string, 
  answer: string
): Promise<UpdateAnnotationResponse> {
  const response = await fetch(`http://aiagent.ygwl.net/v1/apps/annotations/${annotationId}`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      question,
      answer
    })
  });

  if (!response.ok) {
    throw new Error(`更新标注失败: ${response.status}`);
  }

  return response.json();
}

// 删除标注
async function deleteAnnotation(annotationId: string): Promise<void> {
  const response = await fetch(`http://aiagent.ygwl.net/v1/apps/annotations/${annotationId}`, {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    }
  });

  if (!response.ok) {
    throw new Error(`删除标注失败: ${response.status}`);
  }
}

// 标注回复初始设置
async function setupAnnotationReply(
  action: 'enable' | 'disable',
  embeddingProvider: string,
  embeddingModel: string,
  scoreThreshold: number
): Promise<AnnotationReplySetupResponse> {
  const response = await fetch(`http://aiagent.ygwl.net/v1/apps/annotation-reply/${action}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      embedding_provider_name: embeddingProvider,
      embedding_model_name: embeddingModel,
      score_threshold: scoreThreshold
    })
  });

  if (!response.ok) {
    throw new Error(`标注回复设置失败: ${response.status}`);
  }

  return response.json();
}

// 查询任务状态
async function checkAnnotationReplyStatus(action: string, jobId: string): Promise<any> {
  const response = await fetch(`http://aiagent.ygwl.net/v1/apps/annotation-reply/${action}/status/${jobId}`, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    }
  });

  if (!response.ok) {
    throw new Error(`查询任务状态失败: ${response.status}`);
  }

  return response.json();
}

完整 TypeScript 类型定义

复制代码
// 基础类型定义
interface Usage {
  prompt_tokens: number;
  prompt_unit_price: string;
  prompt_price_unit: string;
  prompt_price: string;
  completion_tokens: number;
  completion_unit_price: string;
  completion_price_unit: string;
  completion_price: string;
  total_tokens: number;
  total_price: string;
  currency: string;
  latency: number;
}

interface RetrieverResource {
  position: number;
  dataset_id: string;
  dataset_name: string;
  document_id: string;
  document_name: string;
  segment_id: string;
  score: number;
  content: string;
}

// 文件类型定义
type FileType = 'document' | 'image' | 'audio' | 'video' | 'custom';
type TransferMethod = 'remote_url' | 'local_file';

interface ChatFile {
  type: FileType;
  transfer_method: TransferMethod;
  url?: string;
  upload_file_id?: string;
}

// 事件流类型定义
interface BaseEvent {
  event: string;
  task_id: string;
  [key: string]: any;
}

interface MessageEvent extends BaseEvent {
  event: 'message';
  message_id: string;
  conversation_id: string;
  answer: string;
  created_at: number;
}

interface MessageEndEvent extends BaseEvent {
  event: 'message_end';
  id: string;
  conversation_id: string;
  metadata: {
    usage: Usage;
    retriever_resources: RetrieverResource[];
  };
}

interface WorkflowStartedEvent extends BaseEvent {
  event: 'workflow_started';
  workflow_run_id: string;
  data: {
    id: string;
    workflow_id: string;
    created_at: number;
  };
}

interface NodeStartedEvent extends BaseEvent {
  event: 'node_started';
  workflow_run_id: string;
  data: {
    id: string;
    node_id: string;
    node_type: string;
    title: string;
    index: number;
    predecessor_node_id: string;
    inputs: Record<string, any>;
    created_at: number;
  };
}

interface NodeFinishedEvent extends BaseEvent {
  event: 'node_finished';
  workflow_run_id: string;
  data: {
    id: string;
    node_id: string;
    index: number;
    predecessor_node_id?: string;
    inputs: Record<string, any>;
    process_data?: any;
    outputs?: any;
    status: 'running' | 'succeeded' | 'failed' | 'stopped';
    error?: string;
    elapsed_time?: number;
    execution_metadata: {
      total_tokens?: number;
      total_price?: number;
      currency?: string;
    };
    created_at: number;
  };
}

interface WorkflowFinishedEvent extends BaseEvent {
  event: 'workflow_finished';
  workflow_run_id: string;
  data: {
    id: string;
    workflow_id: string;
    status: 'running' | 'succeeded' | 'failed' | 'stopped';
    outputs?: any;
    error?: string;
    elapsed_time?: number;
    total_tokens?: number;
    total_steps: number;
    created_at: number;
    finished_at: number;
  };
}

interface ErrorEvent extends BaseEvent {
  event: 'error';
  message_id: string;
  status: number;
  code: string;
  message: string;
}

type StreamEvent = 
  | MessageEvent
  | MessageEndEvent
  | WorkflowStartedEvent
  | NodeStartedEvent
  | NodeFinishedEvent
  | WorkflowFinishedEvent
  | ErrorEvent;

最佳实践建议

1. 错误处理

复制代码
class ChatAPIError extends Error {
  constructor(
    public status: number,
    public code: string,
    message: string
  ) {
    super(message);
    this.name = 'ChatAPIError';
  }
}

async function handleAPIRequest<T>(request: Promise<Response>): Promise<T> {
  try {
    const response = await request;
    if (!response.ok) {
      let errorData;
      try {
        errorData = await response.json();
      } catch {
        errorData = { message: response.statusText };
      }
      throw new ChatAPIError(
        response.status,
        errorData.code || 'unknown',
        errorData.message || `HTTP ${response.status}`
      );
    }
    return response.json();
  } catch (error) {
    if (error instanceof ChatAPIError) {
      throw error;
    }
    throw new ChatAPIError(0, 'network_error', error.message);
  }
}

2. 流式响应处理工具类

复制代码
class StreamHandler {
  private controller: AbortController;
  private reader: ReadableStreamDefaultReader<Uint8Array> | null = null;

  constructor() {
    this.controller = new AbortController();
  }

  async processStream(
    url: string, 
    options: RequestInit,
    callbacks: {
      onMessage?: (text: string) => void;
      onWorkflowStart?: (data: any) => void;
      onWorkflowEnd?: (data: any) => void;
      onError?: (error: any) => void;
      onComplete?: (metadata: any) => void;
    }
  ): Promise<void> {
    try {
      const response = await fetch(url, {
        ...options,
        signal: this.controller.signal,
      });

      if (!response.body) {
        throw new Error('No response body');
      }

      this.reader = response.body.getReader();
      const decoder = new TextDecoder();
      let buffer = '';

      while (true) {
        const { done, value } = await this.reader.read();
        if (done) break;

        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split('\n\n');
        
        // 保留最后一行(可能是不完整的)
        buffer = lines.pop() || '';

        for (const line of lines) {
          if (line.startsWith('data: ')) {
            const data = line.substring(6);
            if (data === '[DONE]') continue;
            
            try {
              const event = JSON.parse(data);
              this.handleEvent(event, callbacks);
            } catch (e) {
              console.warn('Failed to parse event:', e, 'data:', data);
            }
          }
        }
      }
    } catch (error) {
      if (error.name === 'AbortError') {
        console.log('Stream aborted');
      } else {
        callbacks.onError?.(error);
      }
    } finally {
      this.cleanup();
    }
  }

  private handleEvent(event: any, callbacks: any) {
    switch (event.event) {
      case 'message':
        callbacks.onMessage?.(event.answer);
        break;
      case 'workflow_started':
        callbacks.onWorkflowStart?.(event.data);
        break;
      case 'workflow_finished':
        callbacks.onWorkflowEnd?.(event.data);
        break;
      case 'message_end':
        callbacks.onComplete?.(event.metadata);
        break;
      case 'error':
        callbacks.onError?.(new Error(event.message));
        break;
    }
  }

  abort() {
    this.controller.abort();
    if (this.reader) {
      this.reader.cancel();
    }
  }

  private cleanup() {
    this.reader = null;
  }
}

3. 会话管理类

复制代码
class ChatSession {
  private conversationId: string | null = null;
  private userId: string;
  private apiKey: string;
  private baseUrl: string;

  constructor(userId: string, apiKey: string, baseUrl: string = 'http://aiagent.ygwl.net/v1') {
    this.userId = userId;
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
  }

  async sendMessage(
    query: string, 
    options: {
      inputs?: Record<string, any>;
      files?: ChatFile[];
      workflowId?: string;
      responseMode?: 'streaming' | 'blocking';
      onStream?: (chunk: string) => void;
    } = {}
  ): Promise<string> {
    const responseMode = options.responseMode || 'streaming';
    const payload = {
      query,
      inputs: options.inputs || {},
      response_mode: responseMode,
      user: this.userId,
      conversation_id: this.conversationId || '',
      files: options.files || [],
      workflow_id: options.workflowId,
    };

    if (responseMode === 'streaming') {
      return this.sendStreamingMessage(payload, options.onStream);
    } else {
      return this.sendBlockingMessage(payload);
    }
  }

  private async sendStreamingMessage(payload: any, onStream?: (chunk: string) => void): Promise<string> {
    const streamHandler = new StreamHandler();
    let fullResponse = '';

    await streamHandler.processStream(
      `${this.baseUrl}/chat-messages`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
      },
      {
        onMessage: (chunk: string) => {
          fullResponse += chunk;
          onStream?.(chunk);
        },
        onComplete: (metadata: any) => {
          if (metadata && metadata.conversation_id) {
            this.conversationId = metadata.conversation_id;
          }
        },
        onError: (error: any) => {
          throw error;
        },
      }
    );

    return fullResponse;
  }

  private async sendBlockingMessage(payload: any): Promise<string> {
    const response = await fetch(`${this.baseUrl}/chat-messages`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(payload),
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const data = await response.json();
    this.conversationId = data.conversation_id;
    return data.answer;
  }

  getConversationId(): string | null {
    return this.conversationId;
  }

  setConversationId(id: string) {
    this.conversationId = id;
  }

  async getHistory(): Promise<any> {
    if (!this.conversationId) {
      throw new Error('No active conversation');
    }

    const response = await fetch(
      `${this.baseUrl}/messages?user=${this.userId}&conversation_id=${this.conversationId}`,
      {
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
        },
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    return response.json();
  }

  async clearConversation(): Promise<void> {
    if (this.conversationId) {
      await fetch(`${this.baseUrl}/conversations/${this.conversationId}`, {
        method: 'DELETE',
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          user: this.userId,
        }),
      });
    }
    this.conversationId = null;
  }
}

常见问题

1. 如何开始一个新会话?

不传递 conversation_id 参数或传递空字符串即可开始一个新会话。

2. 如何继续之前的会话?

在请求中传递之前获取到的 conversation_id

3. 流式模式和阻塞模式如何选择?

  • 流式模式:适合需要实时显示生成过程的场景,用户体验更好,推荐使用

  • 阻塞模式:适合简单请求,不需要实时显示的场景

4. 如何处理大文件上传?

  • 检查文件大小限制:文档15MB,图片10MB,音频50MB,视频100MB

  • 使用分片上传(如果支持)

  • 提供上传进度提示

5. 如何确保API安全性?

  • API Key 必须存储在服务端

  • 使用 HTTPS 协议

  • 实现请求频率限制

  • 记录和监控 API 使用情况

6. 如何调试API调用?

  1. 检查 HTTP 状态码和错误响应

  2. 使用 trace_id 进行链路追踪

  3. 记录请求和响应日志

  4. 使用开发者工具查看网络请求


更新日志

版本 日期 更新内容
1.0 2024-01-07 初始版本,包含完整的 API 文档和 TypeScript 示例

本 API 文档提供了完整的接口说明、参数定义、响应格式和 TypeScript 示例代码。开发者可以根据需要选择合适的接口进行集成开发。如有问题,请参考错误码说明或联系技术支持。

相关推荐
_codemonster2 分钟前
计算机视觉入门到实战系列(六)边缘检测sobel算子
人工智能·计算机视觉
杀生丸学AI2 分钟前
【平面重建】3D高斯平面:混合2D/3D光场重建(NeurIPS2025)
人工智能·平面·3d·大模型·aigc·高斯泼溅·空间智能
九河_3 分钟前
四元数 --> 双四元数
人工智能·四元数·双四元数
Gofarlic_oms14 分钟前
从手动统计到自动化:企业AutoCAD许可管理进化史
大数据·运维·网络·人工智能·微服务·自动化
叫我:松哥5 分钟前
基于 Flask 框架开发的在线学习平台,集成人工智能技术,提供分类练习、随机练习、智能推荐等多种学习模式
人工智能·后端·python·学习·信息可视化·flask·推荐算法
LJ97951119 分钟前
一键宣发时代:Infoseek如何重构企业传播链路
人工智能
东心十13 分钟前
AI学习环境安装
人工智能·学习
晟诺数字人14 分钟前
数字人短视频引流获客攻略
大数据·人工智能
热爱专研AI的学妹14 分钟前
2026世界杯观赛工具自制指南:实时比分推送机器人搭建思路
开发语言·人工智能·python·业界资讯
大力财经18 分钟前
耐士劳发布首款融合星基RTK、AI视觉与激光雷达割草机器人
人工智能·机器人