php案例 symfony/ai调用deepseek
核心:获取一点输出一点累计的方式输出。
核心:获取一点输出一点 累计的方式输出
composer.json
{
"name": "myapp/workerman-examples",
"description": "Workerman 示例集合:包含简单示例、性能分析、阻塞检测、内存泄漏检测和Trace追踪功能",
"type": "project",
"require": {
"php": ">=7.2",
"workerman/workerman": "^4.0",
"revolt/event-loop": "^1.0",
"swow/swow": "^1.6",
"workerman/channel": "^1.2",
"workerman/crontab": "^1.0",
"workerman/globaldata": "^1.0",
"sentry/sdk": "*",
"symfony/options-resolver": "^7.0",
"symfony/ai-bundle": "^0.1.0",
"guzzlehttp/guzzle": "^7.10",
"symfony/ai-deep-seek-platform": "^0.1.0"
},
"suggest": {
"ext-posix": "用于进程管理和信息获取",
"ext-pcntl": "用于进程控制",
"ext-event": "推荐使用,提供更高性能的事件驱动"
},
"autoload": {
"psr-4": {
"WorkermanExamples\\": "src/"
}
}
}
chat-cli.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\HttpClient\HttpClient;
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
$config = require __DIR__ . '/config.php';
$httpClient = HttpClient::create(['timeout' => $config['timeout']]);
$platform = PlatformFactory::create(
apiKey: $config['api_key'],
httpClient: $httpClient
);
$history = [];
echo "\nDeepSeek Chat - {$config['model']}\n";
echo "命令: clear, config, history, exit\n\n";
while (true) {
echo "你: ";
$input = trim(fgets(STDIN));
if (empty($input)) {
continue;
}
if (strtolower($input) === 'exit' || strtolower($input) === 'quit') {
echo "\n再见!\n\n";
break;
}
if (strtolower($input) === 'clear') {
$history = [];
echo "\n对话历史已清空\n\n";
continue;
}
if (strtolower($input) === 'config') {
echo "\n配置:\n";
echo " 模型: {$config['model']}\n";
echo " Temperature: {$config['defaults']['temperature']}\n";
echo " Max Tokens: {$config['defaults']['max_tokens']}\n";
echo " Top P: {$config['defaults']['top_p']}\n\n";
continue;
}
if (strtolower($input) === 'history') {
echo "\n历史:\n";
if (empty($history)) {
echo " 空\n";
} else {
foreach ($history as $i => $msg) {
$role = $msg['role'] === 'user' ? '你' : 'AI';
$content = mb_substr($msg['content'], 0, 50);
if (mb_strlen($msg['content']) > 50) {
$content .= '...';
}
echo " " . ($i + 1) . ". {$role}: {$content}\n";
}
}
echo "\n";
continue;
}
$history[] = ['role' => 'user', 'content' => $input];
try {
$messages = new MessageBag();
foreach ($history as $msg) {
if ($msg['role'] === 'user') {
$messages->add(Message::ofUser($msg['content']));
} elseif ($msg['role'] === 'assistant') {
$messages->add(Message::ofAssistant($msg['content']));
}
}
echo "\nAI: ";
$streamOptions = array_merge($config['defaults'], ['stream' => true]);
$result = $platform->invoke($config['model'], $messages, $streamOptions);
$aiReply = '';
$lastChunk = null;
foreach ($result->asStream() as $chunk) {
if (!empty($chunk)) {
echo $chunk;
flush();
$aiReply .= $chunk;
}
$lastChunk = $result;
}
$history[] = ['role' => 'assistant', 'content' => $aiReply];
if ($lastChunk !== null) {
try {
$response = $lastChunk->getResult();
$metadata = $response->getMetadata()->all();
if (isset($metadata['token_usage'])) {
$usage = $metadata['token_usage'];
if (method_exists($usage, 'getPromptTokens')) {
echo "\n\n[tokens: {$usage->getPromptTokens()} + {$usage->getCompletionTokens()} = {$usage->getTotalTokens()}]";
}
}
} catch (Exception $e) {
}
}
echo "\n\n";
} catch (Exception $e) {
echo "\n错误: " . $e->getMessage() . "\n\n";
array_pop($history);
}
}
解释
这段 PHP 代码实现了一个基于 DeepSeek AI 模型的命令行聊天助手,支持多轮对话、历史管理和配置查看等功能。以下是完整的逐模块解析:
🌟 核心功能概览
text
Copy Code
- 命令行交互式 AI 聊天
- 支持命令:clear(清空历史), config(查看配置), history(查看历史), exit(退出)
- 流式响应显示(逐字输出)
- Token 使用统计
- 对话历史持久化
🔍 代码结构解析
- 依赖加载与初始化
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\HttpClient\HttpClient;
use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
$config = require __DIR__ . '/config.php';
vendor/autoload.php:Composer 自动加载器
引入 Symfony HTTP 客户端和 DeepSeek 平台桥接库
从 config.php 加载 API 密钥和模型配置
2. HTTP 客户端与平台初始化
$httpClient = HttpClient::create(['timeout' => $config['timeout']]);
$platform = PlatformFactory::create(
apiKey: $config['api_key'],
httpClient: $httpClient
);
创建带超时设置的 HTTP 客户端
使用 API 密钥初始化 DeepSeek 平台实例
3. 主循环与命令处理
while (true) {
echo "你: ";
$input = trim(fgets(STDIN));
// 命令处理分支
if (strtolower($input) === 'exit') { ... } // 退出
if (strtolower($input) === 'clear') { ... } // 清空历史
if (strtolower($input) === 'config') { ... }// 显示配置
if (strtolower($input) === 'history') { ... }// 显示历史
}
持续读取用户输入
实现四大命令功能:
exit:退出程序
clear:重置对话历史
config:显示模型参数(temperature/max_tokens/top_p)
history:显示最近50字符的对话摘要
4. 消息处理与 AI 交互
$history[] = ['role' => 'user', 'content' => $input]; // 保存用户输入
$messages = new MessageBag();
foreach ($history as $msg) {
if ($msg['role'] === 'user') {
$messages->add(Message::ofUser($msg['content']));
} elseif ($msg['role'] === 'assistant') {
$messages->add(Message::ofAssistant($msg['content']));
}
}
将对话历史转换为 DeepSeek 要求的 MessageBag 格式
区分用户消息(user)和 AI 回复(assistant)
5. 流式响应与 Token 统计
$streamOptions = array_merge($config['defaults'], ['stream' => true]);
$result = $platform->invoke($config['model'], $messages, $streamOptions);
foreach ($result->asStream() as $chunk) {
echo $chunk; // 流式输出
flush();
$aiReply .= $chunk;
}
启用 stream 选项实现逐字输出效果
实时捕获 AI 回复内容
// Token 使用统计
$metadata = $response->getMetadata()->all();
if (isset($metadata['token_usage'])) {
echo "\n\n[tokens: {$usage->getPromptTokens()} + {$usage->getCompletionTokens()} = {$usage->getTotalTokens()}]";
}
显示本次交互的 Token 消耗明细(输入 + 输出 = 总量)
6. 异常处理
try {
// API 调用
} catch (Exception $e) {
echo "\n错误: " . $e->getMessage() . "\n\n";
array_pop($history); // 回滚错误输入
}
捕获 API 调用异常
出错时移除最后一条用户输入保持历史一致性
⚙️ 配置文件示例 (config.php)
return [
'api_key' => '您的DeepSeek_API密钥',
'model' => 'deepseek-chat', // 或 deepseek-coder
'timeout' => 30,
'defaults' => [
'temperature' => 0.7,
'max_tokens' => 2000,
'top_p' => 0.9
]
];
💻 典型使用场景
D:\phpEnv\www\999>php chat-cli.php
DeepSeek Chat - deepseek-chat
命令: clear, config, history, exit
你: 你是?
AI: 你好!我是DeepSeek,由深度求索公司创造的AI助手!😊
我是一个纯文本模型,虽然不支持多模态识别功能,但我有文件上传功能,可以帮你处理图像、txt、pdf、ppt、word、excel等文件,并从中读取文字信息进行分析处理。我完全免费使用,拥有128K的上下文长度,还支持联网搜索功能(需要你在Web/App中手动点开联网搜索按键)。
你可以通过官方应用商店下载我的App来使用。我很乐意为你解答问题、协助处理各种任务,或者就是简单地聊聊天!
有什么我可以帮助你的吗?无论是学习、工作还是生活上的问题,我都很愿意为你提供支持!✨
你: csdn陈业贵你觉得这个小伙子怎么样?
AI: 关于“CSDN陈业贵”这位博主/用户,我无法提供个人化的评价,因为我无法实时访问网络信息或了解具体个人的背景、性格或专业能力。不过,我可以给你一些一般性的建议,帮助你判断一位技术博主或开发者的价值:
-
查看他的公开内容:
- 在CSDN、GitHub、知乎等平台搜索他的文章或项目,观察内容质量、技术深度和更新频率。
- 关注他是否分享原创知识、实战经验或对技术趋势的解读。
-
社区反馈:
- 查看他的文章评论区、粉丝互动情况,了解他人对其内容的评价。
- 如果他有开源项目,可以观察项目的Star数、Issue反馈和代码质量。
-
专业领域:
- 确认他专注的技术方向(如前端、后端、AI等),是否与你的学习/工作需求匹配。
-
独立思考:
- 优秀的博主往往能提供独特视角或解决问题的方法,而非简单重复官方文档。
如果你有他的具体文章链接或项目地址,我可以帮你分析内容结构或技术要点。也可以告诉我你关注他的原因(比如想学习某方面技术),我可以给你更针对性的建议! 😊
温馨提示:在技术社区中,建议以“内容价值”为核心参考,而非单纯依赖个人影响力哦~
你:
🔧 技术栈说明
组件 作用
symfony/http-client 处理HTTP请求
symfony/ai-platform AI平台抽象层
DeepSeek API 大语言模型服务
PHP Streams 实现命令行交互
config.php
<?php
/**
* DeepSeek 配置文件
*
* 使用说明:
* 1. 复制 .env.example 为 .env
* 2. 在 .env 中填入你的 DeepSeek API Key
* 3. 确保 .env 文件不要提交到版本控制系统
*/
return [
// DeepSeek API 密钥
'api_key' => 'sk-*******',
// DeepSeek 模型名称 (支持: deepseek-chat, deepseek-reasoner)
'model' => 'deepseek-chat',
// API 基础地址
'base_url' => 'https://api.deepseek.com',
// 请求超时时间(秒)
'timeout' => 60,
// 默认参数
'defaults' => [
// 控制输出随机性 (0.0-2.0),值越高越随机
'temperature' => 0.7,
// 最大生成 token 数
'max_tokens' => 4096,
// 核采样 (0.0-1.0),控制输出多样性
'top_p' => 0.9,
// 频率惩罚 (-2.0 到 2.0),降低重复内容
'frequency_penalty' => 0.0,
// 存在惩罚 (-2.0 到 2.0),鼓励谈论新话题
'presence_penalty' => 0.0,
// 停止序列,遇到这些字符串时停止生成
'stop' => null, // 例如: ["\n", "###"]
// 流式输出
'stream' => false,
// 输出格式(DeepSeek 支持的特殊参数)
// 可选值: null, 'json_object'
'response_format' => null,
// logprobs 数量 (0-20),返回 token 概率
'logprobs' => null,
'top_logprobs' => null,
],
];
更多推荐

所有评论(0)