Skip to content

Commit

Permalink
Merge branch 'main' of github.com:kuwaai/genai-os
Browse files Browse the repository at this point in the history
  • Loading branch information
ifTNT committed Apr 14, 2024
2 parents d07ace1 + 5407a3c commit 5ede83e
Show file tree
Hide file tree
Showing 10 changed files with 678 additions and 1,666 deletions.
131 changes: 85 additions & 46 deletions src/multi-chat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,89 +91,82 @@ For Windows you need to escape these characters, here's how to do it:
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer YOUR_AUTH_TOKEN" -d "{\"messages\": [{ \"isbot\": false, \"msg\": \"請自我介紹\" }],\"model\": \"gemini-pro\"}" http://127.0.0.1/v1.0/chat/completions
```

### Using JavaScript (Ajax)
### Using JavaScript

You can also use JavaScript and the `fetch` API to send a single message to our API.
You can also use JavaScript and the `fetch` API to send message to our API.
```javascript
// Define the request payload as an object.
// Define the data to be sent in the request
const requestData = {
messages: [
{ isbot: false, msg: "請自我介紹" }
{ isbot: false, msg: "請自我介紹" } // Requesting a self-introduction
],
model: "gemini-pro"
model: "gemini-pro" // Using the Gemini Pro model
};

// Define the API endpoint and authentication headers.
const apiUrl = 'http://127.0.0.1/v1.0/chat/completions';
// API endpoint for the request
const apiUrl = 'http://localhost/v1.0/chat/completions';

// Headers for the request, including authorization
const headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_AUTH_TOKEN'
};

// Perform the AJAX request using the fetch API.
// Initialize an empty output variable
var output = ""

// Make a POST request to the API
fetch(apiUrl, {
method: 'POST',
headers: headers,
body: JSON.stringify(requestData)
body: JSON.stringify(requestData) // Send the requestData as JSON
})
.then(response => {
if (!response.body) {
throw new Error('ReadableStream not supported');
}

// Create a reader for the response stream.
// Get a ReadableStream from the response
const reader = response.body.getReader();

// Function to read the stream and concatenate chunks.
function readStream(reader, buffer = "") {
let buffer = "";
function readStream() {
return reader.read().then(({ done, value }) => {
if (done) {
// Handle the last chunk and end the stream.
handleStreamData(buffer);
console.log("Stream ended");
return;
}

// Convert the chunk to a string.
const chunk = new TextDecoder().decode(value);

// Split the chunk into lines.
const lines = (buffer + chunk).split("data:");

// Process each line.
lines.forEach(line => {
if (line.trim() !== "") {
// Handle the current line (remove any leading/trailing whitespace).
handleStreamData(line.trim());
buffer += chunk;

// Process the buffer in chunks until it contains complete JSON objects
while (buffer.includes("}\n")) {
const endIndex = buffer.indexOf("}\n") + 2;
const jsonStr = buffer.substring(6, endIndex);
buffer = buffer.substring(endIndex);

try {
// Parse the JSON and extract the content
const data = JSON.parse(jsonStr)["choices"][0]["delta"]["content"];
output += data;
console.clear(); // Clear the console
console.log(output); // Output the result to the console
} catch (error) {
console.error('Error parsing JSON:', error);
}
});
}

// Continue reading the next chunk.
return readStream(reader, lines[lines.length - 1]);
return readStream();
});
}

// Start reading the stream.
return readStream(reader);
return readStream();
})
.catch(error => {
// Handle errors.
console.error('Error:', error);
});

// Function to handle each data point in the stream.
function handleStreamData(line) {
if (line === "event: end") {
// Handle the end of the stream.
console.log("Stream ended");
return;
}

try {
const data = JSON.parse(line)["choices"][0]["delta"]["content"];
console.log(data);
} catch (error) {
}
}
```

### Using Python
Expand Down Expand Up @@ -228,14 +221,59 @@ You can continue to add user and bot messages to this `messages` array to mainta

## Handling Responses

Once you make a successful request to our API, you will receive a JSON response like this.
Once you make a successful request to our API, you will receive multiple streaming JSON response like this.

```json
{
"choices": [
{
"delta": {
"content": "你好,我是由Google開發的大型語言模型,又稱「對話式AI」,或稱「聊天機器人」。我透過文字進行互動,接受過大量資料的訓練,具備學習和理解的能力,能夠回答各種問題、撰寫不同的內容。\n我目前仍然在發展階段,但已經能夠執行多種語言任務,包括以下項目:\n\n* 翻譯語言\n* 回答問題\n* 撰寫故事、詩歌等不同類型的文本\n* 理解和生成程式碼\n* 玩遊戲\n* 提供書寫建議等等\n\n我的目標是成為一個功能強大的工具,幫助人們完成各種任務,並提供有用的資訊。隨著我繼續學習和成長,我希望能越來越好,為人們提供更好的服務。\n\n如果今天想請我幫忙的話,您可以提出您的要求。我將盡力提供您需要且有用的資訊",
"content": "",
"role": null
}
}
],
"created": 1705602791,
"id": "chatcmpl-xxxxx",
"model": "gemini-pro",
"object": "chat.completion",
"usage": []
}
{
"choices": [
{
"delta": {
"content": "",
"role": null
}
}
],
"created": 1705602791,
"id": "chatcmpl-xxxxx",
"model": "gemini-pro",
"object": "chat.completion",
"usage": []
}
{
"choices": [
{
"delta": {
"content": "",
"role": null
}
}
],
"created": 1705602791,
"id": "chatcmpl-xxxxx",
"model": "gemini-pro",
"object": "chat.completion",
"usage": []
}
{
"choices": [
{
"delta": {
"content": "",
"role": null
}
}
Expand All @@ -246,6 +284,7 @@ Once you make a successful request to our API, you will receive a JSON response
"object": "chat.completion",
"usage": []
}
...
```

You can then handle the response data as needed in your application.
3 changes: 3 additions & 0 deletions src/multi-chat/app/Http/Controllers/BotController.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public function upload(Request $request)
$history->fill(['msg' => '* ...thinking... *', 'chat_id' => $chat->id, 'isbot' => true, 'created_at' => date('Y-m-d H:i:s', strtotime(date('Y-m-d H:i:s') . ' +1 second'))]);
$history->save();
Redis::rpush('usertask_' . Auth::user()->id, $history->id);
Redis::expire('usertask_' . Auth::user()->id, 1200);
RequestChat::dispatch(json_encode([['msg' => $msg, 'isbot' => false]]), LLMs::find($llm_id)->access_code, Auth::user()->id, $history->id);
return Redirect::route('play.bots.chat', $chat->id);
}
Expand Down Expand Up @@ -264,6 +265,7 @@ function getFilenameFromURL($url)
$history->save();
$llm = LLMs::findOrFail($llm_id);
Redis::rpush('usertask_' . Auth::user()->id, $history->id);
Redis::expire('usertask_' . Auth::user()->id, 1200);
RequestChat::dispatch($tmp, $llm->access_code, Auth::user()->id, $history->id);
return Redirect::route('play.bots.chat', $chat->id);
}
Expand Down Expand Up @@ -330,6 +332,7 @@ public function request(Request $request): RedirectResponse
$history->save();
$access_code = LLMs::findOrFail(Chats::findOrFail($chatId)->llm_id)->access_code;
Redis::rpush('usertask_' . Auth::user()->id, $history->id);
Redis::expire('usertask_' . Auth::user()->id, 1200);
RequestChat::dispatch($tmp, $access_code, Auth::user()->id, $history->id);
return Redirect::route('play.bots.chat', $chatId);
}
Expand Down
5 changes: 5 additions & 0 deletions src/multi-chat/app/Http/Controllers/ChatController.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public function translate(Request $request)
$response->setCallback(function () use ($history, $tmp, $access_code) {
$client = new Client(['timeout' => 300]);
Redis::rpush('api_' . Auth::user()->id, $history->id);
Redis::expire('api_' . Auth::user()->id, 1200);
RequestChat::dispatch($tmp, $access_code, Auth::user()->id, $history->id, 'api_' . $history->id);

$req = $client->get(route('api.stream'), [
Expand Down Expand Up @@ -355,6 +356,7 @@ function getFilenameFromURL($url)
if ($history->content == '') {
$ids[] = $record->id;
Redis::rpush('usertask_' . $request->user()->id, $record->id);
Redis::expire('usertask_' . $request->user()->id, 1200);
}
} else {
$user_msg = $history->content;
Expand Down Expand Up @@ -487,6 +489,7 @@ public function upload(Request $request)
$history->fill(['msg' => '* ...thinking... *', 'chat_id' => $chat->id, 'isbot' => true, 'created_at' => date('Y-m-d H:i:s', strtotime(date('Y-m-d H:i:s') . ' +1 second'))]);
$history->save();
Redis::rpush('usertask_' . Auth::user()->id, $history->id);
Redis::expire('usertask_' . Auth::user()->id, 1200);
RequestChat::dispatch(json_encode([['msg' => $msg, 'isbot' => false]]), LLMs::find($llm_id)->access_code, Auth::user()->id, $history->id);
return Redirect::route('chat.chat', $chat->id);
}
Expand Down Expand Up @@ -615,6 +618,7 @@ function getFilenameFromURL($url)
$history->save();
$llm = LLMs::findOrFail($llm_id);
Redis::rpush('usertask_' . Auth::user()->id, $history->id);
Redis::expire('usertask_' . Auth::user()->id, 1200);
RequestChat::dispatch($tmp, $llm->access_code, Auth::user()->id, $history->id);
return Redirect::route('chat.chat', $chat->id);
}
Expand Down Expand Up @@ -681,6 +685,7 @@ public function request(Request $request): RedirectResponse
$history->save();
$access_code = LLMs::findOrFail(Chats::findOrFail($chatId)->llm_id)->access_code;
Redis::rpush('usertask_' . Auth::user()->id, $history->id);
Redis::expire('usertask_' . Auth::user()->id, 1200);
RequestChat::dispatch($tmp, $access_code, Auth::user()->id, $history->id);
return Redirect::route('chat.chat', $chatId);
}
Expand Down
7 changes: 4 additions & 3 deletions src/multi-chat/app/Http/Controllers/ProfileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,8 @@ public function api_auth(Request $request)
$response->setCallback(function () use ($request, $history, $tmp, $llm, $user) {
$client = new Client(['timeout' => 300]);
Redis::rpush('api_' . $user->tokenable_id, $history->id);
RequestChat::dispatch($tmp, $llm->access_code, $user->id, $history->id, $user->openai_token, 'api_' . $history->id);
Redis::expire('usertask_' . $user->tokenable_id, 1200);
RequestChat::dispatch($tmp, $llm->access_code, $user->id, $history->id, 'api_' . $history->id);

$req = $client->get(route('api.stream'), [
'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
Expand Down Expand Up @@ -341,13 +342,13 @@ public function api_auth(Request $request)
$jsonData = (object) json_decode(trim(substr($line, 5)));
if ($jsonData !== null) {
$resp['choices'][0]['delta']['content'] = $jsonData->msg;
echo 'data: ' . json_encode($resp) . "\n";
echo 'data: ' . json_encode($resp) . "\n\n";
ob_flush();
flush();
}
} elseif (substr($line, 0, 6) === 'event:') {
if (trim(substr($line, 5)) == 'end') {
echo "event: end\n\n";
echo "event: close\n\n";
ob_flush();
flush();
$client->disconnect();
Expand Down
3 changes: 3 additions & 0 deletions src/multi-chat/app/Http/Controllers/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ public function import(Request $request)
if ($history->content == '') {
$ids[] = $record->id;
Redis::rpush('usertask_' . $request->user()->id, $record->id);
Redis::expire('usertask_' . $request->user()->id, 1200);
}
} else {
$user_msg = $history->content;
Expand Down Expand Up @@ -334,6 +335,7 @@ public function create(Request $request): RedirectResponse
$history->save();
RequestChat::dispatch(json_encode([['msg' => $input, 'isbot' => false]]), LLMs::findOrFail($chat->llm_id)->access_code, Auth::user()->id, $history->id);
Redis::rpush('usertask_' . Auth::user()->id, $history->id);
Redis::expire('usertask_' . Auth::user()->id, 1200);
}
}
}
Expand Down Expand Up @@ -490,6 +492,7 @@ public function request(Request $request): RedirectResponse
$history->save();
RequestChat::dispatch($tmp, LLMs::findOrFail($chat->llm_id)->access_code, Auth::user()->id, $history->id);
Redis::rpush('usertask_' . Auth::user()->id, $history->id);
Redis::expire('usertask_' . Auth::user()->id, 1200);
}
}
}
Expand Down
28 changes: 19 additions & 9 deletions src/multi-chat/app/Http/Controllers/SystemController.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,28 @@ function extractBaseUrl($url)
User::query()->update(['term_accepted' => false]);
}

return Redirect::route('manage.home')
->with('last_tab', 'settings')
->with('last_action', 'update')
->with('status', $result);
return Redirect::route('manage.home')->with('last_tab', 'settings')->with('last_action', 'update')->with('status', $result);
}

public function ResetRedis(Request $request)
{
Redis::flushAll();
return Redirect::route('manage.home')
->with('last_tab', 'settings')
->with('last_action', 'resetRedis')
->with('status', 'success');
foreach (Redis::keys("usertask_*") as $key){
$user_id = explode("usertask_", $key, 2);
if (count($user_id) > 1) {
Redis::del("usertask_" . $user_id[1]);
} else {
Redis::del("usertask_" . $user_id);
}
}
foreach (Redis::keys("api_*") as $key){
$user_id = explode("api_", $key, 2);
if (count($user_id) > 1) {
Redis::del("api_" . $user_id[1]);
} else {
Redis::del("api_" . $user_id);
}
}

return Redirect::route('manage.home')->with('last_tab', 'settings')->with('last_action', 'resetRedis')->with('status', 'success');
}
}
2 changes: 2 additions & 0 deletions src/multi-chat/app/Jobs/RequestChat.php
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ public function handle(): void
Redis::lrem(($this->channel == $this->history_id ? 'usertask_' : 'api_') . $this->user_id, 0, $this->history_id);
Redis::publish($this->channel, 'New ' . json_encode(['msg' => trim($tmp)]));
Redis::publish($this->channel, 'Ended Ended');
}else{
Redis::lrem(($this->channel == $this->history_id ? 'usertask_' : 'api_') . $this->user_id, 0, $this->history_id);
}
}
}
Expand Down
13 changes: 8 additions & 5 deletions src/multi-chat/app/Observers/UserObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function created(User $user): void
];

// Remove unwanted attributes
$attributesToIgnore = ['updated_at', 'openai_token', 'password', 'id', 'created_at'];
$attributesToIgnore = ['updated_at', 'openai_token', 'password', 'id', 'created_at', 'google_token'];
$attributes = array_diff_key($user->getAttributes(), array_flip($attributesToIgnore));

if (!empty($attributes)) {
Expand Down Expand Up @@ -49,15 +49,18 @@ public function updated(User $user): void

$modifiedValues = [];
$passwordChanged = false;
$openaiTokenChanged = false;
$ExternalTokenChanged = false;

foreach ($changes as $attribute => $change) {
if ($attribute === 'password') {
$passwordChanged = true;
continue; // Skip logging the actual password change
} elseif ($attribute === 'openai_token') {
$openaiTokenChanged = true;
$ExternalTokenChanged = true;
continue; // Skip logging the actual openai_token change
} elseif ($attribute === 'google_token') {
$ExternalTokenChanged = true;
continue; // Skip logging the actual google_token change
}

// Check if the attribute exists in original values before accessing it
Expand All @@ -73,8 +76,8 @@ public function updated(User $user): void

if ($passwordChanged) {
$logData['message'] = 'Password has been changed';
} elseif ($openaiTokenChanged) {
$logData['message'] = 'OpenAI token has been changed';
} elseif ($ExternalTokenChanged) {
$logData['message'] = 'External token has been changed';
} elseif (!empty($modifiedValues)) {
$logData['modified_values'] = $modifiedValues;
}
Expand Down
Loading

0 comments on commit 5ede83e

Please sign in to comment.