From cd3a01bfc138ebeea1f43e9317a1b0a8a7225abf Mon Sep 17 00:00:00 2001 From: Twilight Date: Thu, 25 Jul 2024 15:05:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E4=BF=A1=E6=81=AF=E4=BC=A0=E9=80=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Api/ChatHistoryController.php | 9 ++++-- app/LLM/BaseLLM.php | 2 ++ app/LLM/Qwen.php | 31 ++++++++++++++----- app/Logic/LLMTool.php | 28 +++++++++++++++-- app/Repositories/LLM/FunctionCall.php | 4 +++ 5 files changed, 62 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/Api/ChatHistoryController.php b/app/Http/Controllers/Api/ChatHistoryController.php index 4e71635..8bade17 100644 --- a/app/Http/Controllers/Api/ChatHistoryController.php +++ b/app/Http/Controllers/Api/ChatHistoryController.php @@ -8,6 +8,7 @@ use App\Repositories\LLM\ChatEnum; use App\Repositories\LLM\History; use App\Repositories\LLM\HumanMessage; +use GuzzleHttp\Exception\GuzzleException; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Log; @@ -103,14 +104,18 @@ public function stream(string $stream_id) $tools = $chat->assistant->tools()->get(); $llm->setTools($tools); - $llm->setHistory($history); + $llm->setUser($chat->user); $last_human_message = $histories[$histories->count() - 1]; $history->addMessage(new HumanMessage($last_human_message)); - $stream = $llm->streamResponse(); + try { + $stream = $llm->streamResponse(); + } catch (GuzzleException) { + return $this->badRequest('请求失败,请重试。'); + } $response = response()->stream(function () use (&$stream, &$chat) { // 循环输出 diff --git a/app/LLM/BaseLLM.php b/app/LLM/BaseLLM.php index 82feeeb..046fa67 100644 --- a/app/LLM/BaseLLM.php +++ b/app/LLM/BaseLLM.php @@ -2,6 +2,7 @@ namespace App\LLM; +use App\Models\User; use App\Repositories\LLM\History; use Illuminate\Database\Eloquent\Collection; @@ -10,6 +11,7 @@ interface BaseLLM public function setHistory(History $history); public function setTools(Collection $tools); + public function setUser(User $user); public function streamResponse(); } diff --git a/app/LLM/Qwen.php b/app/LLM/Qwen.php index 6560c0d..63fa14d 100644 --- a/app/LLM/Qwen.php +++ b/app/LLM/Qwen.php @@ -3,6 +3,7 @@ namespace App\LLM; use App\Logic\LLMTool; +use App\Models\User; use App\Repositories\LLM\AIChunkMessage; use App\Repositories\LLM\AIToolCallMessage; use App\Repositories\LLM\History; @@ -12,6 +13,7 @@ use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Exception\GuzzleException; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Http\Client\ConnectionException; use Illuminate\Support\Facades\Log; class Qwen implements BaseLLM @@ -30,7 +32,7 @@ class Qwen implements BaseLLM private bool $retry = false; - private int $retires = 0; + private User $user; public function __construct() { @@ -55,6 +57,11 @@ public function setHistory(History $history): void $this->history = $history; } + public function setUser(User $user): void + { + $this->user = $user; + } + public function setTools(Collection $tools): void { $this->tools = $tools; @@ -137,7 +144,7 @@ public function streamResponse() // log $event = json_decode($d, true); - Log::debug('event', $event); +// Log::debug('event', $event); if (isset($event['choices'][0])) { $finish_reason = $event['choices'][0]['finish_reason']; @@ -148,12 +155,12 @@ public function streamResponse() $this->history->addMessage($ai_message); yield $ai_message; - Log::debug('stop!'); +// Log::debug('stop!'); break; } elseif ($finish_reason == 'tool_calls') { $this->retry = true; - Log::debug('finished_reason is tool call, set retry'); +// Log::debug('finished_reason is tool call, set retry'); } $delta = $event['choices'][0]['delta']; @@ -172,7 +179,7 @@ public function streamResponse() yield $tool_req; - Log::debug('tool req', [$tool_req]); +// Log::debug('tool req', [$tool_req]); $tool_call_message = new AIToolCallMessage(content: ''); $tool_call_message->tool_calls = [ @@ -188,8 +195,8 @@ public function streamResponse() $this->history->addMessage($tool_call_message); $this->history->addMessage($tool_response_message); - Log::debug('tool call message', [$tool_call_message]); - Log::debug('tool response', [$tool_response_message]); +// Log::debug('tool call message', [$tool_call_message]); +// Log::debug('tool response', [$tool_response_message]); yield $tool_call_message; yield $tool_response_message; @@ -222,7 +229,7 @@ public function streamResponse() yield $ai_chunk_message; - Log::debug('chunk', [$ai_chunk_message]); +// Log::debug('chunk', [$ai_chunk_message]); } $this->retry = false; @@ -240,6 +247,9 @@ public function streamResponse() } + /** + * @throws ConnectionException + */ private function callTool($tool_name, $args): string { // 遍历 tools, 找到 @@ -248,6 +258,11 @@ private function callTool($tool_name, $args): string if ($f['function']['name'] == $tool_name) { $c = new LLMTool(); $c->setTool($tool->data['tool_id']); + + if (isset($this->user)) { + $c->setUser($this->user); + } + $r = $c->callTool($tool_name, $args); return $r->result; diff --git a/app/Logic/LLMTool.php b/app/Logic/LLMTool.php index 70e5da8..bd3f0ea 100644 --- a/app/Logic/LLMTool.php +++ b/app/Logic/LLMTool.php @@ -3,6 +3,7 @@ namespace App\Logic; use App\Models\Tool; +use App\Models\User; use App\Repositories\LLM\FunctionCall; use Illuminate\Http\Client\ConnectionException; use Illuminate\Support\Facades\Http; @@ -10,12 +11,18 @@ class LLMTool { protected Tool $tool; + protected User $user; public function setTool(int $tool_id): void { $this->tool = Tool::findOrFail($tool_id); } + public function setUser(User $user):void + { + $this->user = $user; + } + /** * @throws ConnectionException */ @@ -27,15 +34,32 @@ public function callTool(string $function_name, $parameters = []): FunctionCall $function_name = substr($function_name, $prefix_length); - $http = Http::withToken($this->tool->api_key)->post($this->tool->data['callback_url'], [ + $data = [ 'function_name' => $function_name, 'parameters' => $parameters, - ]); + 'user' => [], + ]; $r = new FunctionCall(); $r->name = $function_name; $r->parameters = $parameters; + if (empty($this->tool->api_key)) { + $r->success = false; + $r->result = "[Error] 没有找到 API KEY,请先在工具设置中设置 API KEY。"; + + return $r; + } + + if (!empty($this->user)) { + $data['user'] = [ + 'id' => $this->user->external_id, + 'name' => $this->user->name + ]; + } + + $http = Http::withToken($this->tool->api_key)->post($this->tool->data['callback_url'], $data); + if (! $http->ok()) { $r->success = false; $r->result = "[Error] 我们的服务器与工具 $function_name 通讯失败"; diff --git a/app/Repositories/LLM/FunctionCall.php b/app/Repositories/LLM/FunctionCall.php index bf29d7c..7cb6c3f 100644 --- a/app/Repositories/LLM/FunctionCall.php +++ b/app/Repositories/LLM/FunctionCall.php @@ -2,6 +2,8 @@ namespace App\Repositories\LLM; +use App\Models\User; + class FunctionCall { public string $name; @@ -11,4 +13,6 @@ class FunctionCall public bool $success; public string $result; + + public User $user; }