工作流编排对话型应用 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_generate 为 true 实现异步生成标题 |
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_generate 为 true 时,该参数可不传 |
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 | 是 | 动作,只能是 enable 或 disable |
请求体参数
| 字段名 | 类型 | 必填 | 描述 |
|---|---|---|---|
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调用?
-
检查 HTTP 状态码和错误响应
-
使用
trace_id进行链路追踪 -
记录请求和响应日志
-
使用开发者工具查看网络请求
更新日志
| 版本 | 日期 | 更新内容 |
|---|---|---|
| 1.0 | 2024-01-07 | 初始版本,包含完整的 API 文档和 TypeScript 示例 |
本 API 文档提供了完整的接口说明、参数定义、响应格式和 TypeScript 示例代码。开发者可以根据需要选择合适的接口进行集成开发。如有问题,请参考错误码说明或联系技术支持。