本文目录导读:

我来详细讲解PHP项目对接大模型接口的方法,以常见的API为例:
基础调用方式
使用 cURL(最常用)
<?php
function callLLM($prompt) {
$api_key = 'your-api-key';
$api_url = 'https://api.openai.com/v1/chat/completions';
$data = [
'model' => 'gpt-3.5-turbo',
'messages' => [
[
'role' => 'user',
'content' => $prompt
]
],
'temperature' => 0.7,
'max_tokens' => 1000
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $api_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $api_key
],
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
return ['error' => curl_error($ch)];
}
curl_close($ch);
if ($http_code !== 200) {
return ['error' => "HTTP Error: $http_code"];
}
return json_decode($response, true);
}
// 使用示例
$result = callLLM("请用中文写一首关于AI的诗");
if (!isset($result['error'])) {
echo $result['choices'][0]['message']['content'];
}
?>
使用 GuzzleHttp(推荐用于复杂项目)
composer require guzzlehttp/guzzle
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
class LLMService {
private $client;
private $api_key;
public function __construct($api_key) {
$this->api_key = $api_key;
$this->client = new Client([
'base_uri' => 'https://api.openai.com/',
'timeout' => 30,
'headers' => [
'Authorization' => 'Bearer ' . $api_key,
'Content-Type' => 'application/json'
]
]);
}
public function chat($messages, $model = 'gpt-3.5-turbo') {
try {
$response = $this->client->post('v1/chat/completions', [
'json' => [
'model' => $model,
'messages' => $messages,
'temperature' => 0.7,
'max_tokens' => 1000
]
]);
return json_decode($response->getBody(), true);
} catch (RequestException $e) {
return [
'error' => $e->getMessage(),
'status' => $e->getCode()
];
}
}
}
// 使用示例
$llm = new LLMService('your-api-key');
$result = $llm->chat([
['role' => 'user', 'content' => '你好,请介绍一下自己']
]);
print_r($result);
?>
流式输出(Streaming)
<?php
function streamLLM($prompt, $callback) {
$api_key = 'your-api-key';
$data = [
'model' => 'gpt-3.5-turbo',
'messages' => [
['role' => 'user', 'content' => $prompt]
],
'stream' => true
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.openai.com/v1/chat/completions',
CURLOPT_RETURNTRANSFER => false,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $api_key
],
CURLOPT_WRITEFUNCTION => function($ch, $data) use ($callback) {
// 解析SSE数据
$lines = explode("\n", $data);
foreach ($lines as $line) {
if (strpos($line, 'data: ') === 0) {
$json = substr($line, 6);
if ($json !== '[DONE]') {
$content = json_decode($json, true);
if (isset($content['choices'][0]['delta']['content'])) {
$callback($content['choices'][0]['delta']['content']);
}
}
}
}
return strlen($data);
}
]);
curl_exec($ch);
curl_close($ch);
}
// 使用示例 - 网页实时显示
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
streamLLM("写一个简短的故事", function($chunk) {
echo "data: " . json_encode(['content' => $chunk]) . "\n\n";
ob_flush();
flush();
});
?>
封装成统一的Service类
<?php
class AIService {
private $provider;
private $config;
public function __construct($provider = 'openai') {
$this->provider = $provider;
$this->config = [
'openai' => [
'url' => 'https://api.openai.com/v1/chat/completions',
'key' => getenv('OPENAI_API_KEY'),
'model' => 'gpt-3.5-turbo'
],
'claude' => [
'url' => 'https://api.anthropic.com/v1/messages',
'key' => getenv('CLAUDE_API_KEY'),
'model' => 'claude-3-opus-20240229'
],
'文心一言' => [
'url' => 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions',
'key' => getenv('BAIDU_API_KEY'),
'model' => 'ernie-bot-turbo'
]
];
}
public function chat($messages, $options = []) {
$config = $this->config[$this->provider];
switch ($this->provider) {
case 'openai':
return $this->callOpenAI($messages, $config, $options);
case 'claude':
return $this->callClaude($messages, $config, $options);
case '文心一言':
return $this->callBaidu($messages, $config, $options);
default:
throw new Exception("不支持的AI提供商");
}
}
private function callOpenAI($messages, $config, $options) {
// OpenAI 调用实现
$data = array_merge([
'model' => $config['model'],
'messages' => $messages
], $options);
return $this->httpPost($config['url'], $data, [
'Authorization: Bearer ' . $config['key']
]);
}
private function callClaude($messages, $config, $options) {
// Claude 调用实现
$data = array_merge([
'model' => $config['model'],
'messages' => $messages,
'max_tokens' => 1000
], $options);
return $this->httpPost($config['url'], $data, [
'x-api-key: ' . $config['key'],
'anthropic-version: 2023-06-01'
]);
}
private function callBaidu($messages, $config, $options) {
// 百度文心一言调用实现
// 需要先获取access_token
$token = $this->getBaiduToken();
$data = array_merge([
'messages' => $messages
], $options);
return $this->httpPost(
$config['url'] . '?access_token=' . $token,
$data,
['Content-Type: application/json']
);
}
private function httpPost($url, $data, $headers = []) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => array_merge(
['Content-Type: application/json'],
$headers
),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
return ['error' => $error];
}
return json_decode($response, true);
}
private function getBaiduToken() {
// 实现百度access_token获取逻辑
// 通常使用client_credentials方式
}
}
// 使用示例
$ai = new AIService('openai');
$result = $ai->chat([
['role' => 'system', 'content' => '你是一个AI助手'],
['role' => 'user', 'content' => '介绍一下PHP的优势']
]);
?>
错误处理和重试机制
<?php
class AIClient {
private $maxRetries = 3;
private $retryDelay = 2; // 秒
public function callWithRetry($prompt) {
$attempts = 0;
while ($attempts < $this->maxRetries) {
try {
$result = $this->callAPI($prompt);
if (isset($result['error'])) {
throw new Exception($result['error']);
}
return $result;
} catch (Exception $e) {
$attempts++;
if ($attempts >= $this->maxRetries) {
throw $e;
}
// 指数退避
sleep($this->retryDelay * $attempts);
// 记录日志
error_log("API调用失败,第{$attempts}次重试: " . $e->getMessage());
}
}
}
}
?>
配置管理
// .env 文件 OPENAI_API_KEY=sk-xxx CLAUDE_API_KEY=sk-ant-xxx BAIDU_API_KEY=xxx BAIDU_SECRET_KEY=xxx // 使用 vlucas/phpdotenv $dotenv = Dotenv\Dotenv::createImmutable(__DIR__); $dotenv->load(); $apiKey = $_ENV['OPENAI_API_KEY'];
性能优化建议
- 连接池: 使用持久连接
- 缓存: 对相同请求结果缓存
- 异步处理: 使用队列处理大量请求
- 限流: 实现令牌桶算法
// 简单的缓存示例
$cacheKey = md5($prompt);
$cached = apcu_fetch($cacheKey);
if ($cached !== false) {
return $cached;
}
$result = callLLM($prompt);
apcu_store($cacheKey, $result, 3600); // 缓存1小时
return $result;
选择哪种方式取决于你的项目需求,个人推荐使用 GuzzleHttp 配合 Service 类封装,这样更易于维护和扩展。