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 示例代码。开发者可以根据需要选择合适的接口进行集成开发。如有问题,请参考错误码说明或联系技术支持。

相关推荐
宅小年1 分钟前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼16 分钟前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS24 分钟前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区2 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈2 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang2 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx
shengjk13 小时前
NanoClaw 深度剖析:一个"AI 原生"架构的个人助手是如何运转的?
人工智能
西门老铁5 小时前
🦞OpenClaw 让 MacMini 脱销了,而我拿出了6年陈的安卓机
人工智能
恋猫de小郭6 小时前
AI 可以让 WIFI 实现监控室内人体位置和姿态,无需摄像头?
前端·人工智能·ai编程