Skip to content

Commit 3cf4b6c

Browse files
committed
feat: Add streaming and non-streaming chat completion handlers
1 parent 465ef73 commit 3cf4b6c

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { Context } from "hono"
2+
3+
import consola from "consola"
4+
import { streamSSE } from "hono/streaming"
5+
6+
import type { ChatCompletionsPayload } from "~/services/copilot/chat-completions/types"
7+
8+
import { chatCompletionsStream } from "~/services/copilot/chat-completions/service-streaming"
9+
10+
export async function handlerStreaming(c: Context) {
11+
const payload = await c.req.json<ChatCompletionsPayload>()
12+
13+
consola.info(`Received request: ${JSON.stringify(payload).slice(0, 500)}`)
14+
15+
const response = await chatCompletionsStream(payload)
16+
17+
return streamSSE(c, async (stream) => {
18+
let index = 0
19+
for await (const chunk of response) {
20+
if (index === 0) {
21+
consola.info(
22+
`Streaming response, first chunk: ${JSON.stringify(chunk)}`,
23+
)
24+
}
25+
26+
index++
27+
28+
await stream.writeSSE({
29+
data: JSON.stringify(chunk.data),
30+
})
31+
}
32+
})
33+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { Context } from "hono"
2+
3+
import consola from "consola"
4+
import { streamSSE } from "hono/streaming"
5+
6+
import type { ChatCompletionsPayload } from "~/services/copilot/chat-completions/types"
7+
8+
import { chatCompletions } from "~/services/copilot/chat-completions/service"
9+
10+
import { createContentChunk, createFinalChunk, segmentResponse } from "./utils"
11+
12+
export async function handler(c: Context) {
13+
const payload = await c.req.json<ChatCompletionsPayload>()
14+
payload.stream = false
15+
16+
consola.info(`Received request: ${JSON.stringify(payload).slice(0, 500)}`)
17+
18+
const response = await chatCompletions(payload)
19+
consola.info(`Response from Copilot: ${JSON.stringify(response)}`)
20+
21+
const segments = segmentResponse(response.choices[0].message.content)
22+
const chunks = segments.map((segment) =>
23+
createContentChunk(segment, response, payload.model),
24+
)
25+
26+
chunks.push(createFinalChunk(response, payload.model))
27+
28+
consola.info(
29+
`Streaming response, first chunk: ${JSON.stringify(chunks.at(0))}`,
30+
)
31+
32+
return streamSSE(c, async (stream) => {
33+
for (const chunk of chunks) {
34+
await stream.writeSSE({
35+
data: JSON.stringify(chunk.data),
36+
})
37+
await stream.sleep(1) // Simulated latency
38+
}
39+
})
40+
}

0 commit comments

Comments
 (0)