...
|
...
|
@@ -16,6 +16,7 @@ |
|
|
*/
|
|
|
namespace App\Models\Traits;
|
|
|
|
|
|
use App\Jobs\ChatRecordItemJob;
|
|
|
use App\Models\Chat\ChatRecordItem;
|
|
|
use App\Models\System\SystemSetting;
|
|
|
use App\Models\User\TimesRecord;
|
...
|
...
|
@@ -190,9 +191,17 @@ trait ChatTrait |
|
|
* @param string $type
|
|
|
* @return string
|
|
|
*/
|
|
|
public static function sendRequest($open_ai, $send_data, $type = 'stream')
|
|
|
public static function sendRequest1($open_ai, $send_data, $type = 'stream')
|
|
|
{
|
|
|
$answer = '';
|
|
|
if($type === 'general') {
|
|
|
$response = $open_ai->chatCompletions()->create(
|
|
|
new \Tectalic\OpenAi\Models\ChatCompletions\CreateRequest($send_data)
|
|
|
)->toModel();
|
|
|
|
|
|
$answer = $response->choices[0]->message->content;
|
|
|
} else {
|
|
|
|
|
|
if ($type === 'chunked') {
|
|
|
// 设置响应头信息
|
|
|
header('Access-Control-Allow-Credentials: true');
|
...
|
...
|
@@ -213,6 +222,11 @@ trait ChatTrait |
|
|
// header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
|
|
|
// header('Access-Control-Allow-Headers: Content-Type');
|
|
|
// header('Connection: keep-alive');
|
|
|
} elseif ($type === 'stream') {
|
|
|
header('Content-type: text/event-stream');
|
|
|
header('Cache-Control: no-cache');
|
|
|
ob_end_flush();
|
|
|
}
|
|
|
$complete = $open_ai->chat($send_data, function ($curl_info, $response) use (&$answer) {
|
|
|
//闭包函数处理流
|
|
|
$data = [];
|
...
|
...
|
@@ -234,6 +248,8 @@ trait ChatTrait |
|
|
$content = $message['choices'][0]['delta']['content'] ?? '';
|
|
|
$answer .= $content;
|
|
|
// record_log('openai', '内容: ' . $content );
|
|
|
// echo str_replace("\n", "\\n", $content )."\n\n";
|
|
|
dump($content);
|
|
|
echo urlencode($content) . "\r\n";
|
|
|
}
|
|
|
}
|
...
|
...
|
@@ -241,47 +257,145 @@ trait ChatTrait |
|
|
flush();
|
|
|
return strlen($response);
|
|
|
});
|
|
|
} elseif ($type === 'stream') {
|
|
|
header('Content-type: text/event-stream');
|
|
|
}
|
|
|
|
|
|
return $answer;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 发送请求
|
|
|
* @param $open_ai
|
|
|
* @param $send_data
|
|
|
* @param string $type
|
|
|
* @return string
|
|
|
*/
|
|
|
public static function sendRequest($open_ai, $send_data, $type = 'stream')
|
|
|
{
|
|
|
$answer = '';
|
|
|
if ($type === 'chunked') {
|
|
|
// 设置响应头信息
|
|
|
header('Access-Control-Allow-Credentials: true');
|
|
|
// 设置响应头信息
|
|
|
header('Transfer-Encoding: chunked');
|
|
|
header('Cache-Control: no-cache');
|
|
|
ob_end_flush();
|
|
|
$complete = $open_ai->chat($send_data, function ($curl_info, $data) use (&$answer) {
|
|
|
// record_log($this->log_channel, '开始请求' );
|
|
|
header('Access-Control-Allow-Origin: *');
|
|
|
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
|
|
|
header('Access-Control-Allow-Headers: Content-Type');
|
|
|
header('Connection: keep-alive');
|
|
|
header('X-Accel-Buffering: no');
|
|
|
|
|
|
$deltas = explode("\n", $data);
|
|
|
$content = '';
|
|
|
foreach ($deltas as $delta) {
|
|
|
if (strpos($delta, 'data: ') !== 0) {
|
|
|
// header('Access-Control-Allow-Credentials: true');
|
|
|
// // 设置响应头信息
|
|
|
// header('Transfer-Encoding: chunked');
|
|
|
// header('Content-Type: text/plain');
|
|
|
// header('Cache-Control: no-cache');
|
|
|
// header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
|
|
|
// header('Access-Control-Allow-Headers: Content-Type');
|
|
|
// header('Connection: keep-alive');
|
|
|
$complete = $open_ai->chat($send_data, function ($curl_info, $response) use (&$answer) {
|
|
|
//闭包函数处理流
|
|
|
$data = [];
|
|
|
$lines = explode("\n", $response);
|
|
|
foreach ($lines as $line) {
|
|
|
if (!str_contains($line, ':')) {
|
|
|
continue;
|
|
|
}
|
|
|
$json = json_decode(substr($delta, 6));
|
|
|
if (isset($json->choices[0]->delta)) {
|
|
|
$content = $json->choices[0]->delta->content ?? "";
|
|
|
$answer .= $content;
|
|
|
} elseif (isset($json->error->message)) {
|
|
|
$content = $json->error->message;
|
|
|
} elseif(trim($delta) == "data: [DONE]") {
|
|
|
$content = " ";
|
|
|
[$name, $value] = explode(':', $line, 2);
|
|
|
if ($name == 'data') {
|
|
|
$data[] = trim($value);
|
|
|
}
|
|
|
}
|
|
|
foreach ($data as $message) {
|
|
|
if ('[DONE]' === $message) {
|
|
|
echo "0\r\n\r\n";
|
|
|
} else {
|
|
|
$content = "对不起,我不知道怎么去回答。";
|
|
|
$message = json_decode($message, true);
|
|
|
$content = $message['choices'][0]['delta']['content'] ?? '';
|
|
|
$answer .= $content;
|
|
|
// record_log('openai', '内容: ' . $content );
|
|
|
echo urlencode($content) . "\r\n";
|
|
|
}
|
|
|
echo str_replace("\n", "\\n", $content )."\n\n";
|
|
|
}
|
|
|
ob_flush();
|
|
|
flush();
|
|
|
return strlen($response);
|
|
|
});
|
|
|
} elseif ($type === 'stream') {
|
|
|
header('Content-type: text/event-stream');
|
|
|
header('Cache-Control: no-cache');
|
|
|
$complete = $open_ai->chat($send_data, function ($curl_info, $response) use (&$answer) {
|
|
|
//闭包函数处理流
|
|
|
$data = [];
|
|
|
$lines = explode("\n", $response);
|
|
|
foreach ($lines as $line) {
|
|
|
if (!str_contains($line, ':')) {
|
|
|
continue;
|
|
|
}
|
|
|
[$name, $value] = explode(':', $line, 2);
|
|
|
if ($name == 'data') {
|
|
|
$data[] = trim($value);
|
|
|
}
|
|
|
}
|
|
|
foreach ($data as $message) {
|
|
|
if ('[DONE]' === $message) {
|
|
|
echo "0\r\n\r\n";
|
|
|
} else {
|
|
|
$message = json_decode($message, true);
|
|
|
$content = $message['choices'][0]['delta']['content'] ?? '';
|
|
|
$answer .= $content;
|
|
|
// record_log('openai', '内容: ' . $content );
|
|
|
// echo urlencode($content) . "\r\n";
|
|
|
echo str_replace("\n", "\\n", $content )."\n\n";
|
|
|
|
|
|
// record_log($this->log_channel, '内容: ' . $content );
|
|
|
|
|
|
if (connection_aborted()) {
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
echo PHP_EOL;
|
|
|
|
|
|
// echo PHP_EOL;
|
|
|
// ob_flush();
|
|
|
return strlen($data);
|
|
|
ob_flush();
|
|
|
flush();
|
|
|
return strlen($response);
|
|
|
});
|
|
|
|
|
|
echo "event: stop\n";
|
|
|
echo "data: stopped\n\n";
|
|
|
|
|
|
// ob_end_flush();
|
|
|
// $complete = $open_ai->chat($send_data, function ($curl_info, $data) use (&$answer) {
|
|
|
// record_log($this->log_channel, '开始请求' );
|
|
|
//
|
|
|
// $deltas = explode("\n", $data);
|
|
|
// $content = '';
|
|
|
// foreach ($deltas as $delta) {
|
|
|
// if (strpos($delta, 'data: ') !== 0) {
|
|
|
// continue;
|
|
|
// }
|
|
|
// $json = json_decode(substr($delta, 6));
|
|
|
// if (isset($json->choices[0]->delta)) {
|
|
|
// $content = $json->choices[0]->delta->content ?? "";
|
|
|
// $answer .= $content;
|
|
|
// } elseif (isset($json->error->message)) {
|
|
|
// $content = $json->error->message;
|
|
|
// } elseif(trim($delta) == "data: [DONE]") {
|
|
|
// $content = " ";
|
|
|
// } else {
|
|
|
// $content = "对不起,我不知道怎么去回答。";
|
|
|
// }
|
|
|
//// echo "data: " .str_replace("\n", "\\n", $content )."\n\n";
|
|
|
// echo str_replace("\n", "\\n", $content )."\n\n";
|
|
|
// flush();
|
|
|
// }
|
|
|
//
|
|
|
// record_log($this->log_channel, '内容: ' . $content );
|
|
|
//
|
|
|
// if (connection_aborted()) {
|
|
|
// return 0;
|
|
|
// }
|
|
|
//
|
|
|
//// echo PHP_EOL;
|
|
|
//// ob_flush();
|
|
|
// return strlen($data);
|
|
|
// });
|
|
|
//
|
|
|
// echo "event: stop\n";
|
|
|
// echo "data: stopped\n\n";
|
|
|
} elseif($type === 'general') {
|
|
|
$response = $open_ai->chatCompletions()->create(
|
|
|
new \Tectalic\OpenAi\Models\ChatCompletions\CreateRequest($send_data)
|
...
|
...
|
|