Dify PHP SDK 实战:在 PHP 应用中集成 Dify 聊天、补全与工作流 API
2026/9/13 16:03:10 网站建设 项目流程

Dify PHP SDK 实战:在 PHP 应用中集成 Dify 聊天、补全与工作流 API

【免费下载链接】difyBuild Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.项目地址: https://gitcode.com/GitHub_Trending/di/dify

Dify 在仓库中提供了官方 PHP SDK(sdks/php-client/),它基于 Guzzle 封装了 Dify Service API(/v1)的核心能力:聊天应用(chat-messages)、补全应用(completion-messages)、工作流运行(workflows/run)、文件上传、语音转文字等接口。读完本文,你将掌握 SDK 的安装配置方式、全部可用方法的参数含义,并能结合服务端源码理解每个方法实际调用的 HTTP 端点与返回处理细节。

环境要求与安装方式

根据 sdks/php-client/README.md 的说明,SDK 的运行环境要求非常轻量:

  • PHP 7.2 或更高版本;
  • Guzzle HTTP 客户端库(guzzlehttp/guzzle ^7.9)。

仓库中的 composer.json 也印证了这一点:

{ "require": { "php": ">=7.2", "guzzlehttp/guzzle": "^7.9" }, "autoload": { "files": ["dify-client.php"] } }

SDK 本身不是一个通过 Packagist 发布的 composer 包,而是以“单文件客户端 + Composer 自动加载”的方式集成。README 给出了两种使用路径:

  1. 直接体验示例:进入sdks/php-client/目录执行composer install,即可用目录内的composer.lock锁定依赖;
  2. 集成到已有项目:把 dify-client.php 复制到自己项目中,然后在项目的composer.json中合并如下配置,再运行composer install && composer dump-autoload
{ "require": { "guzzlehttp/guzzle": "^7.9" }, "autoload": { "files": ["path/to/dify-client.php"] } }

需要注意 README 中的一条提示:Guzzle 并未在 7.9 之外的版本上做过测试,^7.9是已验证的版本基线,使用其他版本“可以试试但不保证”。autoload.files机制会把dify-client.php中的 4 个类(DifyClientCompletionClientChatClientWorkflowClient)在 Composer 自动加载时直接引入,因此无需手动require该文件。

SDK 类结构与请求机制

整个 SDK 只有一个源文件 dify-client.php,采用“一个基类 + 三个按应用类型划分的子类”的结构,这与 Dify 服务端的三种应用形态(聊天、文本生成、工作流)一一对应。

基类 DifyClient:认证与请求封装

从 dify-client.php#L5-L31 的源码看,构造函数的逻辑是:

public function __construct($api_key, $base_url = null) { $this->api_key = $api_key; $this->base_url = $base_url ?? 'https://api.dify.ai/v1/'; $this->client = new Client([ 'base_uri' => $this->base_url, 'headers' => [ 'Authorization' => 'Bearer ' . $this->api_key, 'Content-Type' => 'application/json', ], ]); }

这里有两个关键点:

  • 默认服务端点是 Dify 云服务https://api.dify.ai/v1/。如果你的 Dify 是自部署(self-hosted)实例,必须通过第二个参数$base_url传入自己实例的地址(形如https://your-dify.example.com/v1/),这一点 README 虽未展开,但从构造函数签名可以直接确认;
  • 所有请求统一携带Authorization: Bearer <api_key>请求头,这里的 API Key 就是 Dify 控制台为应用发布的 API Token。

所有网络调用收敛到send_request()方法(dify-client.php#L22-L31):

protected function send_request($method, $endpoint, $data = null, $params = null, $stream = false) { $options = [ 'json' => $data, // 请求体(JSON) 'query' => $params, // URL 查询参数 'stream' => $stream, // 是否流式 ]; $response = $this->client->request($method, $endpoint, $options); return $response; }

值得注意的设计是:SDK不解析响应体,而是把 Guzzle 的Psr\Http\Message\ResponseInterface原样返回,由调用方自己json_decode($response->getBody(), true)处理。这给了使用方最大的灵活性,但也意味着错误处理需要自己判断 HTTP 状态码。

子类与端点映射

从源码看,三个子类各自封装的端点与服务端 api/controllers/service_api/ 下的路由完全对应:

客户端类方法服务端端点服务端实现
DifyClientmessage_feedback()POST /messages/{message_id}/feedbacksmessage.py
DifyClientget_application_parameters()GET /parametersapp.py
DifyClientfile_upload()POST /files/uploadfile.py
DifyClienttext_to_audio()POST /text-to-audioaudio.py
DifyClientget_meta()GET /metaapp.py
CompletionClientcreate_completion_message()POST /completion-messagescompletion.py
ChatClientcreate_chat_message()POST /chat-messagescompletion.py 所在应用模块
ChatClientget_suggestions()GET /messages/{message_id}/suggestedmessage.py#L226
ChatClientstop_message()POST /chat-messages/{task_id}/stop
ChatClientget_conversations()GET /conversationsconversation.py#L159
ChatClientget_conversation_messages()GET /messagesmessage.py
ChatClientrename_conversation()PATCH /conversations/{conversation_id}conversation.py
ChatClientdelete_conversation()DELETE /conversations/{conversation_id}conversation.py
ChatClientaudio_to_text()POST /audio-to-textaudio.py#L48
WorkflowClientrun()POST /workflows/runworkflow.py#L287
WorkflowClientstop()POST /workflows/tasks/{task_id}/stopworkflow.py

服务端这些路由挂载在 Blueprintservice_api上,其url_prefix="/v1"(见 api/controllers/service_api/init.py#L6),这与 SDK 默认 base_url 末尾的/v1/相互印证——SDK 的每个短端点(如chat-messages)最终都会拼到/v1/chat-messages

快速上手:README 官方示例全解

以下示例完整继承自 sdks/php-client/README.md,并补充了参数说明。

基本初始化

<?php require 'vendor/autoload.php'; $apiKey = 'your-api-key-here'; // 替换为 Dify 控制台中应用的真实 API Key $difyClient = new DifyClient($apiKey);

补全应用(Completion)

// 创建补全客户端 $completionClient = new CompletionClient($apiKey); $response = $completionClient->create_completion_message( array("query" => "Who are you?"), // $inputs:应用启动所需的输入变量 "blocking", // $response_mode:blocking 或 streaming "user_id" // $user:终端用户标识,必填 );

对照 dify-client.php#L96-L104 的实现,该方法把参数组装为inputs/response_mode/user/files四个字段,并且当$response_mode === 'streaming'时会自动开启 Guzzle 的流式模式(stream => true),这样 SSE 流可以边接收边处理,避免一次性缓冲整个响应。

聊天应用(Chat)

// 创建聊天客户端 $chatClient = new ChatClient($apiKey); $response = $chatClient->create_chat_message( array(), // $inputs "Who are you?", // $query:用户问题 "user_id", // $user "blocking", // $response_mode(默认 blocking) $conversation_id // $conversation_id:首轮对话传 null,之后传上轮返回的会话 ID );

从 dify-client.php#L108-L121 的实现可以看到,$conversation_id只有在非空时才会被加入请求体——这与服务端“首轮不带会话 ID 新建会话、后续轮次带上以延续上下文”的协议一致。

多模态:附带图片/文件提问(Vision)

SDK 支持通过files参数传入文件描述数组,两种transfer_method

// 方式一:远程 URL(图片直接以 URL 提供) $fileForVision = [ [ "type" => "image", "transfer_method" => "remote_url", "url" => "your_image_url" ] ]; // 方式二:本地文件(需先通过 file_upload() 上传,拿到文件 ID) // $fileForVision = [ // [ // "type" => "image", // "transfer_method" => "local_file", // "url" => "your_file_id" // 实际填上传接口返回的 id // ] // ]; // 补全应用 + 视觉模型(如 gpt-4-vision) $response = $completionClient->create_completion_message( array("query" => "Describe this image."), "blocking", "user_id", $fileForVision ); // 聊天应用 + 视觉模型 $response = $chatClient->create_chat_message( array(), "Describe this image.", "user_id", "blocking", $conversation_id, $fileForVision );

文件上传与响应解析

// File Upload:以 multipart/form-data 上传,一次一个文件 $fileForUpload = [ [ 'tmp_name' => '/path/to/file/filename.jpg', // 服务器上的本地文件路径 'name' => 'filename.jpg' // 提交给 API 的文件名 ] ]; $response = $difyClient->file_upload("user_id", $fileForUpload); $result = json_decode($response->getBody(), true); echo 'upload_file_id: ' . $result['id']; // 返回的 id 即 local_file 方式引用的文件标识

SDK 的file_upload()(dify-client.php#L46-L73)内部通过prepareMultipart()$data(如user字段)与文件流拼装为 Guzzle 的 multipart 结构,每个文件的字段名固定为file

服务端对该接口的约束可以在 api/controllers/service_api/app/file.py 中逐条确认:

  • 请求体必须包含file字段,否则返回 400no_file_uploaded
  • 一次只允许上传一个文件,否则 400too_many_files
  • 文件必须带文件名,且扩展名不在安全黑名单内(分别对应filename_not_exists_errorfile_extension_blocked);
  • 超过大小限制返回 413file_too_large,类型不允许返回 415unsupported_file_type

成功时返回 201 与文件对象(含idnamesizemime_type等字段),该id正是上面local_file引用方式中要填的值。

应用参数与消息反馈

// 获取应用的参数配置(应用定义的输入变量、建议问题等) $response = $difyClient->get_application_parameters("user_id"); // 对某条消息提交评分反馈(rating 常见取值为 like / dislike,以 API 约定为准) $response = $difyClient->message_feedback($message_id, $rating, "user_id");

message_feedback()对应服务端POST /messages/{message_id}/feedbacks,这是 Dify 在控制台中查看“消息评分统计”的数据来源。

会话管理与更多方法

README 末尾列出了“Other available methods”,源码中它们的具体签名如下,可一并纳入你的业务封装:

// 获取会话列表:user 必填;first_id/limit/pinned 用于游标分页与置顶过滤 $chatClient->get_conversations($user, $first_id, $limit, $pinned); // 获取会话下的消息列表:conversation_id 可选(不传则跨会话按 user 查询) $chatClient->get_conversation_messages($user, $conversation_id, $first_id, $limit); // 重命名会话:auto_generate 为 true 时由系统自动根据内容生成标题 $chatClient->rename_conversation($conversation_id, $name, $auto_generate, $user); // 删除会话 $chatClient->delete_conversation($conversation_id, $user); // 获取某条消息后的建议追问(应用需开启 suggested questions) $chatClient->get_suggestions($message_id, $user); // 停止一个进行中的流式任务(传入该任务的 task_id) $chatClient->stop_message($task_id, $user);

从源码结构看,get_conversations()get_conversation_messages()采用first_id + limit的游标式分页参数,与服务端 conversation.py#L159-L224 中返回has_more+ 游标的分页响应结构相匹配;rename_conversation()实际发送PATCH方法且请求体携带auto_generate标志。

此外还有两个在 README 示例中未展示、但源码已实现的能力:

  • 工作流应用WorkflowClient->run($inputs, $response_mode, $user)调用POST /workflows/run触发工作流运行,WorkflowClient->stop($task_id, $user)可停止指定任务(dify-client.php#L189-L205);
  • 语音能力DifyClient->text_to_audio($text, $user, $streaming)ChatClient->audio_to_text($audio_file, $user)(multipart 上传音频)分别对应服务端的/text-to-audio/audio-to-text路由(api/controllers/service_api/app/audio.py);DifyClient->get_meta($user)则用于获取应用元信息。

实践注意事项

  1. API Key 与 base_url:Key 必须替换 README 中的占位符'your-api-key-here',且必须来自目标应用;自部署用户务必传第二个参数指定自己的/v1/基址,否则会请求到 Dify 云服务。
  2. user参数是全局必填项:从源码看几乎每个方法都要求传入user标识,服务端用它做终端用户维度的数据隔离(如“上传文件仅当前 end-user 可用”),生产环境建议映射为你系统内的稳定用户 ID。
  3. 流式模式response_modestreaming时,SDK 会自动打开 Guzzle stream,响应体是逐块到达的 SSE 流,需要按 Dify 流式事件协议逐行解析,而不能直接json_decode整个 body。
  4. 错误处理:SDK 不抛业务异常也不解析错误体,HTTP 4xx/5xx 时请自行检查$response->getStatusCode()并读取响应 JSON 中的code/message字段(例如文件上传的 400/413/415 各错误码见上文服务端说明)。
  5. 文件上传路径tmp_name参数名来自 PHP$_FILES的惯用结构,适合直接转发浏览器上传的临时文件,但生产代码建议校验文件存在性与类型后再上传。

小结

Dify 的 PHP SDK 以单文件、零额外依赖(除 Guzzle)的形态提供了对 Dify Service API 的完整覆盖:聊天、补全、工作流三大应用类型的运行入口,加上会话管理、消息反馈、建议追问、文件上传与语音互转等配套能力。它的价值在于把 Bearer 认证、multipart 组装、流式开关这些繁琐细节收敛进DifyClient基类,业务代码只需关注参数本身。结合服务端 api/controllers/service_api/ 下的路由实现,你可以进一步核对每个端点的请求/响应 schema,把 SDK 稳定地嵌入 PHP 业务系统中。该 SDK 以 MIT License 发布(见 sdks/php-client/README.md)。

【免费下载链接】difyBuild Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.项目地址: https://gitcode.com/GitHub_Trending/di/dify

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询