JienDa聊PHP:PHP 调用 DeepSeek API 完整指南:从入门到实战应用
本文介绍了使用PHP调用DeepSeek API的完整指南,涵盖从基础配置到实战应用的全流程。主要内容包括:DeepSeek API的功能特性与版本介绍、PHP环境准备与SDK安装、基础API调用类的实现(支持Guzzle和原生cURL两种方式)、错误处理机制以及性能优化策略。文章还提供了配置管理类示例代码,帮助开发者快速集成DeepSeek的强大AI能力到PHP应用中,适用于文本生成、代码补全等
PHP 调用 DeepSeek API 完整指南:从入门到实战应用
前言
在人工智能快速发展的今天,大型语言模型(LLM)已经成为开发者不可或缺的工具。DeepSeek 作为国内领先的 AI 大模型提供商,提供了强大的 API 接口供开发者调用。本文将详细介绍如何使用 PHP 语言与 DeepSeek API 进行交互,涵盖从基础概念到高级应用的完整知识体系。
无论您是刚接触 AI 开发的初学者,还是有一定经验的 PHP 开发者,本文都将为您提供全面而深入的指导。我们将从基础的环境配置开始,逐步深入到高级功能实现和性能优化,最后通过实际项目案例展示如何将 DeepSeek API 集成到 PHP 应用中。
目录
- DeepSeek API 概述
- 环境准备与配置
- 基础 API 调用
- 高级功能实现
- 错误处理与调试
- 性能优化策略
- 安全最佳实践
- 实战项目案例
- 常见问题解答
第一章 DeepSeek API 概述
1.1 DeepSeek 简介
DeepSeek 是一家专注于人工智能大模型研发的科技公司,其提供的 API 接口可以让开发者轻松集成先进的自然语言处理能力到自己的应用中。DeepSeek 模型具有以下特点:
- 强大的语言理解能力:能够准确理解复杂的自然语言查询
- 多领域知识覆盖:涵盖科技、文学、历史、编程等多个领域
- 代码生成能力:特别擅长生成高质量的编程代码
- 中文优化:对中文有很好的支持和优化
1.2 API 功能特性
DeepSeek API 提供了丰富的功能,主要包括:
- 文本补全:根据提示词生成连贯的文本内容
- 代码生成:根据描述生成各种语言的代码
- 对话系统:构建多轮对话应用
- 文本摘要:自动生成文本摘要
- 翻译功能:支持多语言间的翻译
1.3 API 版本与定价
DeepSeek 提供多个版本的 API,包括免费版和付费版。开发者可以根据自己的需求选择合适的版本。当前主要版本包括:
- DeepSeek-Chat:专注于对话场景
- DeepSeek-Coder:专注于代码生成
- DeepSeek-General:通用文本处理
第二章 环境准备与配置
2.1 系统要求
在开始使用 DeepSeek API 之前,确保您的开发环境满足以下要求:
- PHP 7.4 或更高版本
- 启用 cURL 扩展
- 启用 JSON 扩展
- 有效的 DeepSeek API 密钥
2.2 获取 API 密钥
要使用 DeepSeek API,首先需要注册账号并获取 API 密钥:
- 访问 DeepSeek 官方网站
- 注册开发者账号
- 进入控制台创建新的 API 密钥
- 记录并妥善保存您的 API 密钥
2.3 安装必要的依赖
虽然可以直接使用 PHP 的原生函数调用 API,但使用专门的 SDK 可以简化开发过程。以下是几种可选方案:
方案一:使用官方 SDK(如果提供)
composer require deepseek/sdk
方案二:使用 Guzzle HTTP 客户端
composer require guzzlehttp/guzzle
方案三:纯 PHP 实现
如果不想引入额外依赖,可以直接使用 PHP 内置函数。
2.4 基础配置类
让我们创建一个配置类来管理 API 设置:
<?php
class DeepSeekConfig
{
// API 端点
const API_BASE_URL = 'https://api.deepseek.com/v1';
// API 密钥(从环境变量获取)
private $apiKey;
// 默认模型
private $defaultModel = 'deepseek-chat';
// 超时设置(秒)
private $timeout = 30;
public function __construct()
{
$this->apiKey = getenv('DEEPSEEK_API_KEY');
if (!$this->apiKey) {
throw new Exception('DeepSeek API key not found in environment variables');
}
}
public function getApiKey()
{
return $this->apiKey;
}
public function getBaseUrl()
{
return self::API_BASE_URL;
}
public function getDefaultModel()
{
return $this->defaultModel;
}
public function getTimeout()
{
return $this->timeout;
}
public function setDefaultModel($model)
{
$this->defaultModel = $model;
return $this;
}
public function setTimeout($timeout)
{
$this->timeout = $timeout;
return $this;
}
}
第三章 基础 API 调用
3.1 创建基础客户端类
首先,我们创建一个基础的客户端类来处理 API 调用:
<?php
class DeepSeekClient
{
private $config;
private $httpClient;
public function __construct(DeepSeekConfig $config = null)
{
$this->config = $config ?: new DeepSeekConfig();
$this->httpClient = $this->createHttpClient();
}
private function createHttpClient()
{
// 检查是否安装了 Guzzle
if (class_exists('GuzzleHttp\Client')) {
return new GuzzleHttp\Client([
'base_uri' => $this->config->getBaseUrl(),
'timeout' => $this->config->getTimeout(),
'headers' => [
'Authorization' => 'Bearer ' . $this->config->getApiKey(),
'Content-Type' => 'application/json',
]
]);
}
// 如果不使用 Guzzle,返回 null,使用原生 cURL
return null;
}
/**
* 发送 API 请求
*/
public function sendRequest($endpoint, $data = [], $method = 'POST')
{
if ($this->httpClient) {
return $this->sendRequestWithGuzzle($endpoint, $data, $method);
} else {
return $this->sendRequestWithCurl($endpoint, $data, $method);
}
}
/**
* 使用 Guzzle 发送请求
*/
private function sendRequestWithGuzzle($endpoint, $data, $method)
{
try {
$options = [];
if ($method === 'POST') {
$options['json'] = $data;
}
$response = $this->httpClient->request($method, $endpoint, $options);
return json_decode($response->getBody(), true);
} catch (Exception $e) {
throw new DeepSeekException('API request failed: ' . $e->getMessage(), $e->getCode(), $e);
}
}
/**
* 使用 cURL 发送请求
*/
private function sendRequestWithCurl($endpoint, $data, $method)
{
$url = $this->config->getBaseUrl() . $endpoint;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, $this->config->getTimeout());
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $this->config->getApiKey(),
'Content-Type: application/json',
]);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new DeepSeekException('cURL error: ' . $error);
}
$result = json_decode($response, true);
if ($httpCode !== 200) {
$errorMessage = $result['error']['message'] ?? 'Unknown error';
throw new DeepSeekException("API error ($httpCode): $errorMessage", $httpCode);
}
return $result;
}
}
class DeepSeekException extends Exception {}
3.2 实现文本补全功能
文本补全是 DeepSeek API 最基本的功能,下面实现一个完整的文本补全类:
<?php
class DeepSeekCompletions extends DeepSeekClient
{
/**
* 创建文本补全
*/
public function createCompletion($prompt, $options = [])
{
$defaultOptions = [
'model' => $this->config->getDefaultModel(),
'prompt' => $prompt,
'max_tokens' => 1000,
'temperature' => 0.7,
'top_p' => 0.9,
'frequency_penalty' => 0,
'presence_penalty' => 0,
'stop' => null,
'stream' => false,
];
$finalOptions = array_merge($defaultOptions, $options);
// 移除空值
$finalOptions = array_filter($finalOptions, function($value) {
return $value !== null;
});
return $this->sendRequest('/completions', $finalOptions);
}
/**
* 流式输出(用于实时显示结果)
*/
public function createCompletionStream($prompt, $callback, $options = [])
{
$options['stream'] = true;
$options['prompt'] = $prompt;
$url = $this->config->getBaseUrl() . '/completions';
$headers = [
'Authorization: Bearer ' . $this->config->getApiKey(),
'Content-Type: application/json',
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => false,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($options),
CURLOPT_HTTPHEADER => $headers,
CURLOPT_WRITEFUNCTION => function($ch, $data) use ($callback) {
$lines = explode("\n", $data);
foreach ($lines as $line) {
$line = trim($line);
if (empty($line) || $line === 'data: [DONE]') {
continue;
}
if (strpos($line, 'data: ') === 0) {
$json = substr($line, 6);
$data = json_decode($json, true);
if (isset($data['choices'][0]['text'])) {
call_user_func($callback, $data['choices'][0]['text']);
}
}
}
return strlen($data);
}
]);
curl_exec($ch);
if (curl_error($ch)) {
throw new DeepSeekException('Stream error: ' . curl_error($ch));
}
curl_close($ch);
}
}
3.3 实现对话功能
对话功能是更高级的接口,支持多轮对话:
<?php
class DeepSeekChat extends DeepSeekClient
{
/**
* 创建对话
*/
public function createChatCompletion($messages, $options = [])
{
$defaultOptions = [
'model' => $this->config->getDefaultModel(),
'messages' => $messages,
'max_tokens' => 1000,
'temperature' => 0.7,
'top_p' => 0.9,
'frequency_penalty' => 0,
'presence_penalty' => 0,
'stop' => null,
'stream' => false,
];
$finalOptions = array_merge($defaultOptions, $options);
$finalOptions = array_filter($finalOptions, function($value) {
return $value !== null;
});
return $this->sendRequest('/chat/completions', $finalOptions);
}
/**
* 简化对话方法
*/
public function chat($message, $history = [], $options = [])
{
$messages = [];
// 添加历史消息
foreach ($history as $item) {
$messages[] = [
'role' => $item['role'],
'content' => $item['content']
];
}
// 添加当前消息
$messages[] = [
'role' => 'user',
'content' => $message
];
$options['messages'] = $messages;
return $this->createChatCompletion($messages, $options);
}
/**
* 对话会话管理类
*/
public function createSession()
{
return new ChatSession($this);
}
}
class ChatSession
{
private $chatClient;
private $messages = [];
public function __construct(DeepSeekChat $chatClient)
{
$this->chatClient = $chatClient;
}
public function send($message, $options = [])
{
// 添加用户消息
$this->messages[] = [
'role' => 'user',
'content' => $message
];
// 调用 API
$response = $this->chatClient->createChatCompletion($this->messages, $options);
// 添加助手回复
$assistantMessage = $response['choices'][0]['message']['content'];
$this->messages[] = [
'role' => 'assistant',
'content' => $assistantMessage
];
return $assistantMessage;
}
public function getMessages()
{
return $this->messages;
}
public function clear()
{
$this->messages = [];
}
}
3.4 基础使用示例
下面是一个完整的使用示例:
<?php
require_once 'DeepSeekConfig.php';
require_once 'DeepSeekClient.php';
require_once 'DeepSeekCompletions.php';
require_once 'DeepSeekChat.php';
// 设置 API 密钥(实际使用时应该从环境变量获取)
putenv('DEEPSEEK_API_KEY=your_api_key_here');
try {
// 创建聊天客户端
$chatClient = new DeepSeekChat();
// 简单对话
$response = $chatClient->chat('你好,请介绍一下 PHP 语言');
echo "回复: " . $response['choices'][0]['message']['content'] . "\n";
// 使用会话管理
$session = $chatClient->createSession();
$session->send('什么是面向对象编程?');
$reply = $session->send('能用 PHP 举个例子吗?');
echo "第二次回复: " . $reply . "\n";
// 查看完整对话历史
print_r($session->getMessages());
} catch (DeepSeekException $e) {
echo "错误: " . $e->getMessage() . "\n";
}
第四章 高级功能实现
4.1 文件上传与处理
DeepSeek API 支持文件上传功能,可以处理多种格式的文档:
<?php
class DeepSeekFiles extends DeepSeekClient
{
/**
* 上传文件
*/
public function uploadFile($filePath, $purpose = 'assistants')
{
if (!file_exists($filePath)) {
throw new DeepSeekException("File not found: $filePath");
}
$url = $this->config->getBaseUrl() . '/files';
$postData = [
'purpose' => $purpose,
'file' => new CURLFile($filePath)
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postData,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->config->getApiKey(),
],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new DeepSeekException('File upload error: ' . $error);
}
$result = json_decode($response, true);
if ($httpCode !== 200) {
$errorMessage = $result['error']['message'] ?? 'Unknown error';
throw new DeepSeekException("File upload error ($httpCode): $errorMessage", $httpCode);
}
return $result;
}
/**
* 获取文件列表
*/
public function listFiles()
{
return $this->sendRequest('/files', [], 'GET');
}
/**
* 获取文件内容
*/
public function getFileContent($fileId)
{
return $this->sendRequest("/files/$fileId/content", [], 'GET');
}
/**
* 删除文件
*/
public function deleteFile($fileId)
{
return $this->sendRequest("/files/$fileId", [], 'DELETE');
}
}
4.2 批量处理功能
对于需要处理大量数据的场景,可以使用批量处理功能:
<?php
class DeepSeekBatch extends DeepSeekClient
{
/**
* 创建批量任务
*/
public function createBatch($requests, $options = [])
{
$batchData = [
'requests' => $requests
];
if (!empty($options)) {
$batchData = array_merge($batchData, $options);
}
return $this->sendRequest('/batches', $batchData);
}
/**
* 获取批量任务状态
*/
public function getBatch($batchId)
{
return $this->sendRequest("/batches/$batchId", [], 'GET');
}
/**
* 取消批量任务
*/
public function cancelBatch($batchId)
{
return $this->sendRequest("/batches/$batchId/cancel", [], 'POST');
}
/**
* 批量文本处理示例
*/
public function processTexts($texts, $options = [])
{
$requests = [];
foreach ($texts as $text) {
$requests[] = [
'method' => 'POST',
'url' => '/completions',
'body' => array_merge([
'model' => $this->config->getDefaultModel(),
'prompt' => $text,
'max_tokens' => 500
], $options)
];
}
return $this->createBatch($requests);
}
}
4.3 自定义模型参数调优
针对特定应用场景,可能需要调整模型参数:
<?php
class DeepSeekTuning extends DeepSeekClient
{
/**
* 创建微调任务
*/
public function createFineTune($trainingFile, $options = [])
{
$defaultOptions = [
'training_file' => $trainingFile,
'model' => $this->config->getDefaultModel(),
'suffix' => null,
'epochs' => 4,
'batch_size' => null,
'learning_rate' => null,
];
$finalOptions = array_merge($defaultOptions, $options);
$finalOptions = array_filter($finalOptions, function($value) {
return $value !== null;
});
return $this->sendRequest('/fine-tunes', $finalOptions);
}
/**
* 列出微调任务
*/
public function listFineTunes()
{
return $this->sendRequest('/fine-tunes', [], 'GET');
}
/**
* 获取微调任务详情
*/
public function getFineTune($fineTuneId)
{
return $this->sendRequest("/fine-tunes/$fineTuneId", [], 'GET');
}
/**
* 取消微调任务
*/
public function cancelFineTune($fineTuneId)
{
return $this->sendRequest("/fine-tunes/$fineTuneId/cancel", [], 'POST');
}
}
第五章 错误处理与调试
5.1 完整的异常处理体系
建立健壮的异常处理机制对于生产环境应用至关重要:
<?php
class DeepSeekException extends Exception
{
private $errorCode;
private $errorDetails;
public function __construct($message = "", $code = 0, Exception $previous = null, $errorCode = null, $errorDetails = null)
{
parent::__construct($message, $code, $previous);
$this->errorCode = $errorCode;
$this->errorDetails = $errorDetails;
}
public function getErrorCode()
{
return $this->errorCode;
}
public function getErrorDetails()
{
return $this->errorDetails;
}
public static function fromApiResponse($httpCode, $responseData)
{
$errorMessage = $responseData['error']['message'] ?? 'Unknown API error';
$errorCode = $responseData['error']['code'] ?? 'unknown_error';
$errorDetails = $responseData['error']['details'] ?? null;
return new self("DeepSeek API Error ($httpCode): $errorMessage", $httpCode, null, $errorCode, $errorDetails);
}
}
class DeepSeekErrorHandler
{
private $logger;
public function __construct($logger = null)
{
$this->logger = $logger;
}
public function handle(Exception $e)
{
$this->logError($e);
if ($e instanceof DeepSeekException) {
return $this->handleDeepSeekException($e);
} else {
return $this->handleGenericException($e);
}
}
private function handleDeepSeekException(DeepSeekException $e)
{
$errorCode = $e->getErrorCode();
switch ($e->getCode()) {
case 401:
return $this->createErrorResponse('认证失败,请检查 API 密钥', 'authentication_error');
case 403:
return $this->createErrorResponse('权限不足', 'permission_denied');
case 429:
return $this->createErrorResponse('请求频率超限', 'rate_limit_exceeded');
case 500:
return $this->createErrorResponse('服务器内部错误', 'internal_server_error');
case 503:
return $this->createErrorResponse('服务暂时不可用', 'service_unavailable');
default:
return $this->createErrorResponse($e->getMessage(), 'api_error');
}
}
private function handleGenericException(Exception $e)
{
return $this->createErrorResponse('系统错误: ' . $e->getMessage(), 'system_error');
}
private function createErrorResponse($message, $code)
{
return [
'success' => false,
'error' => [
'code' => $code,
'message' => $message,
'timestamp' => date('c')
]
];
}
private function logError(Exception $e)
{
if ($this->logger) {
$logMessage = sprintf(
"[%s] %s in %s:%d\nStack trace:\n%s",
get_class($e),
$e->getMessage(),
$e->getFile(),
$e->getLine(),
$e->getTraceAsString()
);
if (is_callable($this->logger)) {
call_user_func($this->logger, $logMessage);
} else {
error_log($logMessage);
}
}
}
}
5.2 调试工具类
创建一个调试工具类来帮助开发和排查问题:
<?php
class DeepSeekDebugger
{
private $enabled;
private $logFile;
private $maxLogSize = 10485760; // 10MB
public function __construct($enabled = false, $logFile = null)
{
$this->enabled = $enabled;
$this->logFile = $logFile ?: __DIR__ . '/deepseek_debug.log';
}
public function enable()
{
$this->enabled = true;
return $this;
}
public function disable()
{
$this->enabled = false;
return $this;
}
public function logRequest($method, $endpoint, $data, $headers)
{
if (!$this->enabled) return;
$logEntry = [
'timestamp' => date('c'),
'type' => 'request',
'method' => $method,
'endpoint' => $endpoint,
'data' => $data,
'headers' => $this->sanitizeHeaders($headers)
];
$this->writeLog($logEntry);
}
public function logResponse($response, $httpCode, $timeTaken)
{
if (!$this->enabled) return;
$logEntry = [
'timestamp' => date('c'),
'type' => 'response',
'http_code' => $httpCode,
'time_taken' => $timeTaken,
'response' => $response
];
$this->writeLog($logEntry);
}
public function logError($error, $context = [])
{
if (!$this->enabled) return;
$logEntry = [
'timestamp' => date('c'),
'type' => 'error',
'error' => $error,
'context' => $context
];
$this->writeLog($logEntry);
}
private function sanitizeHeaders($headers)
{
$sanitized = [];
foreach ($headers as $key => $value) {
if (strtolower($key) === 'authorization') {
$sanitized[$key] = 'Bearer ***';
} else {
$sanitized[$key] = $value;
}
}
return $sanitized;
}
private function writeLog($entry)
{
// 检查日志文件大小,如果过大则轮转
if (file_exists($this->logFile) && filesize($this->logFile) > $this->maxLogSize) {
$this->rotateLog();
}
$line = json_encode($entry, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
file_put_contents($this->logFile, $line, FILE_APPEND | LOCK_EX);
}
private function rotateLog()
{
$backupFile = $this->logFile . '.' . date('Y-m-d_His');
if (file_exists($this->logFile)) {
rename($this->logFile, $backupFile);
}
// 保留最近 5 个日志文件
$logFiles = glob($this->logFile . '.*');
if (count($logFiles) > 5) {
usort($logFiles, function($a, $b) {
return filemtime($a) - filemtime($b);
});
for ($i = 0; $i < count($logFiles) - 5; $i++) {
unlink($logFiles[$i]);
}
}
}
public function getLogs($limit = 100)
{
if (!file_exists($this->logFile)) {
return [];
}
$lines = file($this->logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$logs = [];
$count = 0;
for ($i = count($lines) - 1; $i >= 0 && $count < $limit; $i--) {
$log = json_decode($lines[$i], true);
if ($log) {
$logs[] = $log;
$count++;
}
}
return array_reverse($logs);
}
}
5.3 重试机制
实现智能重试机制处理临时性错误:
<?php
class DeepSeekRetryHandler
{
private $maxRetries;
private $baseDelay;
private $maxDelay;
private $retryableErrors;
public function __construct($maxRetries = 3, $baseDelay = 1000, $maxDelay = 30000)
{
$this->maxRetries = $maxRetries;
$this->baseDelay = $baseDelay;
$this->maxDelay = $maxDelay;
$this->retryableErrors = [
429, // Rate limit
500, // Internal server error
502, // Bad gateway
503, // Service unavailable
504, // Gateway timeout
];
}
public function executeWithRetry(callable $operation, $context = '')
{
$lastException = null;
for ($attempt = 0; $attempt <= $this->maxRetries; $attempt++) {
try {
return $operation();
} catch (DeepSeekException $e) {
$lastException = $e;
// 检查是否应该重试
if (!$this->shouldRetry($e, $attempt)) {
break;
}
// 计算等待时间
$delay = $this->calculateDelay($attempt);
// 记录重试信息
error_log(sprintf(
"DeepSeek API call failed (attempt %d/%d). Retrying in %dms. Context: %s. Error: %s",
$attempt + 1,
$this->maxRetries + 1,
$delay,
$context,
$e->getMessage()
));
// 等待
usleep($delay * 1000);
} catch (Exception $e) {
// 非 DeepSeek 异常,不重试
throw $e;
}
}
// 所有重试都失败了
throw $lastException;
}
private function shouldRetry(DeepSeekException $e, $attempt)
{
if ($attempt >= $this->maxRetries) {
return false;
}
$httpCode = $e->getCode();
// 检查是否是可重试的错误码
if (in_array($httpCode, $this->retryableErrors)) {
return true;
}
// 检查错误信息中是否包含重试提示
$message = strtolower($e->getMessage());
$retryKeywords = [
'timeout', 'busy', 'try again', 'overload', 'rate limit'
];
foreach ($retryKeywords as $keyword) {
if (strpos($message, $keyword) !== false) {
return true;
}
}
return false;
}
private function calculateDelay($attempt)
{
// 指数退避算法,带随机抖动
$delay = min($this->baseDelay * pow(2, $attempt), $this->maxDelay);
$jitter = $delay * 0.1 * (mt_rand() / mt_getrandmax() - 0.5);
return (int)($delay + $jitter);
}
}
第六章 性能优化策略
6.1 连接池管理
对于高并发场景,实现连接池提高性能:
<?php
class DeepSeekConnectionPool
{
private $pool;
private $maxSize;
private $timeout;
private $poolSize;
public function __construct($maxSize = 10, $timeout = 30)
{
$this->pool = new SplQueue();
$this->maxSize = $maxSize;
$this->timeout = $timeout;
$this->poolSize = 0;
}
public function getConnection($config)
{
if (!$this->pool->isEmpty()) {
return $this->pool->dequeue();
}
if ($this->poolSize < $this->maxSize) {
$this->poolSize++;
return $this->createConnection($config);
}
// 等待可用连接
return $this->waitForConnection($config);
}
public function releaseConnection($connection)
{
if ($this->pool->count() < $this->maxSize) {
$this->pool->enqueue($connection);
} else {
// 连接池已满,关闭连接
$this->closeConnection($connection);
$this->poolSize--;
}
}
private function createConnection($config)
{
// 创建新的 HTTP 客户端连接
return new GuzzleHttp\Client([
'base_uri' => $config->getBaseUrl(),
'timeout' => $config->getTimeout(),
'headers' => [
'Authorization' => 'Bearer ' . $config->getApiKey(),
'Content-Type' => 'application/json',
],
'connection' => [
'max_requests' => 100, // 每个连接最大请求数
]
]);
}
private function closeConnection($connection)
{
// 关闭连接资源
if (method_exists($connection, 'close')) {
$connection->close();
}
}
private function waitForConnection($config)
{
$startTime = microtime(true);
while ((microtime(true) - $startTime) < $this->timeout) {
if (!$this->pool->isEmpty()) {
return $this->pool->dequeue();
}
usleep(100000); // 等待 100ms
}
throw new DeepSeekException('Connection pool timeout');
}
}
6.2 缓存策略
实现多级缓存减少 API 调用:
<?php
class DeepSeekCache
{
private $memoryCache = [];
private $cacheDir;
private $memoryTtl;
private $fileTtl;
public function __construct($cacheDir = null, $memoryTtl = 300, $fileTtl = 3600)
{
$this->cacheDir = $cacheDir ?: sys_get_temp_dir() . '/deepseek_cache';
$this->memoryTtl = $memoryTtl;
$this->fileTtl = $fileTtl;
if (!is_dir($this->cacheDir)) {
mkdir($this->cacheDir, 0755, true);
}
}
public function get($key, $maxAge = null)
{
// 首先检查内存缓存
if (isset($this->memoryCache[$key])) {
$entry = $this->memoryCache[$key];
if (time() - $entry['timestamp'] < ($maxAge ?: $this->memoryTtl)) {
return $entry['data'];
}
unset($this->memoryCache[$key]);
}
// 检查文件缓存
$filename = $this->getFilename($key);
if (file_exists($filename)) {
$data = file_get_contents($filename);
$entry = unserialize($data);
if (time() - $entry['timestamp'] < ($maxAge ?: $this->fileTtl)) {
// 更新内存缓存
$this->memoryCache[$key] = $entry;
return $entry['data'];
} else {
// 缓存过期,删除文件
unlink($filename);
}
}
return null;
}
public function set($key, $data, $ttl = null)
{
$entry = [
'data' => $data,
'timestamp' => time(),
'ttl' => $ttl ?: $this->fileTtl
];
// 更新内存缓存
$this->memoryCache[$key] = $entry;
// 更新文件缓存
$filename = $this->getFilename($key);
file_put_contents($filename, serialize($entry), LOCK_EX);
return true;
}
public function delete($key)
{
unset($this->memoryCache[$key]);
$filename = $this->getFilename($key);
if (file_exists($filename)) {
unlink($filename);
}
return true;
}
public function clear()
{
$this->memoryCache = [];
$files = glob($this->cacheDir . '/*.cache');
foreach ($files as $file) {
unlink($file);
}
return true;
}
private function getFilename($key)
{
$hash = md5($key);
return $this->cacheDir . '/' . $hash . '.cache';
}
public function cleanup()
{
$files = glob($this->cacheDir . '/*.cache');
$now = time();
foreach ($files as $file) {
$data = file_get_contents($file);
$entry = unserialize($data);
if ($now - $entry['timestamp'] > $entry['ttl']) {
unlink($file);
}
}
// 清理内存缓存
foreach ($this->memoryCache as $key => $entry) {
if ($now - $entry['timestamp'] > $entry['ttl']) {
unset($this->memoryCache[$key]);
}
}
}
}
6.3 批量请求优化
优化批量请求处理,减少网络开销:
<?php
class DeepSeekBatchProcessor
{
private $client;
private $batchSize;
private $delayBetweenBatches;
private $concurrentRequests;
public function __construct($client, $batchSize = 10, $delayBetweenBatches = 100, $concurrentRequests = 3)
{
$this->client = $client;
$this->batchSize = $batchSize;
$this->delayBetweenBatches = $delayBetweenBatches;
$this->concurrentRequests = $concurrentRequests;
}
public function processBatch($items, callable $processor, $options = [])
{
$results = [];
$batches = array_chunk($items, $this->batchSize);
foreach ($batches as $batchIndex => $batch) {
$batchResults = $this->processConcurrent($batch, $processor, $options);
$results = array_merge($results, $batchResults);
// 批次间延迟,避免触发速率限制
if ($batchIndex < count($batches) - 1) {
usleep($this->delayBetweenBatches * 1000);
}
}
return $results;
}
private function processConcurrent($items, callable $processor, $options)
{
$promises = [];
$client = new GuzzleHttp\Client();
foreach ($items as $index => $item) {
$promises[$index] = $client->postAsync($this->client->getConfig()->getBaseUrl() . '/completions', [
'json' => array_merge($options, [
'prompt' => $processor($item),
'model' => $this->client->getConfig()->getDefaultModel()
]),
'headers' => [
'Authorization' => 'Bearer ' . $this->client->getConfig()->getApiKey()
]
]);
}
// 限制并发数
$each = new GuzzleHttp\Promise\EachPromise($promises, [
'concurrency' => $this->concurrentRequests,
'fulfilled' => function($response) use (&$results) {
// 处理成功响应
},
'rejected' => function($reason) {
// 处理失败响应
error_log('Request failed: ' . $reason);
}
]);
$results = $each->promise()->wait();
return $results;
}
}
第七章 安全最佳实践
7.1 API 密钥安全管理
<?php
class DeepSeekSecurityManager
{
private $encryptionKey;
private $keyStorage;
public function __construct($encryptionKey = null)
{
$this->encryptionKey = $encryptionKey ?: $this->generateEncryptionKey();
$this->keyStorage = new SecureKeyStorage();
}
public function storeApiKey($keyId, $apiKey, $description = '')
{
$encryptedKey = $this->encryptApiKey($apiKey);
return $this->keyStorage->storeKey($keyId, $encryptedKey, $description);
}
public function getApiKey($keyId)
{
$encryptedKey = $this->keyStorage->getKey($keyId);
return $this->decryptApiKey($encryptedKey);
}
public function rotateApiKey($keyId, $newApiKey)
{
$this->storeApiKey($keyId, $newApiKey);
$this->keyStorage->logKeyRotation($keyId);
}
public function validateApiKey($apiKey)
{
// 基本的 API 密钥格式验证
if (strlen($apiKey) !== 32) { // 根据实际格式调整
return false;
}
// 可以添加更复杂的验证逻辑
return preg_match('/^sk-[a-zA-Z0-9]+$/', $apiKey);
}
private function encryptApiKey($apiKey)
{
$iv = random_bytes(openssl_cipher_iv_length('aes-256-gcm'));
$encrypted = openssl_encrypt($apiKey, 'aes-256-gcm', $this->encryptionKey, 0, $iv, $tag);
return base64_encode($iv . $tag . $encrypted);
}
private function decryptApiKey($encryptedData)
{
$data = base64_decode($encryptedData);
$ivLength = openssl_cipher_iv_length('aes-256-gcm');
$tagLength = 16;
$iv = substr($data, 0, $ivLength);
$tag = substr($data, $ivLength, $tagLength);
$encrypted = substr($data, $ivLength + $tagLength);
return openssl_decrypt($encrypted, 'aes-256-gcm', $this->encryptionKey, 0, $iv, $tag);
}
private function generateEncryptionKey()
{
return random_bytes(32); // 256位密钥
}
}
class SecureKeyStorage
{
private $storageFile;
public function __construct($storageFile = null)
{
$this->storageFile = $storageFile ?: __DIR__ . '/../storage/api_keys.dat';
// 确保存储目录存在
$dir = dirname($this->storageFile);
if (!is_dir($dir)) {
mkdir($dir, 0700, true);
}
}
public function storeKey($keyId, $encryptedKey, $description)
{
$keys = $this->loadKeys();
$keys[$keyId] = [
'key' => $encryptedKey,
'description' => $description,
'created_at' => date('c'),
'last_used' => null
];
return $this->saveKeys($keys);
}
public function getKey($keyId)
{
$keys = $this->loadKeys();
if (isset($keys[$keyId])) {
$keys[$keyId]['last_used'] = date('c');
$this->saveKeys($keys);
return $keys[$keyId]['key'];
}
return null;
}
public function logKeyRotation($keyId)
{
$logFile = dirname($this->storageFile) . '/key_rotation.log';
$logEntry = sprintf(
"[%s] Key rotated: %s\n",
date('c'),
$keyId
);
file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
}
private function loadKeys()
{
if (!file_exists($this->storageFile)) {
return [];
}
$data = file_get_contents($this->storageFile);
return unserialize($data) ?: [];
}
private function saveKeys($keys)
{
$data = serialize($keys);
return file_put_contents($this->storageFile, $data, LOCK_EX) !== false;
}
}
7.2 输入验证与清理
<?php
class DeepSeekInputValidator
{
public static function validatePrompt($prompt, $maxLength = 4000)
{
if (empty($prompt)) {
throw new InvalidArgumentException('Prompt cannot be empty');
}
if (strlen($prompt) > $maxLength) {
throw new InvalidArgumentException(sprintf('Prompt too long. Maximum length is %d characters', $maxLength));
}
// 检查是否有潜在的安全问题
if (self::containsMaliciousContent($prompt)) {
throw new InvalidArgumentException('Prompt contains potentially malicious content');
}
return self::sanitizeText($prompt);
}
public static function validateParameters($parameters)
{
$allowedParams = [
'model', 'prompt', 'max_tokens', 'temperature', 'top_p',
'frequency_penalty', 'presence_penalty', 'stop', 'stream'
];
$validated = [];
foreach ($parameters as $key => $value) {
if (!in_array($key, $allowedParams)) {
throw new InvalidArgumentException(sprintf('Invalid parameter: %s', $key));
}
$validated[$key] = self::validateParameter($key, $value);
}
return $validated;
}
private static function validateParameter($key, $value)
{
switch ($key) {
case 'temperature':
case 'top_p':
case 'frequency_penalty':
case 'presence_penalty':
return self::validateFloat($value, 0, 2);
case 'max_tokens':
return self::validateInteger($value, 1, 4000);
case 'model':
return self::validateModel($value);
default:
return $value;
}
}
private static function validateFloat($value, $min, $max)
{
if (!is_numeric($value)) {
throw new InvalidArgumentException(sprintf('%s must be a number', $value));
}
$floatValue = (float)$value;
if ($floatValue < $min || $floatValue > $max) {
throw new InvalidArgumentException(sprintf('%s must be between %s and %s', $value, $min, $max));
}
return $floatValue;
}
private static function validateInteger($value, $min, $max)
{
if (!is_numeric($value) || (int)$value != $value) {
throw new InvalidArgumentException(sprintf('%s must be an integer', $value));
}
$intValue = (int)$value;
if ($intValue < $min || $intValue > $max) {
throw new InvalidArgumentException(sprintf('%s must be between %s and %s', $value, $min, $max));
}
return $intValue;
}
private static function validateModel($model)
{
$allowedModels = ['deepseek-chat', 'deepseek-coder', 'deepseek-general'];
if (!in_array($model, $allowedModels)) {
throw new InvalidArgumentException(sprintf('Invalid model: %s', $model));
}
return $model;
}
private static function containsMaliciousContent($text)
{
$patterns = [
'/<script\b[^>]*>(.*?)<\/script>/is',
'/javascript:/i',
'/vbscript:/i',
'/onload\s*=/i',
'/onerror\s*=/i'
];
foreach ($patterns as $pattern) {
if (preg_match($pattern, $text)) {
return true;
}
}
return false;
}
private static function sanitizeText($text)
{
// 移除控制字符(除了换行和制表符)
$text = preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $text);
// 转义 HTML 特殊字符
$text = htmlspecialchars($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
return $text;
}
}
第八章 实战项目案例
8.1 智能客服系统
<?php
class SmartCustomerService
{
private $chatClient;
private $knowledgeBase;
private $sessionManager;
public function __construct($apiKey)
{
$config = new DeepSeekConfig();
$config->setApiKey($apiKey);
$this->chatClient = new DeepSeekChat($config);
$this->knowledgeBase = new KnowledgeBase();
$this->sessionManager = new SessionManager();
}
public function handleCustomerQuery($sessionId, $query, $context = [])
{
// 获取或创建会话
$session = $this->sessionManager->getSession($sessionId);
// 检索相关知识
$relevantKnowledge = $this->knowledgeBase->search($query);
// 构建系统提示
$systemMessage = $this->buildSystemMessage($context, $relevantKnowledge);
// 准备消息历史
$messages = array_merge(
[['role' => 'system', 'content' => $systemMessage]],
$session->getMessages()
);
// 添加当前查询
$messages[] = ['role' => 'user', 'content' => $query];
try {
// 调用 DeepSeek API
$response = $this->chatClient->createChatCompletion([
'messages' => $messages,
'temperature' => 0.3, // 较低的温度值使回复更稳定
'max_tokens' => 500
]);
$reply = $response['choices'][0]['message']['content'];
// 更新会话
$session->addMessage('user', $query);
$session->addMessage('assistant', $reply);
// 记录交互日志
$this->logInteraction($sessionId, $query, $reply);
return $reply;
} catch (Exception $e) {
// 错误处理
return $this->getFallbackResponse($e);
}
}
private function buildSystemMessage($context, $knowledge)
{
$message = "你是一个专业的客服助手。请根据以下指南回答问题:\n\n";
if (!empty($knowledge)) {
$message .= "相关知识:\n" . implode("\n", $knowledge) . "\n\n";
}
$message .= "回答指南:\n";
$message .= "- 保持友好和专业\n";
$message .= "- 如果不知道答案,请如实告知\n";
$message .= "- 引导用户提供更多信息\n";
$message .= "- 避免做出无法兑现的承诺\n";
if (!empty($context['product'])) {
$message .= "\n当前产品:" . $context['product'];
}
return $message;
}
private function getFallbackResponse($exception)
{
// 根据错误类型返回不同的降级响应
if ($exception instanceof DeepSeekException) {
switch ($exception->getCode()) {
case 429:
return "当前服务繁忙,请稍后再试。";
case 503:
return "服务暂时不可用,请稍后重试。";
default:
return "抱歉,系统暂时无法处理您的请求。";
}
}
return "系统繁忙,请稍后再试。";
}
private function logInteraction($sessionId, $query, $reply)
{
$logData = [
'session_id' => $sessionId,
'query' => $query,
'reply' => $reply,
'timestamp' => date('c'),
'response_time' => microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']
];
file_put_contents(
__DIR__ . '/logs/customer_service.log',
json_encode($logData) . "\n",
FILE_APPEND | LOCK_EX
);
}
}
class KnowledgeBase
{
public function search($query)
{
// 这里可以实现基于向量数据库的语义搜索
// 简化版:基于关键词匹配
$knowledge = $this->loadKnowledge();
$results = [];
foreach ($knowledge as $item) {
similar_text($query, $item['question'], $percent);
if ($percent > 60) { // 相似度阈值
$results[] = $item['answer'];
}
}
return array_slice($results, 0, 3); // 返回最相关的3条
}
private function loadKnowledge()
{
// 从文件或数据库加载知识库
return [
[
'question' => '如何重置密码',
'answer' => '要重置密码,请访问登录页面点击"忘记密码",然后按照邮件指示操作。'
],
// ... 更多知识条目
];
}
}
class SessionManager
{
private $sessions = [];
private $sessionTimeout = 1800; // 30分钟
public function getSession($sessionId)
{
$this->cleanupExpiredSessions();
if (!isset($this->sessions[$sessionId])) {
$this->sessions[$sessionId] = new ChatSession();
}
$this->sessions[$sessionId]->lastActivity = time();
return $this->sessions[$sessionId];
}
private function cleanupExpiredSessions()
{
$now = time();
foreach ($this->sessions as $sessionId => $session) {
if ($now - $session->lastActivity > $this->sessionTimeout) {
unset($this->sessions[$sessionId]);
}
}
}
}
class ChatSession
{
public $messages = [];
public $lastActivity;
public function addMessage($role, $content)
{
$this->messages[] = [
'role' => $role,
'content' => $content,
'timestamp' => time()
];
// 保持最近20条消息
if (count($this->messages) > 20) {
$this->messages = array_slice($this->messages, -20);
}
}
public function getMessages()
{
return $this->messages;
}
}
8.2 代码生成工具
<?php
class CodeGenerator
{
private $client;
private $languageTemplates;
public function __construct($apiKey)
{
$config = new DeepSeekConfig();
$config->setApiKey($apiKey);
$config->setDefaultModel('deepseek-coder'); // 使用代码专用模型
$this->client = new DeepSeekCompletions($config);
$this->loadLanguageTemplates();
}
public function generateFunction($description, $language, $options = [])
{
$prompt = $this->buildFunctionPrompt($description, $language, $options);
$response = $this->client->createCompletion($prompt, [
'max_tokens' => 1000,
'temperature' => 0.2, // 低温度确保代码确定性
'stop' => ['\n\nfunction', '\n\nclass'] // 停止生成条件
]);
$code = $response['choices'][0]['text'];
// 后处理:清理和格式化代码
return $this->postProcessCode($code, $language);
}
public function explainCode($code, $language)
{
$prompt = "请解释以下{$language}代码的功能和工作原理:\n\n```{$language}\n{$code}\n```";
$response = $this->client->createCompletion($prompt, [
'max_tokens' => 500,
'temperature' => 0.3
]);
return $response['choices'][0]['text'];
}
public function debugCode($code, $language, $errorDescription)
{
$prompt = "以下{$language}代码有错误:{$errorDescription}\n\n请修复代码:\n```{$language}\n{$code}\n```";
$response = $this->client->createCompletion($prompt, [
'max_tokens' => 800,
'temperature' => 0.1
]);
$fixedCode = $response['choices'][0]['text'];
return $this->postProcessCode($fixedCode, $language);
}
private function buildFunctionPrompt($description, $language, $options)
{
$template = $this->languageTemplates[$language] ?? $this->languageTemplates['default'];
$prompt = "根据以下描述生成{$language}代码:\n";
$prompt .= "描述:{$description}\n\n";
if (!empty($options['input'])) {
$prompt .= "输入要求:{$options['input']}\n";
}
if (!empty($options['output'])) {
$prompt .= "输出要求:{$options['output']}\n";
}
if (!empty($options['constraints'])) {
$prompt .= "约束条件:" . implode(', ', $options['constraints']) . "\n";
}
$prompt .= "\n生成高质量的、可读性好的代码,包含适当的注释。\n\n";
$prompt .= "代码:\n";
return $prompt;
}
private function postProcessCode($code, $language)
{
// 移除可能的多余文本
$code = preg_replace('/^(```.*?\n|\n*```\n*)/', '', $code);
// 根据语言进行特定处理
switch ($language) {
case 'php':
// 确保PHP标签正确
if (strpos($code, '<?php') === false && strpos($code, '<?=') === false) {
$code = "<?php\n\n" . $code;
}
break;
case 'python':
// 检查缩进
$lines = explode("\n", $code);
$formattedLines = [];
foreach ($lines as $line) {
if (trim($line) !== '') {
$formattedLines[] = $line;
}
}
$code = implode("\n", $formattedLines);
break;
}
return trim($code);
}
private function loadLanguageTemplates()
{
$this->languageTemplates = [
'php' => '生成符合PSR标准的PHP代码,包含类型声明和文档注释。',
'python' => '生成符合PEP 8规范的Python代码,包含类型提示和文档字符串。',
'javascript' => '生成现代ES6+ JavaScript代码,使用const/let,包含JSDoc注释。',
'java' => '生成符合Java编码规范的代码,包含适当的注释和文档。',
'default' => '生成高质量、可维护的代码,包含适当的注释。'
];
}
}
// 使用示例
$generator = new CodeGenerator('your_api_key');
// 生成PHP函数
$functionCode = $generator->generateFunction(
'计算斐波那契数列的第n项',
'php',
[
'input' => '整数n',
'output' => '第n项斐波那契数',
'constraints' => ['使用递归实现', '包含边界条件处理']
]
);
echo "生成的代码:\n";
echo $functionCode;
// 解释代码
$explanation = $generator->explainCode($functionCode, 'php');
echo "\n代码解释:\n";
echo $explanation;
第九章 常见问题解答
9.1 API 调用相关问题
Q: 如何获取 DeepSeek API 密钥?
A: 访问 DeepSeek 官方网站,注册开发者账号,在控制台中创建新的 API 密钥。
Q: API 调用的频率限制是多少?
A: 频率限制因套餐而异,免费版通常有较低的限制,付费版有更高的限制。具体限制请在官方文档中查看。
Q: 如何避免频率限制错误?
A: 实现指数退避重试机制,合理控制请求频率,使用缓存减少重复请求。
9.2 技术实现问题
Q: 如何处理长时间的 API 响应?
A: 使用异步请求或设置适当的超时时间,对于生成长文本可以考虑使用流式响应。
Q: 如何优化 API 调用的性能?
A: 使用连接池、实现缓存策略、批量处理请求、优化提示词设计。
Q: 如何保证 API 调用的安全性?
A: 安全存储 API 密钥、验证和清理用户输入、使用 HTTPS 加密通信、实现适当的权限控制。
9.3 业务应用问题
Q: 如何设计高质量的提示词?
A: 明确具体的要求、提供足够的上下文、使用示例说明、迭代优化提示词。
Q: 如何评估生成内容的质量?
A: 建立评估指标体系、人工审核样本、使用自动化质量检查、收集用户反馈。
Q: 如何处理不恰当或错误的生成内容?
A: 实现内容过滤机制、设置后处理流程、提供用户反馈渠道、持续优化提示词。
结语
本文详细介绍了如何使用 PHP 调用 DeepSeek API 的完整流程,从基础的环境配置到高级的功能实现,再到实战项目应用。通过阅读本文,您应该能够:
- 理解 DeepSeek API 的基本概念和功能特性
- 掌握 PHP 调用 DeepSeek API 的各种技术方法
- 实现错误处理、性能优化和安全防护机制
- 构建实际的 AI 应用系统
DeepSeek API 为 PHP 开发者提供了强大的 AI 能力,合理利用这些能力可以显著提升应用的智能水平和用户体验。随着技术的不断发展,建议持续关注 DeepSeek 官方文档的更新,及时应用新的功能和优化。
希望本文对您的开发工作有所帮助,祝您在 AI 开发的道路上取得更大的成功!
版权声明:本文为技术分享文章,转载请注明出处。文中代码示例仅供参考,请根据实际需求进行调整和优化。
更多推荐
所有评论(0)