如何重构PHP代码使GPT-4生成连贯完整的5000字文档
大文本生成连贯内容的PHP代码重构方案
原代码核心问题
- 续写请求未传递有效指令:后续请求中用户消息为空,模型无法判断需要延续之前的内容,导致生成主题变体
- 参数使用错误:Chat Completions接口不支持独立的
prompt参数,需通过messages数组维护上下文逻辑 - 长度控制不准确:用
strlen统计字符数代替单词数,直接截断易破坏语句完整性
重构后的代码
public function writePrompt(Request $request) { $this->authCheck(); $this->validate($request, [ 'content' => 'required', 'maxWords' => 'required|integer|min:1', ]); ini_set('max_execution_time', 1800); $userPrompt = $request->input('content'); $targetWordCount = intval($request->input('maxWords')); $maxTokensPerRequest = 1500; // 预留token给指令,避免内容截断 $generatedContent = ''; $messageHistory = [ [ 'role' => 'user', 'content' => $userPrompt . "\n请生成一篇连贯完整的长文档,严格围绕主题展开,后续续写时保持内容的连续性和逻辑性。" ] ]; if (empty($this->super_settings['openai_api_key']) || $this->isDemo() || $this->super_settings['openai_api_key'] == 'demo') { $generatedContent = __('Sorry, I am not able to write anything for you.'); return $this->returnJsonResponse($generatedContent); } $client = OpenAI::client($this->super_settings['openai_api_key']); try { do { $response = $client->chat()->create([ 'model' => 'gpt-4', 'messages' => $messageHistory, 'max_tokens' => $maxTokensPerRequest, 'temperature' => 0.7, // 平衡创造性与内容连贯性 ]); $newContent = $response->choices[0]->message->content; $generatedContent .= $newContent; // 更新对话历史,让模型明确已有内容,后续继续续写 $messageHistory[] = ['role' => 'assistant', 'content' => $newContent]; $messageHistory[] = [ 'role' => 'user', 'content' => "继续围绕之前的主题和内容续写,保持连贯性,直到总字数达到约{$targetWordCount}字。当前已生成的最近内容:" . substr($generatedContent, -500) ]; $currentWordCount = $this->countWords($generatedContent); } while ($currentWordCount < $targetWordCount && $currentWordCount + 500 < $targetWordCount); // 调整内容到目标字数,优先保证语句完整 $generatedContent = $this->trimToWordCount($generatedContent, $targetWordCount); } catch (\Exception $e) { $generatedContent = $this->user->is_super_admin ? 'Error: ' . $e->getMessage() : __('Sorry, I am not able to write anything for you.'); } $generatedContent = Str::markdown($generatedContent); return $this->returnJsonResponse($generatedContent); } /** * 统计内容单词数(兼容中英文) */ private function countWords(string $content): int { $chineseChars = preg_match_all('/[\x{4e00}-\x{9fa5}]/u', $content, $matches); $englishWords = str_word_count(preg_replace('/[\x{4e00}-\x{9fa5}]/u', '', $content)); return $chineseChars + $englishWords; } /** * 将内容截断到指定单词数,尽量保证语句完整 */ private function trimToWordCount(string $content, int $targetCount): string { $currentCount = $this->countWords($content); if ($currentCount <= $targetCount) { return $content; } $punctuations = ['。', '!', '?', '.', '!', '?', ';', ';']; $trimmed = $content; while ($this->countWords($trimmed) > $targetCount) { $lastPos = PHP_INT_MAX; foreach ($punctuations as $punc) { $pos = strrpos($trimmed, $punc); if ($pos !== false && $pos < $lastPos) { $lastPos = $pos; } } if ($lastPos === PHP_INT_MAX) { $words = preg_split('/\s+|(?<=[\x{4e00}-\x{9fa5}])|(?=[\x{4e00}-\x{9fa5}])/u', $trimmed); $trimmed = implode('', array_slice($words, 0, $targetCount)); break; } $trimmed = substr($trimmed, 0, $lastPos + 1); } return $trimmed; } /** * 返回统一JSON响应 */ private function returnJsonResponse(string $content): \Illuminate\Http\JsonResponse { return response()->json([ 'success' => true, 'result' => $content, ]); }
关键改进说明
- 上下文逻辑修复:通过
messageHistory数组完整保存对话流程,每次续写时明确告知模型基于已有内容延续 - 指令明确化:初始请求和续写请求都添加清晰要求,强制模型保持内容连贯性
- 字数控制优化:新增中英文兼容的单词统计方法,截断时优先按标点分割,避免破坏语句结构
- 代码结构优化:拆分工具方法,提升代码可读性和维护性
内容的提问来源于stack exchange,提问作者Kevin Otieno
相关产品推荐
相关产品推荐

