PHP项目私有化大模型如何内网对接调用

wen PHP项目 30

本文目录导读:

PHP项目私有化大模型如何内网对接调用

  1. 核心架构选择(推荐方案)
  2. 具体实现步骤
  3. 性能优化建议
  4. 错误处理与容错
  5. 安全注意事项
  6. 完整代码示例(Guzzle + 异步队列)

针对PHP项目私有化大模型在内网环境下的对接调用,核心在于解决网络隔离、API兼容性、性能与安全这三个问题,以下是具体的实现方案和步骤:

核心架构选择(推荐方案)

由于PHP本身是同步阻塞模型,直接通过HTTP调用大模型API(如OpenAI兼容接口)在长耗时推理场景下会阻塞进程,推荐采用反向代理 + 异步任务队列的架构:

[PHP应用] --> [任务队列/异步处理] --> [内网大模型Server] --> [处理结果回调]
                     ^
                     |  (或者)
[PHP应用] --> [内网代理网关] --> [大模型Server]

具体实现步骤

部署内网大模型服务

假设你已内网部署了模型(如通过llama.cpp、vLLM、Ollama、FastChat等),暴露一个OpenAI兼容的HTTP API接口:

# 示例:使用Ollama
curl http://192.168.1.100:11434/api/generate -d '{
  "model": "qwen2.5:7b",
  "prompt": "你好",
  "stream": false
}'

PHP端对接方式

方案A:直接cURL调用(适合轻量、非流式、短响应)

<?php
function callLLM(string $prompt): string {
    $url = 'http://192.168.1.100:11434/api/generate';
    $data = [
        'model' => 'qwen2.5:7b',
        'prompt' => $prompt,
        'stream' => false,
        'options' => [
            'num_predict' => 1024,
        ]
    ];
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($data),
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30, // 大模型推理可能超时
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_NOSIGNAL => true, // 防止PHP进程被信号中断
    ]);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if ($httpCode !== 200) {
        throw new Exception("LLM API error: HTTP $httpCode");
    }
    $result = json_decode($response, true);
    return $result['response'] ?? '';
}

注意事项

  • CURLOPT_TIMEOUT要设置足够大(如120秒),避免推理未完成被切断。
  • 如果模型返回速度慢,PHP-FPM进程会被长时间占用,需调整pm.max_children

方案B:使用GuzzleHttp客户端(推荐)

composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
$client = new Client([
    'base_uri' => 'http://192.168.1.100:11434',
    'timeout' => 120.0,
    'connect_timeout' => 5.0,
]);
try {
    $response = $client->post('/api/generate', [
        'json' => [
            'model' => 'qwen2.5:7b',
            'prompt' => '你好',
            'stream' => false
        ]
    ]);
    $body = json_decode($response->getBody(), true);
    echo $body['response'];
} catch (RequestException $e) {
    // 处理超时或连接错误
}

处理流式响应(SSE)

如果需要像ChatGPT那样逐字返回,有两种实现方式:

方式A:PHP-FPM + 流式输出(不推荐) 利用PHP的输出缓冲,在每个token到达时flush:

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$ch = curl_init('http://192.168.1.100:11434/api/generate');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    'model' => 'qwen2.5:7b',
    'prompt' => '讲个故事',
    'stream' => true
]));
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $chunk) {
    // 解析SSE数据行
    $lines = explode("\n", $chunk);
    foreach ($lines as $line) {
        if (str_starts_with($line, 'data: ')) {
            $data = json_decode(substr($line, 6), true);
            echo "data: " . json_encode(['token' => $data['response']]) . "\n\n";
            ob_flush();
            flush();
        }
    }
    return strlen($chunk);
});
curl_exec($ch);

缺点:PHP-FPM单个进程会长时间占用,并发能力差。

方式B:使用Swoole/Workerman(生产推荐) 利用常驻内存的PHP框架处理SSE:

// 使用Swoole HTTP Server
$http = new Swoole\Http\Server("0.0.0.0", 9501);
$http->on('request', function ($request, $response) {
    $response->header('Content-Type', 'text/event-stream');
    $response->header('Cache-Control', 'no-cache');
    $cli = new Swoole\Coroutine\Http\Client('192.168.1.100', 11434);
    $cli->set(['timeout' => -1]);
    $cli->post('/api/generate', [
        'model' => 'qwen2.5:7b',
        'prompt' => $request->get['prompt'] ?? 'hi',
        'stream' => true
    ]);
    // 逐行读取流并发送
    while (!$cli->eof()) {
        $chunk = $cli->recv();
        if ($chunk) {
            $response->write("data: $chunk\n\n");
        }
    }
    $response->end();
});
$http->start();

内网API网关设计(可选)

如果需要统一管理多个模型或添加认证,可以在PHP和大模型之间加一层Nginx代理:

server {
    listen 80;
    server_name llm.internal;
    location /v1/ {
        proxy_pass http://192.168.1.100:11434;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_buffering off;  # 流式必须关闭缓冲
        proxy_cache off;
        proxy_read_timeout 300s;
    }
    # 添加API Key验证
    location /v1/chat/completions {
        if ($http_authorization != "Bearer internal-key-xxx") {
            return 401;
        }
        proxy_pass http://192.168.1.200:8000;  # 指向另一个模型服务
    }
}

性能优化建议

问题 解决方案
PHP-FPM阻塞 使用Swoole/Workerman + 协程处理流式请求
请求超时 设置CURLOPT_TIMEOUT为120秒以上,Nginx proxy_read_timeout同步调整
并发低 增加PHP-FPM pm.max_children,或使用消息队列异步处理
内存不足 大模型推理请使用C++/Python服务,PHP只负责转发
流式卡顿 关闭Nginx、Apache的缓冲:proxy_buffering off; output_buffering = Off

错误处理与容错

// 重试机制
$maxRetries = 3;
$attempt = 0;
while ($attempt < $maxRetries) {
    try {
        $result = callLLM($prompt);
        break;
    } catch (\Exception $e) {
        $attempt++;
        if ($attempt >= $maxRetries) {
            throw $e;
        }
        usleep(1000000 * $attempt); // 指数退避
    }
}

安全注意事项

  1. 内网隔离:确保模型API只监听内网IP(0.0.1168.x.x),不暴露到公网。
  2. 输入过滤:严格过滤用户输入的prompt,防止SQL注入或XSS(虽然模型一般不会执行,但结果可能反射到页面)。
  3. 速率限制:在Nginx或PHP端限制单个IP的调用频率,防止滥用。
  4. 日志审计:记录每次调用的用户、prompt、响应长度,内网环境也应有审计。

完整代码示例(Guzzle + 异步队列)

// 使用Redis队列异步处理
public function handleLongTask(string $prompt, string $callbackUrl) {
    // 1. 放入队列
    Redis::lpush('llm:queue', json_encode([
        'prompt' => $prompt,
        'callback' => $callbackUrl
    ]));
    // 2. 返回任务ID,前端轮询结果
    return ['task_id' => uniqid()];
}
// 单独的工作进程(CLI模式运行)
while (true) {
    $job = Redis::brpop('llm:queue', 10);
    if ($job) {
        $data = json_decode($job[1], true);
        try {
            $result = callLLM($data['prompt']);
            // 回调通知PHP应用
            file_get_contents($data['callback'] . '?result=' . urlencode($result));
        } catch (Exception $e) {
            // 错误处理
        }
    }
}
  • 简单场景:直接用curl + timeout设置即可。
  • 流式交互:推荐升级到Swoole/Workerman,或使用前端直接连大模型API(如果安全允许)。
  • 高并发:必须使用消息队列解耦PHP-FPM和后端模型。
  • 生产环境:内网Nginx反代 + 限流 + 日志 + 健康检查。

根据你的实际场景(实时聊天、文档分析、代码生成),选择最合适的架构即可,如果需要进一步的代码调试,可以提供具体的模型地址和响应示例。

抱歉,评论功能暂时关闭!