Rollback to OpenAI API
This commit is contained in:
parent
56f22c1b58
commit
efe9d2bd49
|
@ -13,7 +13,7 @@ use Mails\CustomEmail;
|
|||
use Models\Memory;
|
||||
use Models\User;
|
||||
use OpenAI;
|
||||
use OpenAI\Responses\Chat\CreateResponse;
|
||||
use OpenAI\Responses\Chat\CreateStreamedResponse;
|
||||
use Symfony\Component\HttpClient\HttpClient;
|
||||
|
||||
class ChatController extends BaseController
|
||||
|
@ -104,19 +104,18 @@ class ChatController extends BaseController
|
|||
foreach ($r->choices as $data) {
|
||||
|
||||
$allowed_role = ['user', 'system', 'assistant', 'tool'];
|
||||
if (!in_array($data->message->role, $allowed_role)) continue;
|
||||
if (!in_array($data->delta->role, $allowed_role)) continue;
|
||||
|
||||
if ($data->message->role == 'tool') {
|
||||
if ($data->delta->role == 'tool' || !empty($data->delta->toolCalls)) {
|
||||
self::$context_messages[] = [
|
||||
'tool_call_id' => $data->tool_call_id,
|
||||
'name' => $data->message->name,
|
||||
'role' => $data->message->role,
|
||||
'content' => $data->message->content,
|
||||
'toolCalls' => $data->delta->toolCalls,
|
||||
'role' => $data->delta->role,
|
||||
'content' => $data->delta->content,
|
||||
];
|
||||
} else {
|
||||
self::$context_messages[] = [
|
||||
'role' => $data->message->role,
|
||||
'content' => $data->message->content,
|
||||
'role' => $data->delta->role,
|
||||
'content' => $data->delta->content,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -152,20 +151,20 @@ class ChatController extends BaseController
|
|||
{
|
||||
try {
|
||||
// self::$client = OpenAI::client(config('chat.key'));
|
||||
// self::$client = OpenAI::factory()
|
||||
// ->withBaseUri(config("chat.base_uri", "api.openai.com/v1"))
|
||||
// ->withApiKey(config('chat.key'))
|
||||
// ->withHttpClient($client = new \GuzzleHttp\Client([])) // default: HTTP client found using PSR-18 HTTP Client Discovery
|
||||
// ->withHttpHeader('OpenAI-Beta', 'assistants=v1')
|
||||
// ->make();
|
||||
self::$client = new \GuzzleHttp\Client([
|
||||
'base_uri' => config("chat.base_uri", "https://api.openai.com/v1"),
|
||||
"headers" => [
|
||||
"Authorization" => "Bearer " . config('chat.key'),
|
||||
'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
]
|
||||
]);
|
||||
self::$client = OpenAI::factory()
|
||||
// ->withBaseUri(config("chat.base_uri", "api.openai.com/v1"))
|
||||
->withApiKey(config('chat.key'))
|
||||
->withHttpClient($client = new \GuzzleHttp\Client([])) // default: HTTP client found using PSR-18 HTTP Client Discovery
|
||||
->withHttpHeader('OpenAI-Beta', 'assistants=v1')
|
||||
->make();
|
||||
// self::$client = new \GuzzleHttp\Client([
|
||||
// 'base_uri' => config("chat.base_uri", "https://api.openai.com/v1"),
|
||||
// "headers" => [
|
||||
// "Authorization" => "Bearer " . config('chat.key'),
|
||||
// 'accept' => 'application/json',
|
||||
// 'Content-Type' => 'application/json',
|
||||
// ]
|
||||
// ]);
|
||||
|
||||
|
||||
if (!Helper::isCLI()) {
|
||||
|
@ -650,99 +649,65 @@ class ChatController extends BaseController
|
|||
}
|
||||
|
||||
self::$NB_REQUEST++;
|
||||
// $result = self::$client->chat()->create([
|
||||
// 'model' => config('chat.model'),
|
||||
// 'messages' => (array)self::$context_messages,
|
||||
// 'tools' => (array)self::$tools,
|
||||
// 'user' => Helper::isCLI() ? "system" : Auth::user()->username,
|
||||
// ]);
|
||||
$stream = self::$client->chat()->createStreamed([
|
||||
'model' => config('chat.model'),
|
||||
'messages' => (array)self::$context_messages,
|
||||
'tools' => (array)self::$tools,
|
||||
'user' => Helper::isCLI() ? "system" : Auth::user()->username,
|
||||
]);
|
||||
|
||||
ob_implicit_flush(1); // Enable implicit flush
|
||||
ob_end_flush(); // Flush the buffer
|
||||
|
||||
// Use guzzle HTTP directly
|
||||
$response = self::$client->post('v1/completions', [
|
||||
'stream' => true,
|
||||
'timeout' => 0,
|
||||
'json' => [
|
||||
'model' => config('chat.model'),
|
||||
// 'messages' => (array)self::$context_messages,
|
||||
// 'tools' => (array)self::$tools,
|
||||
// 'user' => Helper::isCLI() ? "system" : Auth::user()->username,
|
||||
"prompt" => implode("\n", array_map(function ($message) {
|
||||
$text = "";
|
||||
if ($message['role'] === "user") {
|
||||
if (Auth::check()) {
|
||||
$text = "### Instruction:\n" . Auth::user()->username . ": ";
|
||||
} else {
|
||||
$text = "### Instruction:\n";
|
||||
}
|
||||
} elseif ($message['role'] === "system") {
|
||||
$text = "### Context:\n";
|
||||
} elseif ($message['role'] === "assistant") {
|
||||
$text = "### Response:\n";
|
||||
} // elseif TODO Handle tool
|
||||
|
||||
// Clean extra whitespaces
|
||||
$message['content'] = preg_replace('/\s+/', ' ', trim($message['content']));
|
||||
$text .= $message['content'];
|
||||
|
||||
|
||||
return $text;
|
||||
}, self::$context_messages)) . "\n### Response:\nScotty: ",
|
||||
"max_tokens" => 150,
|
||||
"temperature" => 0.5,
|
||||
"top_p" => 0.3,
|
||||
"top_k" => 20,
|
||||
"n" => 1,
|
||||
"stream" => true,
|
||||
"repeat_penalty" => 1.8
|
||||
]
|
||||
]);
|
||||
|
||||
$body = $response->getBody();
|
||||
$jsonBuffer = '';
|
||||
$concatened_final_data = null;
|
||||
foreach($stream as $chunk) {
|
||||
|
||||
while (!$body->eof()) {
|
||||
$chunk = $body->read(1024);
|
||||
$jsonBuffer .= $chunk;
|
||||
|
||||
// Each chunk return data like:
|
||||
// data: (json object)
|
||||
// Each new "data:" prefix is a new chunk of data
|
||||
// So we can split the buffer by "data:" to get each json object
|
||||
// also each chunk can have multiple json objects, so we can split by "\n" to get each json object
|
||||
// or incomplete json object
|
||||
// Convert to object
|
||||
$chunk = (object)(array) $chunk;
|
||||
foreach($chunk->choices as &$choice) {
|
||||
$choice = (object)(array) $choice;
|
||||
$choice->delta = (object)(array) $choice->delta;
|
||||
$choice->delta->toolCalls = (array) $choice->delta->toolCalls;
|
||||
foreach($choice->delta->toolCalls as &$toolCall) {
|
||||
$toolCall = (object)(array) $toolCall;
|
||||
$toolCall->function = (object)(array) $toolCall->function;
|
||||
}
|
||||
}
|
||||
|
||||
$jsonObjects = explode("data: ", $jsonBuffer);
|
||||
foreach ($jsonObjects as $jsonObject) {
|
||||
$baseJsonObject = $jsonObject;
|
||||
if (empty($jsonObject)) continue;
|
||||
|
||||
$jsonObject = json_decode($jsonObject, true);
|
||||
if (empty($jsonObject)) continue;
|
||||
|
||||
$result = $this->handleResponse($jsonObject);
|
||||
if(empty($concatened_final_data)) {
|
||||
$concatened_final_data = $result;
|
||||
} else {
|
||||
$concatened_final_data[0]->choices[0]->text .= $result[0]->choices[0]->text;
|
||||
if(empty($concatened_final_data)) {
|
||||
$concatened_final_data = $chunk;
|
||||
} else {
|
||||
if(!empty($chunk->choices[0]->delta->role)) {
|
||||
$concatened_final_data->choices[0]->delta->role .= $chunk->choices[0]->delta->role;
|
||||
}else{
|
||||
$chunk->choices[0]->delta->role = $concatened_final_data->choices[0]->delta->role;
|
||||
}
|
||||
|
||||
// Traiter l'objet JSON
|
||||
$streamResponse = "::end:: " . json_encode([
|
||||
'success' => true,
|
||||
'stream' => true,
|
||||
'id' => $jsonObject['id'],
|
||||
'result' => $result,
|
||||
]) . " ";
|
||||
if(!empty($concatened_final_data->choices[0]->delta->content)) {
|
||||
$concatened_final_data->choices[0]->delta->content .= $chunk->choices[0]->delta->content;
|
||||
}
|
||||
|
||||
echo $streamResponse;
|
||||
// For each toolsCalls, we need to merge the data
|
||||
foreach($chunk->choices[0]->delta->toolCalls as $toolCallIndex => $toolCall) {
|
||||
if(!empty($concatened_final_data->choices[0]->delta->toolCalls[$toolCallIndex])) {
|
||||
$concatened_final_data->choices[0]->delta->toolCalls[$toolCallIndex]->function->arguments .= $toolCall->function->arguments;
|
||||
} else {
|
||||
$concatened_final_data->choices[0]->delta->toolCalls[] = $toolCall;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the data json object from the buffer
|
||||
$jsonBuffer = str_replace("data: " . $baseJsonObject, "", $jsonBuffer);
|
||||
$concatened_final_data->choices[0]->finishReason .= $chunk->choices[0]->finishReason;
|
||||
}
|
||||
|
||||
$streamResponse = "::end:: " . json_encode([
|
||||
'success' => true,
|
||||
'stream' => true,
|
||||
'id' => $chunk->id,
|
||||
'result' => [$chunk],
|
||||
]) . " ";
|
||||
|
||||
echo $streamResponse;
|
||||
|
||||
}
|
||||
|
||||
return $this->handleResponse($concatened_final_data);
|
||||
|
@ -754,25 +719,11 @@ class ChatController extends BaseController
|
|||
private function handleResponse($response)
|
||||
{
|
||||
|
||||
if (empty($response) || !is_array($response)) {
|
||||
if (empty($response)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$message = $response['choices'][0]['text'];
|
||||
return [
|
||||
(object)[
|
||||
"choices" => [
|
||||
(object)[
|
||||
"message" => (object)[
|
||||
"role" => "assistant",
|
||||
"content" => $message,
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
// TODO: Handle tool
|
||||
$message = $response->choices[0]->delta;
|
||||
$results = [];
|
||||
|
||||
if ($message) {
|
||||
|
|
|
@ -241,6 +241,7 @@ View::set('title', __('home'));
|
|||
// Then parse each message
|
||||
|
||||
// Splitting the chunk into messages
|
||||
console.log(textDecoder.decode(value));
|
||||
const json_responses = (textDecoder.decode(value)).split('::end::');
|
||||
|
||||
// Parsing each message
|
||||
|
@ -286,8 +287,8 @@ View::set('title', __('home'));
|
|||
const messageId = data.id;
|
||||
data.result.forEach((r) => {
|
||||
r.choices.forEach((data) => {
|
||||
if (data.message && data.message.content) {
|
||||
currentCloneMessage = addMessage(data.message.role, data.message.content, messageId);
|
||||
if (data.delta.content && data.delta.content) {
|
||||
currentCloneMessage = addMessage(data.delta.role, data.delta.content, messageId);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue