Skip to content

Instantly share code, notes, and snippets.

@thekid
Last active November 3, 2024 21:09
Show Gist options
  • Save thekid/50a30956fc70cd9b1fe2a7843446a61c to your computer and use it in GitHub Desktop.
Save thekid/50a30956fc70cd9b1fe2a7843446a61c to your computer and use it in GitHub Desktop.
ChatGPT REST API
<?php
use com\openai\rest\OpenAIEndpoint;
use io\File;
use util\Objects;
use web\Application;
class TestGPT extends Application {
private $ai;
public function initialize() {
$this->ai= new OpenAIEndpoint('https://'.$this->environment->variable('OPENAI_API_KEY').'@api.openai.com/v1');
}
public function message($conn, $message) {
$conn->send("🧑 {$message}\n");
// Read user messages
$store= new File('messages_'.$conn->id());
if ($store->exists()) {
$store->open(File::READWRITE);
$messages= json_decode($store->read($store->size()), true);
} else {
$store->open(File::WRITE);
$messages= [];
}
// Stream AI response
$messages[]= ['role' => 'user', 'content' => $message];
$conn->send("🤖 ");
try {
$stream= $this->ai->api('/chat/completions')->stream([
'model' => 'gpt-4o-mini',
'messages' => $messages,
]);
foreach ($stream->deltas('content') as $delta) {
$conn->send($delta);
yield;
}
$messages[]= $stream->result()['choices'][0]['message'];
$store->seek(0, SEEK_SET);
$store->write(json_encode($messages));
} finally {
$conn->send("\n\n");
$store->close();
}
}
public function routes() {
return [
'/ws' => function($req, $res) {
// Hash websocket key and well-known GUID
$key= $req->header('Sec-WebSocket-Key');
$accept= base64_encode(sha1($key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
$res->answer(101);
$res->header('Connection', 'upgrade');
$res->header('Upgrade', 'websocket');
$res->header('Sec-WebSocket-Accept', $accept);
},
'/' => function($req, $res) {
$html= <<<'HTML'
<!DOCTYPE html>
<html>
<head>
<title>WebSocket demo</title>
<style type="text/css">
* {
font-family: system-ui;
font-size: 1.1rem;
}
main {
max-width: 40rem;
margin-inline: auto;
}
#messages {
display: block;
white-space: pre-wrap;
padding-block: .5rem;
}
input {
width: 100%;
padding: .5rem;
}
</style>
</head>
<body>
<main>
<output id="messages"></output>
<form id="message">
<input name="message" autocomplete="off" type="text">
</form>
</main>
</body>
<script type="module">
const $messages = document.getElementById('messages');
const $message = document.getElementById('message');
const ws = new WebSocket('ws://localhost:8080/ws');
ws.onopen = console.log;
ws.onclose = console.warn;
ws.onmessage = e => {
$messages.innerText += e.data;
$message.scrollIntoView();
};
$message.onsubmit = e => {
const $input = $message.elements['message'];
e.preventDefault();
ws.send($input.value);
$input.value = '';
};
</script>
</html>
HTML;
$res->send($html, 'text/html; charset=utf-8');
},
];
}
}
@thekid
Copy link
Author

thekid commented Nov 3, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment