refactor!: move step interface, tools option to shared-chat (#173)
* refactor!: move step interface to shared-chat * refactor: move tools to chat options * fix: optional type
This commit is contained in:
1 parent
65f0c01eee
commit
f429e33920
9 files changed
+34
-48
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import type { AssistantMessageResponse, ChatOptions, CompletionToolCall, CompletionToolResult, FinishReason, Message, StepType, Tool, Usage } from '@xsai/shared-chat'
|
||||
import type { AssistantMessageResponse, ChatOptions, CompletionStep, CompletionToolCall, CompletionToolResult, FinishReason, Message, Usage } from '@xsai/shared-chat'
|
||||
|
||||
import { responseJSON, trampoline } from '@xsai/shared'
|
||||
import { chat, determineStepType, executeTool } from '@xsai/shared-chat'
|
||||
@@ -6,12 +6,11 @@ import { chat, determineStepType, executeTool } from '@xsai/shared-chat'
|
||||
export interface GenerateTextOptions extends ChatOptions {
|
||||
/** @default 1 */
|
||||
maxSteps?: number
|
||||
onStepFinish?: (step: GenerateTextStepResult) => Promise<unknown> | unknown
|
||||
onStepFinish?: (step: CompletionStep<true>) => Promise<unknown> | unknown
|
||||
/** @internal */
|
||||
steps?: GenerateTextStepResult[]
|
||||
steps?: CompletionStep<true>[]
|
||||
/** if you want to enable stream, use `@xsai/stream-{text,object}` */
|
||||
stream?: never
|
||||
tools?: Tool[]
|
||||
}
|
||||
|
||||
export interface GenerateTextResponse {
|
||||
@@ -31,16 +30,7 @@ export interface GenerateTextResponse {
|
||||
export interface GenerateTextResult {
|
||||
finishReason: FinishReason
|
||||
messages: Message[]
|
||||
steps: GenerateTextStepResult[]
|
||||
text?: string
|
||||
toolCalls: CompletionToolCall[]
|
||||
toolResults: CompletionToolResult[]
|
||||
usage: Usage
|
||||
}
|
||||
|
||||
export interface GenerateTextStepResult {
|
||||
finishReason: FinishReason
|
||||
stepType: StepType
|
||||
steps: CompletionStep<true>[]
|
||||
text?: string
|
||||
toolCalls: CompletionToolCall[]
|
||||
toolResults: CompletionToolResult[]
|
||||
@@ -70,7 +60,7 @@ const rawGenerateText: RawGenerateText = async (options: GenerateTextOptions) =>
|
||||
throw new Error(`No choices returned, response body: ${JSON.stringify(res)}`)
|
||||
|
||||
const messages: Message[] = structuredClone(options.messages)
|
||||
const steps: GenerateTextStepResult[] = options.steps ? structuredClone(options.steps) : []
|
||||
const steps: CompletionStep<true>[] = options.steps ? structuredClone(options.steps) : []
|
||||
const toolCalls: CompletionToolCall[] = []
|
||||
const toolResults: CompletionToolResult[] = []
|
||||
|
||||
@@ -87,7 +77,7 @@ const rawGenerateText: RawGenerateText = async (options: GenerateTextOptions) =>
|
||||
messages.push({ ...message, content: message.content })
|
||||
|
||||
if (finishReason === 'stop' || stepType === 'done') {
|
||||
const step: GenerateTextStepResult = {
|
||||
const step: CompletionStep<true> = {
|
||||
finishReason,
|
||||
stepType,
|
||||
text: message.content,
|
||||
@@ -129,7 +119,7 @@ const rawGenerateText: RawGenerateText = async (options: GenerateTextOptions) =>
|
||||
})
|
||||
}
|
||||
|
||||
const step: GenerateTextStepResult = {
|
||||
const step: CompletionStep<true> = {
|
||||
finishReason,
|
||||
stepType,
|
||||
text: message.content,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export type * from './finish-reason'
|
||||
export type * from './message'
|
||||
export type * from './message-part'
|
||||
export type * from './step-type'
|
||||
export type * from './step'
|
||||
export type * from './tool'
|
||||
export type * from './tool-choice'
|
||||
export type * from './usage'
|
||||
@@ -1 +0,0 @@
|
||||
export type StepType = 'continue' | 'done' | 'initial' | 'tool-result'
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { FinishReason } from './finish-reason'
|
||||
import type { CompletionToolCall, CompletionToolResult } from './tool'
|
||||
import type { Usage } from './usage'
|
||||
|
||||
export type CompletionStep<T extends boolean = false> = (T extends true ? { usage: Usage } : { usage?: Usage }) & {
|
||||
finishReason: FinishReason
|
||||
stepType: CompletionStepType
|
||||
text?: string
|
||||
toolCalls: CompletionToolCall[]
|
||||
toolResults: CompletionToolResult[]
|
||||
}
|
||||
|
||||
export type CompletionStepType = 'continue' | 'done' | 'initial' | 'tool-result'
|
||||
@@ -27,6 +27,7 @@ export interface ChatOptions extends CommonRequestOptions {
|
||||
*/
|
||||
temperature?: number
|
||||
toolChoice?: ToolChoice
|
||||
tools?: Tool[]
|
||||
/** @default 1 */
|
||||
topP?: number
|
||||
}
|
||||
@@ -35,7 +36,7 @@ export const chat = async <T extends ChatOptions>(options: T) =>
|
||||
(options.fetch ?? globalThis.fetch)(requestURL('chat/completions', options.baseURL), {
|
||||
body: requestBody({
|
||||
...options,
|
||||
tools: (options.tools as Tool[] | undefined)?.map(tool => ({
|
||||
tools: (options.tools)?.map(tool => ({
|
||||
function: clean({
|
||||
...tool.function,
|
||||
returns: undefined,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { FinishReason, StepType } from '../types'
|
||||
import type { CompletionStepType, FinishReason } from '../types'
|
||||
|
||||
export interface DetermineStepTypeOptions {
|
||||
finishReason: FinishReason
|
||||
@@ -8,7 +8,7 @@ export interface DetermineStepTypeOptions {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const determineStepType = ({ finishReason, maxSteps, stepsLength, toolCallsLength }: DetermineStepTypeOptions): StepType => {
|
||||
export const determineStepType = ({ finishReason, maxSteps, stepsLength, toolCallsLength }: DetermineStepTypeOptions): CompletionStepType => {
|
||||
if (stepsLength === 0) {
|
||||
return 'initial'
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import type { ChatOptions, CompletionToolCall, CompletionToolResult, FinishReason, Message, Tool, ToolCall, Usage } from '@xsai/shared-chat'
|
||||
import type { ChatOptions, CompletionStep, CompletionToolCall, CompletionToolResult, FinishReason, Message, ToolCall, Usage } from '@xsai/shared-chat'
|
||||
|
||||
import { objCamelToSnake, trampoline } from '@xsai/shared'
|
||||
import { chat, determineStepType, executeTool } from '@xsai/shared-chat'
|
||||
|
||||
import type { StreamTextEvent } from './types/event'
|
||||
import type { StreamTextStep } from './types/step-result'
|
||||
|
||||
import { transformChunk } from './_transform-chunk'
|
||||
import { DelayedPromise } from './internal/delayed-promise'
|
||||
@@ -13,8 +12,8 @@ export interface StreamTextOptions extends ChatOptions {
|
||||
/** @default 1 */
|
||||
maxSteps?: number
|
||||
onEvent?: (event: StreamTextEvent) => Promise<unknown> | unknown
|
||||
onFinish?: (step?: StreamTextStep) => Promise<unknown> | unknown
|
||||
onStepFinish?: (step: StreamTextStep) => Promise<unknown> | unknown
|
||||
onFinish?: (step?: CompletionStep) => Promise<unknown> | unknown
|
||||
onStepFinish?: (step: CompletionStep) => Promise<unknown> | unknown
|
||||
/**
|
||||
* If you want to disable stream, use `@xsai/generate-{text,object}`.
|
||||
*/
|
||||
@@ -26,13 +25,12 @@ export interface StreamTextOptions extends ChatOptions {
|
||||
*/
|
||||
includeUsage?: boolean
|
||||
}
|
||||
tools?: Tool[]
|
||||
}
|
||||
|
||||
export interface StreamTextResult {
|
||||
fullStream: ReadableStream<StreamTextEvent>
|
||||
messages: Promise<Message[]>
|
||||
steps: Promise<StreamTextStep[]>
|
||||
steps: Promise<CompletionStep[]>
|
||||
textStream: ReadableStream<string>
|
||||
usage: Promise<undefined | Usage>
|
||||
// TODO: totalUsage
|
||||
@@ -40,13 +38,13 @@ export interface StreamTextResult {
|
||||
|
||||
export const streamText = async (options: StreamTextOptions): Promise<StreamTextResult> => {
|
||||
// state
|
||||
const steps: StreamTextStep[] = []
|
||||
const steps: CompletionStep[] = []
|
||||
const messages: Message[] = structuredClone(options.messages)
|
||||
const maxSteps = options.maxSteps ?? 1
|
||||
let usage: undefined | Usage
|
||||
|
||||
// result state
|
||||
const resultSteps = new DelayedPromise<StreamTextStep[]>()
|
||||
const resultSteps = new DelayedPromise<CompletionStep[]>()
|
||||
const resultMessages = new DelayedPromise<Message[]>()
|
||||
const resultUsage = new DelayedPromise<undefined | Usage>()
|
||||
|
||||
@@ -62,7 +60,7 @@ export const streamText = async (options: StreamTextOptions): Promise<StreamText
|
||||
void options.onEvent?.(stepEvent)
|
||||
}
|
||||
|
||||
const pushStep = (step: StreamTextStep) => {
|
||||
const pushStep = (step: CompletionStep) => {
|
||||
steps.push(step)
|
||||
// eslint-disable-next-line sonarjs/void-use
|
||||
void options.onStepFinish?.(step)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import type { CompletionToolCall, CompletionToolResult, FinishReason, StepType, Usage } from '@xsai/shared-chat'
|
||||
|
||||
export interface StreamTextStep {
|
||||
finishReason: FinishReason
|
||||
stepType: StepType
|
||||
text?: string
|
||||
toolCalls: CompletionToolCall[]
|
||||
toolResults: CompletionToolResult[]
|
||||
usage?: Usage
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AssistantMessage, ChatOptions, CompletionToolCall, CompletionToolResult, FinishReason, Message, StepType, Tool, ToolCall, ToolMessagePart, Usage } from '@xsai/shared-chat'
|
||||
import type { AssistantMessage, ChatOptions, CompletionStepType, CompletionToolCall, CompletionToolResult, FinishReason, Message, ToolCall, ToolMessagePart, Usage } from '@xsai/shared-chat'
|
||||
|
||||
import { objCamelToSnake, XSAIError } from '@xsai/shared'
|
||||
import { chat, determineStepType, executeTool } from '@xsai/shared-chat'
|
||||
@@ -75,11 +75,6 @@ export interface StreamTextOptions extends ChatOptions {
|
||||
*/
|
||||
includeUsage?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* List of tools to be used in the stream.
|
||||
*/
|
||||
tools?: Tool[]
|
||||
}
|
||||
|
||||
export interface StreamTextResult {
|
||||
@@ -92,7 +87,7 @@ export interface StreamTextStep {
|
||||
choices: StreamTextChoice[]
|
||||
finishReason: FinishReason
|
||||
messages: Message[]
|
||||
stepType: StepType
|
||||
stepType: CompletionStepType
|
||||
toolCalls: CompletionToolCall[]
|
||||
toolResults: CompletionToolResult[]
|
||||
usage?: Usage
|
||||
|
||||
Reference in new issue
Block a user