PHP 接入降重降AI接口
PHP 调用降重降AI API 完整示例:Guzzle 带重试的基础调用、逐段落处理全文、Laravel 队列批量任务实践。
PHP 接入降重降AI接口
PHP 8+ 推荐用 Guzzle 调用降重降AI接口(cURL 原生写法亦可,Guzzle 处理超时与异常更省事)。接口一次改写同时完成降重和降AI,单次请求处理一个正文自然段(不超过1000字),详细参数说明见接口文档。
安装依赖
composer require guzzlehttp/guzzle
基础调用
以下代码包含超时控制与错误重试,可直接复制运行(替换 API_KEY):
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
$client = new Client([
'base_uri' => 'https://api.llmapi.fit',
'timeout' => 180, // 高峰期智能排队最长约2分钟
]);
function reduceParagraph(Client $client, string $apiKey, string $text, int $maxRetries = 3): string
{
$attempt = 0;
while (true) {
$attempt++;
try {
$resp = $client->post('/completion/v2/reduce', [
'headers' => ['Authorization' => "Bearer {$apiKey}"],
'json' => ['text' => $text],
]);
$data = json_decode((string) $resp->getBody(), true);
if (($data['code'] ?? '') === 'success') {
return $data['output_text'];
}
throw new RuntimeException(
'业务错误: ' . ($data['code'] ?? 'unknown') . ' ' . ($data['message'] ?? '')
);
} catch (RequestException $e) {
$status = $e->getResponse()?->getStatusCode();
// 429 请求过于频繁 / 503 GPU服务繁忙:等待后重试
if (in_array($status, [429, 503], true) && $attempt < $maxRetries) {
sleep(4);
continue;
}
// 400 参数或余额问题、401 密钥问题:不可重试
throw $e;
}
}
}
$rewritten = reduceParagraph($client, 'YOUR_API_KEY', '待改写的正文自然段……');
echo $rewritten, PHP_EOL;
逐段落处理全文
接口按段落级别改写,循环处理论文的正文自然段:
$paragraphs = [
'第一个正文自然段……',
'第二个正文自然段……',
];
$rewritten = [];
foreach ($paragraphs as $p) {
$rewritten[] = reduceParagraph($client, $apiKey, $p);
usleep(500000); // 500ms,速率控制在 10 次/秒以内
}
Laravel 队列批量处理
批量改写整篇论文(几十上百段)时,建议丢进队列异步处理,避免 HTTP 请求超时:
// app/Jobs/RewriteParagraph.php
class RewriteParagraph implements ShouldQueue
{
public $timeout = 300;
public function __construct(
public Document $document,
public int $paragraphIndex,
public string $text,
) {}
public function handle(): void
{
$client = app(Client::class);
$result = reduceParagraph($client, config('services.llmapi.key'), $this->text);
$this->document->updateParagraph($this->paragraphIndex, $result);
}
}
// 分发时用 RateLimiter 控制速率(10 次/秒以内)
foreach ($paragraphs as $i => $p) {
RateLimiter::attempt(
"reduce:{$document->id}",
$perSecond = 10,
fn() => RewriteParagraph::dispatch($document, $i, $p),
1
);
}
处理 Word 文档脚注(PhpWord)
论文段落常带脚注引用,直接发送会丢失。正确做法是把脚注引用替换为 [[FNn]] 占位符,改写后原样保留,写回时恢复(完整规范见接口文档第8节)。
phpoffice/phpword 读取段落文本后,可用正则把脚注引用标记替换为段内顺序编号的占位符(每段从 [[FN0]] 开始);写回时按占位符切分文本,在占位符处插回原脚注引用节点。word/footnotes.xml 条目文件全程不修改,保存时 Word 按引用出现顺序自动重排编号。
PhpWord 对脚注写回的支持有限,复杂文档(脚注+尾注+批注并存)建议直接操作 OOXML 包(
ZipArchive+DOMDocument)。
常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
401 unauthorized | API Key 错误 | 检查 Authorization: Bearer YOUR_API_KEY |
400 textTooLong | 单段超过1000字 | 按语义拆分成多个自然段分别调用 |
| cURL error 28 | 超时 | timeout 保持 180,重试 2-3 次 |
| JSON 中文转义 | json_encode 默认转 Unicode | Guzzle 的 json 选项已正确处理 UTF-8,无需干预 |