Skip to content

Commit 3e26480

Browse files
committed
refactor!: new package shared-chat-completion
1 parent 130eabb commit 3e26480

File tree

32 files changed

+419
-648
lines changed

32 files changed

+419
-648
lines changed

docs/content/docs/get-started/tool.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ It accepts parameters as defined above and returns the string (other types may b
6262
### Get weather
6363

6464
```ts twoslash
65-
import generateText from '@xsai/generate-text'
65+
import { generateText } from '@xsai/generate-text'
6666
import { tool } from '@xsai/tool'
6767
import { description, object, pipe, string } from 'valibot'
6868

packages/generate-object/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
],
2525
"scripts": {
2626
"build": "pkgroll",
27-
"build:watch": "pkgroll --watch",
28-
"test": "vitest run",
29-
"test:watch": "vitest"
27+
"build:watch": "pkgroll --watch"
3028
},
3129
"dependencies": {
3230
"@typeschema/main": "catalog:",

packages/generate-object/src/index.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,47 @@
1-
export { generateObject, generateObject as default, type GenerateObjectOptions, type GenerateObjectResult } from './utils/generate-object'
1+
import { type Infer, type Schema, toJSONSchema } from '@typeschema/main'
2+
import { generateText, type GenerateTextOptions, type GenerateTextResult } from '@xsai/generate-text'
3+
import { clean } from '@xsai/shared'
4+
5+
export interface GenerateObjectOptions<T extends Schema> extends GenerateTextOptions {
6+
schema: T
7+
schemaDescription?: string
8+
schemaName?: string
9+
}
10+
11+
export interface GenerateObjectResult<T extends Schema> extends Omit<GenerateTextResult, 'text'> {
12+
object: Infer<T>
13+
}
14+
15+
/**
16+
* @experimental
17+
* WIP, test failed
18+
* @remarks Ollama doesn't support this, see {@link https://github.com/ollama/ollama/issues/6473}
19+
*/
20+
export const generateObject = async <T extends Schema>(options: GenerateObjectOptions<T>): Promise<GenerateObjectResult<T>> =>
21+
await generateText(clean({
22+
...options,
23+
responseFormat: {
24+
jsonSchema: {
25+
description: options.schemaDescription,
26+
name: options.schemaName ?? 'json_schema',
27+
schema: await toJSONSchema(options.schema)
28+
.then(json => clean({
29+
...json,
30+
$schema: undefined,
31+
})),
32+
strict: true,
33+
},
34+
type: 'json_schema',
35+
},
36+
schema: undefined,
37+
schemaDescription: undefined,
38+
schemaName: undefined,
39+
}))
40+
.then(({ finishReason, text, usage }) => ({
41+
finishReason,
42+
// TODO: import { validate } from '@typeschema/main'
43+
object: JSON.parse(text || '{}'),
44+
usage,
45+
}))
46+
47+
export default generateObject

packages/generate-object/src/utils/generate-object.ts

Lines changed: 0 additions & 45 deletions
This file was deleted.

packages/generate-object/test/index.test.ts

Lines changed: 0 additions & 29 deletions
This file was deleted.

packages/generate-text/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@
2929
"test:watch": "vitest"
3030
},
3131
"dependencies": {
32-
"@xsai/shared": "workspace:"
32+
"@xsai/shared-chat-completion": "workspace:"
3333
}
3434
}

packages/generate-text/src/index.ts

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,80 @@
1-
export type * from './types'
2-
export { generateText, generateText as default, type GenerateTextOptions, type GenerateTextResponseUsage, type GenerateTextResult } from './utils/generate-text'
1+
import { type AssistantMessageResponse, chatCompletion, type ChatCompletionOptions, type FinishReason, type Message, type Tool } from '@xsai/shared-chat-completion'
2+
3+
export interface GenerateTextOptions extends ChatCompletionOptions {}
4+
5+
interface GenerateTextResponse {
6+
choices: {
7+
finish_reason: FinishReason
8+
index: number
9+
message: AssistantMessageResponse
10+
}[]
11+
created: number
12+
id: string
13+
model: string
14+
object: 'chat.completion'
15+
system_fingerprint: string
16+
usage: GenerateTextResponseUsage
17+
}
18+
19+
export interface GenerateTextResponseUsage {
20+
completion_tokens: number
21+
prompt_tokens: number
22+
total_tokens: number
23+
}
24+
25+
export interface GenerateTextResult {
26+
finishReason: FinishReason
27+
text?: string
28+
usage: GenerateTextResponseUsage
29+
}
30+
31+
export const generateText = async (options: GenerateTextOptions): Promise<GenerateTextResult> =>
32+
await chatCompletion({
33+
...options,
34+
stream: false,
35+
})
36+
.then(async (res) => {
37+
if (!res.ok) {
38+
const error = await res.text()
39+
throw new Error(`Error(${res.status}): ${error}`)
40+
}
41+
else {
42+
return res.json() as Promise<GenerateTextResponse>
43+
}
44+
})
45+
.then(async ({ choices, usage }) => {
46+
const { finish_reason, message } = choices[0]
47+
48+
if (!!message.content || !message.tool_calls) {
49+
return {
50+
finishReason: finish_reason,
51+
text: message.content,
52+
usage,
53+
}
54+
}
55+
56+
const toolMessages = []
57+
58+
for (const toolCall of message.tool_calls) {
59+
const tool = (options.tools as Tool[]).find(tool => tool.function.name === toolCall.function.name)!
60+
const toolResult = await tool.execute(JSON.parse(toolCall.function.arguments))
61+
const toolMessage = {
62+
content: toolResult,
63+
role: 'tool',
64+
tool_call_id: toolCall.id,
65+
} satisfies Message
66+
67+
toolMessages.push(toolMessage)
68+
}
69+
70+
return await generateText({
71+
...options,
72+
messages: [
73+
...options.messages,
74+
{ ...message, content: message.content! },
75+
...toolMessages,
76+
],
77+
})
78+
})
79+
80+
export default generateText

packages/generate-text/src/types/index.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

packages/generate-text/src/types/message.ts

Lines changed: 0 additions & 78 deletions
This file was deleted.

0 commit comments

Comments
 (0)