格式化

This commit is contained in:
Twilight 2024-07-25 01:26:40 +08:00
parent af6171f5fc
commit e879784209
17 changed files with 46 additions and 59 deletions

View File

@ -3,9 +3,7 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\LLM\Qwen; use App\LLM\Qwen;
use App\Models\Assistant;
use App\Models\Tool; use App\Models\Tool;
use App\Repositories\LLM\AIMessage;
use App\Repositories\LLM\ChatEnum; use App\Repositories\LLM\ChatEnum;
use App\Repositories\LLM\History; use App\Repositories\LLM\History;
use App\Repositories\LLM\HumanMessage; use App\Repositories\LLM\HumanMessage;
@ -30,6 +28,7 @@ class TestLLM extends Command
/** /**
* Execute the console command. * Execute the console command.
*
* @throws GuzzleException * @throws GuzzleException
*/ */
public function handle() public function handle()
@ -45,12 +44,12 @@ public function handle()
$llm->setHistory($history); $llm->setHistory($history);
while (true) { while (true) {
// var_dump($history->getMessages()); // var_dump($history->getMessages());
$q = $this->ask('请输入问题'); $q = $this->ask('请输入问题');
if (empty($q)) { if (empty($q)) {
$q = "北京天气"; $q = '北京天气';
} }
$history->addMessage(new HumanMessage($q)); $history->addMessage(new HumanMessage($q));
@ -60,12 +59,12 @@ public function handle()
foreach ($s as $item) { foreach ($s as $item) {
if ($item->role == ChatEnum::Tool) { if ($item->role == ChatEnum::Tool) {
if ($item->processing) { if ($item->processing) {
$this->info("正在执行: " . $item->content); $this->info('正在执行: '.$item->content);
echo "\n"; echo "\n";
} else { } else {
$this->info("执行结果: " . $item->content); $this->info('执行结果: '.$item->content);
} }
} else if ($item->role == ChatEnum::AssistantChunk) { } elseif ($item->role == ChatEnum::AssistantChunk) {
echo $item->getLastAppend(); echo $item->getLastAppend();
} }
} }

View File

@ -44,11 +44,10 @@ public function store(Request $request)
$json = Http::get($url); $json = Http::get($url);
$tool = new Tool(); $tool = new Tool();
$tool = $tool->create([ $tool = $tool->create([
'name' => "", 'name' => '',
'description' => "", 'description' => '',
'discovery_url' => $url, 'discovery_url' => $url,
'api_key' => $request->input('api_key'), 'api_key' => $request->input('api_key'),
'user_id' => $request->user('api')->id, 'user_id' => $request->user('api')->id,

View File

@ -1,14 +1,15 @@
<?php <?php
namespace App\LLM; namespace App\LLM;
use App\Repositories\LLM\History; use App\Repositories\LLM\History;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
interface BaseLLM interface BaseLLM
{ {
public function setHistory(History $history); public function setHistory(History $history);
public function setTools(Collection $tools); public function setTools(Collection $tools);
public function streamResponse(); public function streamResponse();
} }

View File

@ -21,6 +21,7 @@ class Qwen implements BaseLLM
private array $tool_info = []; private array $tool_info = [];
private Collection $tools; private Collection $tools;
private array $tool_functions = []; private array $tool_functions = [];
const END_OF_MESSAGE = "/\r\n\r\n|\n\n|\r\r/"; const END_OF_MESSAGE = "/\r\n\r\n|\n\n|\r\r/";
@ -69,17 +70,16 @@ public function streamResponse()
'Content-Type' => 'application/json', 'Content-Type' => 'application/json',
'Accept' => 'text/event-stream', 'Accept' => 'text/event-stream',
'Cache-Control' => 'no-cache', 'Cache-Control' => 'no-cache',
'Authorization' => 'Bearer ' . config('services.dashscope.api_key'), 'Authorization' => 'Bearer '.config('services.dashscope.api_key'),
], ],
]); ]);
$url = config('services.dashscope.api_base') . '/compatible-mode/v1/chat/completions'; $url = config('services.dashscope.api_base').'/compatible-mode/v1/chat/completions';
$this->request_again = true; $this->request_again = true;
while ($this->request_again) { while ($this->request_again) {
$ai_chunk_message = new AIChunkMessage(""); $ai_chunk_message = new AIChunkMessage('');
$request_body = [ $request_body = [
'model' => $this->model, 'model' => $this->model,
@ -97,7 +97,7 @@ public function streamResponse()
$buffer = ''; $buffer = '';
while (!$body->eof()) { while (! $body->eof()) {
$data = $body->read(1); $data = $body->read(1);
$buffer .= $data; $buffer .= $data;
@ -117,7 +117,6 @@ public function streamResponse()
break; break;
} }
if (empty($d)) { if (empty($d)) {
return; return;
} }
@ -129,7 +128,7 @@ public function streamResponse()
$ai_chunk_message->processing = false; $ai_chunk_message->processing = false;
$this->history->addMessage($ai_chunk_message->toAIMessage()); $this->history->addMessage($ai_chunk_message->toAIMessage());
break; break;
// yield $ai_chunk_message; // yield $ai_chunk_message;
} }
$delta = $event['choices'][0]['delta']; $delta = $event['choices'][0]['delta'];
@ -147,14 +146,13 @@ public function streamResponse()
$r = $this->callTool($this->tool_info['function']['name'], $info); $r = $this->callTool($this->tool_info['function']['name'], $info);
// $tool_response = [
// 'name' => $this->tool_info['function']['name'],
// 'role' => 'tool',
// 'content' => $r,
// ];
// $tool_response = [ $tool_call_message = new AIToolCallMessage(content: '');
// 'name' => $this->tool_info['function']['name'],
// 'role' => 'tool',
// 'content' => $r,
// ];
$tool_call_message = new AIToolCallMessage(content: "");
$tool_call_message->tool_calls = [ $tool_call_message->tool_calls = [
$this->tool_info, $this->tool_info,
]; ];
@ -167,15 +165,14 @@ public function streamResponse()
yield $tool_call_message; yield $tool_call_message;
yield $tool_response_message; yield $tool_response_message;
// //
// //
// //
// $this->history[] = $tool_response; // $this->history[] = $tool_response;
// yield new ToolResponseMessage(
// content: $tool_response_message->content,
// );
// yield new ToolResponseMessage(
// content: $tool_response_message->content,
// );
// 清空参数,以备二次调用 // 清空参数,以备二次调用
$this->clearToolInfo(); $this->clearToolInfo();
@ -202,7 +199,7 @@ public function streamResponse()
$this->tool_info['function']['arguments'] .= $call_info['function']['arguments']; $this->tool_info['function']['arguments'] .= $call_info['function']['arguments'];
} }
} elseif (empty($delta['choices'][0]['finish_reason'])) { } elseif (empty($delta['choices'][0]['finish_reason'])) {
if (!empty($delta['content'])) { if (! empty($delta['content'])) {
$ai_chunk_message->append($delta['content']); $ai_chunk_message->append($delta['content']);
$ai_chunk_message->processing = true; $ai_chunk_message->processing = true;
@ -214,12 +211,10 @@ public function streamResponse()
} }
$buffer = ''; $buffer = '';
} }
} }
} }
} }
@ -240,7 +235,6 @@ private function callTool($tool_name, $args): string
} }
return "[Hint] 没有找到对应的工具 " . $tool_name . ',你确定是这个吗?'; return '[Hint] 没有找到对应的工具 '.$tool_name.',你确定是这个吗?';
} }
} }

View File

@ -36,7 +36,7 @@ public function callTool(string $function_name, $parameters = []): FunctionCall
$r->name = $function_name; $r->name = $function_name;
$r->parameters = $parameters; $r->parameters = $parameters;
if (!$http->ok()) { if (! $http->ok()) {
$r->success = false; $r->success = false;
$r->result = "[Error] 我们的服务器与工具 $function_name 通讯失败"; $r->result = "[Error] 我们的服务器与工具 $function_name 通讯失败";
} }
@ -44,9 +44,10 @@ public function callTool(string $function_name, $parameters = []): FunctionCall
$d = $http->json(); $d = $http->json();
// 必须有 success 和 message 两个 // 必须有 success 和 message 两个
if (!isset($d['success']) || !isset($d['message'])) { if (! isset($d['success']) || ! isset($d['message'])) {
$r->success = false; $r->success = false;
$r->result = "[Error] 和 工具 $function_name 通讯失败,返回数据格式错误。"; $r->result = "[Error] 和 工具 $function_name 通讯失败,返回数据格式错误。";
return $r; return $r;
} }

View File

@ -5,7 +5,8 @@
class AIChunkMessage extends BaseMessage class AIChunkMessage extends BaseMessage
{ {
public ChatEnum $role = ChatEnum::AssistantChunk; public ChatEnum $role = ChatEnum::AssistantChunk;
protected string $last_append = "";
protected string $last_append = '';
public function toAIMessage(): AIMessage public function toAIMessage(): AIMessage
{ {

View File

@ -4,9 +4,7 @@
class AIToolCallMessage extends BaseMessage class AIToolCallMessage extends BaseMessage
{ {
public ChatEnum $role = ChatEnum::Assistant; public ChatEnum $role = ChatEnum::Assistant;
public array $tool_calls; public array $tool_calls;
} }

View File

@ -5,6 +5,7 @@
class BaseMessage class BaseMessage
{ {
public string $content; public string $content;
public bool $processing = false; public bool $processing = false;
public function __construct(string $content) public function __construct(string $content)
@ -12,7 +13,6 @@ public function __construct(string $content)
$this->content = $content; $this->content = $content;
} }
public function append(string $content): void public function append(string $content): void
{ {
$this->content .= $content; $this->content .= $content;
@ -27,5 +27,4 @@ public function __toString(): string
{ {
return $this->content; return $this->content;
} }
} }

View File

@ -30,7 +30,6 @@ public function getForApi(): array
{ {
$history = []; $history = [];
foreach ($this->history as $h) { foreach ($this->history as $h) {
$a = [ $a = [
@ -47,6 +46,4 @@ public function getForApi(): array
return $history; return $history;
} }
} }

View File

@ -5,7 +5,4 @@
class HumanMessage extends BaseMessage class HumanMessage extends BaseMessage
{ {
public ChatEnum $role = ChatEnum::Human; public ChatEnum $role = ChatEnum::Human;
} }

View File

@ -2,8 +2,7 @@
namespace App\Repositories\LLM; namespace App\Repositories\LLM;
class ToolMessage extends BaseMessage class ToolMessage extends BaseMessage
{ {
public ChatEnum $role = ChatEnum::Tool; public ChatEnum $role = ChatEnum::Tool;
} }

View File

@ -2,8 +2,9 @@
namespace App\Repositories\LLM; namespace App\Repositories\LLM;
class ToolRequestMessage extends BaseMessage class ToolRequestMessage extends BaseMessage
{ {
public ChatEnum $role = ChatEnum::Tool; public ChatEnum $role = ChatEnum::Tool;
public bool $processing = true; public bool $processing = true;
} }

View File

@ -7,6 +7,6 @@ class ToolResponseMessage extends BaseMessage
public ChatEnum $role = ChatEnum::Tool; public ChatEnum $role = ChatEnum::Tool;
public bool $requesting = false; public bool $requesting = false;
public string $name;
public string $name;
} }

View File

@ -13,6 +13,7 @@ class Tool
public string $callback_url; public string $callback_url;
public string $description; public string $description;
public int $tool_id; public int $tool_id;
public array $tool_functions; public array $tool_functions;

View File

@ -16,6 +16,7 @@ class ToolFunction
protected array $data; protected array $data;
public array $required; public array $required;
/** /**
* Create a new class instance. * Create a new class instance.
* *
@ -33,7 +34,7 @@ public function __construct(array $data)
private function parse(): void private function parse(): void
{ {
$random_str = Str::random(config('settings.function_call.random_prefix_length')); $random_str = Str::random(config('settings.function_call.random_prefix_length'));
$this->name = $random_str . '_' . $this->data['name']; $this->name = $random_str.'_'.$this->data['name'];
$this->description = $this->data['description']; $this->description = $this->data['description'];
// 如果 parameters 不为空,则验证 // 如果 parameters 不为空,则验证

View File

@ -40,5 +40,4 @@
'api_base' => env('DASHSCOPE_API_BASE', 'https://dashscope.aliyuncs.com'), 'api_base' => env('DASHSCOPE_API_BASE', 'https://dashscope.aliyuncs.com'),
], ],
]; ];

View File

@ -3,6 +3,6 @@
return [ return [
'function_call' => [ 'function_call' => [
// 防止命名冲突的随机长度,如果你更改了它,则需要更新全部函数的 name // 防止命名冲突的随机长度,如果你更改了它,则需要更新全部函数的 name
'random_prefix_length' => 8 'random_prefix_length' => 8,
] ],
]; ];