Dify Chat API 集成指南

Dify Chat API 实战集成教程,包含完整可用的 Node.js 和 curl 示例代码,帮助你快速构建聊天机器人和对话式 AI 应用。

本指南提供经过验证的可用代码示例,帮助你集成 Dify Chat App API。你将学习如何发送消息、处理流式响应以及管理对话会话。

前提条件

开始之前,你需要准备:

  • Dify API Key(在 Dify 应用设置中获取)
  • Base URL:https://api.dify.ai/v1(或你的私有化部署地址)

身份认证

所有 API 请求都需要通过 Authorization 请求头进行认证:

Authorization: Bearer {YOUR_API_KEY}

[!IMPORTANT] API Key 仅应存储在服务端。切勿在客户端代码或公开仓库中暴露密钥。


发送聊天消息

/chat-messages 接口是对话交互的核心 API。

阻塞模式

处理完成后返回完整响应。适合简单集成场景。

curl 示例:

curl -X POST 'https://api.dify.ai/v1/chat-messages' \
  --header 'Authorization: Bearer {YOUR_API_KEY}' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "inputs": {},
    "query": "什么是 Dify?",
    "response_mode": "blocking",
    "conversation_id": "",
    "user": "user-123"
  }'

Node.js 示例:

// sendMessage.js - 发送聊天消息(阻塞模式)
const DIFY_API_KEY = process.env.DIFY_API_KEY;
const DIFY_BASE_URL = 'https://api.dify.ai/v1';

async function sendMessage(query, conversationId = '', userId = 'user-123') {
  const response = await fetch(`${DIFY_BASE_URL}/chat-messages`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${DIFY_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      inputs: {},
      query,
      response_mode: 'blocking',
      conversation_id: conversationId,
      user: userId,
    }),
  });

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

  return await response.json();
}

// 使用示例
const result = await sendMessage('什么是 Dify?');
console.log('回答:', result.answer);
console.log('会话 ID:', result.conversation_id);

响应示例:

{
  "event": "message",
  "message_id": "9da23599-e713-473b-982c-4328d4f5c78a",
  "conversation_id": "45701982-8118-4bc5-8e9b-64562b4555f2",
  "answer": "Dify 是一个开源的 LLM 应用开发平台...",
  "created_at": 1705407629,
  "metadata": {
    "usage": {
      "total_tokens": 219,
      "total_price": "0.0001395"
    }
  }
}

流式模式(推荐)

通过 Server-Sent Events (SSE) 返回响应块,实现实时打字机效果。

curl 示例:

curl -N -X POST 'https://api.dify.ai/v1/chat-messages' \
  --header 'Authorization: Bearer {YOUR_API_KEY}' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "inputs": {},
    "query": "什么是 Dify?",
    "response_mode": "streaming",
    "conversation_id": "",
    "user": "user-123"
  }'

Node.js 示例:

// streamMessage.js - 流式响应处理
const DIFY_API_KEY = process.env.DIFY_API_KEY;
const DIFY_BASE_URL = 'https://api.dify.ai/v1';

async function streamMessage(query, conversationId = '', userId = 'user-123') {
  const response = await fetch(`${DIFY_BASE_URL}/chat-messages`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${DIFY_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      inputs: {},
      query,
      response_mode: 'streaming',
      conversation_id: conversationId,
      user: userId,
    }),
  });

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

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let fullAnswer = '';
  let convId = '';

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

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

    for (const line of lines) {
      try {
        const data = JSON.parse(line.slice(5));
        
        if (data.event === 'message') {
          // 实时输出每个字符块
          process.stdout.write(data.answer);
          fullAnswer += data.answer;
          convId = data.conversation_id;
        } else if (data.event === 'message_end') {
          console.log('\n--- 流式响应结束 ---');
          console.log('Token 使用量:', data.metadata?.usage);
        } else if (data.event === 'error') {
          throw new Error(data.message);
        }
      } catch (e) {
        // 忽略解析错误(可能是 ping 事件)
      }
    }
  }

  return { answer: fullAnswer, conversationId: convId };
}

// 使用示例
const result = await streamMessage('用简单的话解释一下人工智能');
console.log('完整回答:', result.answer);

获取会话列表

查询用户的对话会话列表。

curl 示例:

curl -X GET 'https://api.dify.ai/v1/conversations?user=user-123&limit=20' \
  --header 'Authorization: Bearer {YOUR_API_KEY}'

Node.js 示例:

// getConversations.js - 获取会话列表
async function getConversations(userId = 'user-123', limit = 20) {
  const params = new URLSearchParams({ user: userId, limit: limit.toString() });
  
  const response = await fetch(`${DIFY_BASE_URL}/conversations?${params}`, {
    headers: {
      'Authorization': `Bearer ${DIFY_API_KEY}`,
    },
  });

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

  return await response.json();
}

// 使用示例
const conversations = await getConversations();
console.log('会话列表:', conversations.data);

响应示例:

{
  "limit": 20,
  "has_more": false,
  "data": [
    {
      "id": "10799fb8-64f7-4296-bbf7-b42bfbe0ae54",
      "name": "新对话",
      "status": "normal",
      "created_at": 1679667915,
      "updated_at": 1679667915
    }
  ]
}

获取消息历史

查询指定会话的聊天记录。

curl 示例:

curl -X GET 'https://api.dify.ai/v1/messages?user=user-123&conversation_id={CONVERSATION_ID}&limit=20' \
  --header 'Authorization: Bearer {YOUR_API_KEY}'

Node.js 示例:

// getMessages.js - 获取消息历史
async function getMessages(conversationId, userId = 'user-123', limit = 20) {
  const params = new URLSearchParams({
    user: userId,
    conversation_id: conversationId,
    limit: limit.toString(),
  });

  const response = await fetch(`${DIFY_BASE_URL}/messages?${params}`, {
    headers: {
      'Authorization': `Bearer ${DIFY_API_KEY}`,
    },
  });

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

  return await response.json();
}

// 使用示例
const messages = await getMessages('your-conversation-id');
for (const msg of messages.data) {
  console.log(`问: ${msg.query}`);
  console.log(`答: ${msg.answer}\n`);
}

继续对话

传入上一条消息的 conversation_id 可保持对话上下文:

// 继续对话示例
let conversationId = '';

// 第一条消息
const first = await sendMessage('给我讲讲机器学习');
conversationId = first.conversation_id;

// 后续消息会记住上下文
const followUp = await sendMessage('它和深度学习有什么区别?', conversationId);
console.log(followUp.answer); // AI 会记得之前讨论的是机器学习

文件上传

对于需要文件输入(图片、文档)的应用,Dify 提供文件上传 API:

  1. 上传文件:使用 POST /files/upload 接口,Content-Type 为 multipart/form-data
  2. 引用文件:在聊天消息中使用返回的 upload_file_id

[!TIP] 文件上传主要用于支持视觉能力的模型(如 GPT-4V)来分析图片。支持的格式包括 PNG、JPG、JPEG、WEBP 和 GIF。

详细的文件上传实现,请参考 Dify 官方 API 文档


错误处理

常见错误码及处理方式:

状态码错误代码描述解决方案
400invalid_param参数无效检查请求体格式
400provider_quota_exceeded模型配额超限检查 API 额度
400model_currently_not_support模型不可用更换其他模型
404conversation_not_exists会话不存在开始新对话
500internal_server_error服务器错误延迟后重试

Node.js 错误处理示例:

// errorHandling.js - 错误处理示例
async function safeSendMessage(query, conversationId = '') {
  try {
    return await sendMessage(query, conversationId);
  } catch (error) {
    if (error.message.includes('429')) {
      console.log('请求频率超限,等待后重试...');
      await new Promise(r => setTimeout(r, 5000));
      return await sendMessage(query, conversationId);
    }
    
    if (error.message.includes('404')) {
      console.log('会话不存在,开始新对话...');
      return await sendMessage(query, '');
    }
    
    throw error;
  }
}

完整示例

以下是一个完整的 Node.js 聊天客户端:

// difyClient.js - 完整的 Dify Chat 客户端
class DifyClient {
  constructor(apiKey, baseUrl = 'https://api.dify.ai/v1') {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
  }

  async chat(query, conversationId = '', user = 'default-user', streaming = false) {
    const response = await fetch(`${this.baseUrl}/chat-messages`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        inputs: {},
        query,
        response_mode: streaming ? 'streaming' : 'blocking',
        conversation_id: conversationId,
        user,
      }),
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message || `HTTP ${response.status}`);
    }

    if (streaming) {
      return this._handleStream(response);
    }

    return await response.json();
  }

  async *_handleStream(response) {
    const reader = response.body.getReader();
    const decoder = new TextDecoder();

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

      const lines = decoder.decode(value).split('\n');
      for (const line of lines) {
        if (line.startsWith('data:')) {
          try {
            yield JSON.parse(line.slice(5));
          } catch (e) {}
        }
      }
    }
  }

  async getConversations(user = 'default-user', limit = 20) {
    const params = new URLSearchParams({ user, limit: String(limit) });
    const response = await fetch(`${this.baseUrl}/conversations?${params}`, {
      headers: { 'Authorization': `Bearer ${this.apiKey}` },
    });
    return await response.json();
  }

  async getMessages(conversationId, user = 'default-user', limit = 20) {
    const params = new URLSearchParams({ user, conversation_id: conversationId, limit: String(limit) });
    const response = await fetch(`${this.baseUrl}/messages?${params}`, {
      headers: { 'Authorization': `Bearer ${this.apiKey}` },
    });
    return await response.json();
  }
}

// 使用示例
const client = new DifyClient(process.env.DIFY_API_KEY);

// 阻塞模式
const result = await client.chat('你好!');
console.log(result.answer);

// 流式模式
for await (const chunk of await client.chat('给我讲个故事', '', 'user-1', true)) {
  if (chunk.event === 'message') {
    process.stdout.write(chunk.answer);
  }
}

下一步