@@ -15,6 +15,14 @@ import { MockModel } from './MockModel'
15
15
16
16
type ChatModel = Runnable < BaseLanguageModelInput , AIMessageChunk , BaseChatModelCallOptions >
17
17
18
+ /**
19
+ * Gets a chat model instance based on the provided configuration.
20
+ * Can be a MockModel for testing or an AzureChatOpenAI model.
21
+ * @param modelConfig The configuration for the model.
22
+ * @param tools The structured tools the model can use.
23
+ * @param temperature The temperature for the model's responses.
24
+ * @returns A chat model instance.
25
+ */
18
26
const getChatModel = ( modelConfig : ( typeof validModels ) [ number ] , tools : StructuredTool [ ] , temperature : number ) : ChatModel => {
19
27
const chatModel =
20
28
modelConfig . name === 'mock'
@@ -31,7 +39,7 @@ const getChatModel = (modelConfig: (typeof validModels)[number], tools: Structur
31
39
summary : null ,
32
40
generate_summary : null ,
33
41
} ,
34
- } ) . bindTools ( tools )
42
+ } ) . bindTools ( tools ) // Make tools available to the model.
35
43
36
44
return chatModel
37
45
}
@@ -40,6 +48,23 @@ type WriteEventFunction = (data: ChatEvent) => Promise<void>
40
48
41
49
type ChatTool = StructuredTool < any , any , any , string >
42
50
51
+ /**
52
+ * Handles the main chat streaming logic.
53
+ * It takes the chat history, model configuration, and a set of tools,
54
+ * and streams the response from the language model, handling tool calls
55
+ * and sending events back to the client.
56
+ *
57
+ * This function can perform two chat turns if the first one results in tool calls.
58
+ *
59
+ * @param model The name of the model to use.
60
+ * @param temperature The temperature for the model's responses.
61
+ * @param systemMessage The system message to prepend to the chat history.
62
+ * @param chatMessages The history of chat messages.
63
+ * @param tools The structured tools available to the model.
64
+ * @param writeEvent A function to write chat events to the client.
65
+ * @param user The user initiating the chat.
66
+ * @returns An object containing response statistics and the final response message.
67
+ */
43
68
export const streamChat = async ( {
44
69
model,
45
70
temperature,
@@ -77,6 +102,7 @@ export const streamChat = async ({
77
102
78
103
const result = await chatTurn ( chatModel , messages , toolsByName , writeEvent , user )
79
104
105
+ // If the model decided to call tools, execute them and send the results back to the model in a second turn.
80
106
if ( result . toolCalls . length > 0 ) {
81
107
const result2 = await chatTurn ( chatModel , messages , toolsByName , writeEvent , user )
82
108
@@ -102,6 +128,17 @@ export const streamChat = async ({
102
128
}
103
129
}
104
130
131
+ /**
132
+ * Executes a single turn of the chat.
133
+ * It streams the model's response, handles tool calls, and sends events.
134
+ *
135
+ * @param model The chat model instance.
136
+ * @param messages The messages to send to the model.
137
+ * @param toolsByName A record of available tools, keyed by name.
138
+ * @param writeEvent A function to write chat events to the client.
139
+ * @param user The user for whom the tool results are stored.
140
+ * @returns An object with statistics about the chat turn and any tool calls made.
141
+ */
105
142
const chatTurn = async ( model : ChatModel , messages : BaseMessageLike [ ] , toolsByName : Record < string , ChatTool > , writeEvent : WriteEventFunction , user : User ) => {
106
143
const stream = await model . stream ( messages )
107
144
@@ -140,9 +177,11 @@ const chatTurn = async (model: ChatModel, messages: BaseMessageLike[], toolsByNa
140
177
} )
141
178
}
142
179
180
+ // Append the chunk to the full response.
143
181
fullOutput = fullOutput !== undefined ? concat ( fullOutput , chunk ) : chunk
144
182
}
145
183
184
+ // Add the assistant's full response to the message history.
146
185
messages . push ( fullOutput as AIMessageChunk )
147
186
148
187
const toolCalls = fullOutput ?. tool_calls ?? [ ]
@@ -162,6 +201,7 @@ const chatTurn = async (model: ChatModel, messages: BaseMessageLike[], toolsByNa
162
201
const result = await tool . invoke ( toolCall )
163
202
const artifact = result . artifact as ChatToolOutput
164
203
await ToolResultStore . saveResults ( id , artifact , user )
204
+ // Add the tool's output to the message history for the next turn.
165
205
messages . push ( result )
166
206
toolCallStatuses [ id ] = {
167
207
status : 'completed' ,
@@ -182,6 +222,7 @@ const chatTurn = async (model: ChatModel, messages: BaseMessageLike[], toolsByNa
182
222
}
183
223
}
184
224
225
+ // Calculate statistics about the response generation.
185
226
const tokenCount = fullOutput ?. usage_metadata ?. output_tokens ?? 0
186
227
const inputTokenCount = fullOutput ?. usage_metadata ?. input_tokens ?? 0
187
228
const tokenStreamingDuration = Date . now ( ) - firstTokenTS
0 commit comments