11import { tools } from './tools.js'
22
3- const systemPrompt =
4- 'You are a machine learning web application named "hyperparam". ' +
5- 'You assist users with building high quality ML models by introspecting on their training set data. ' +
6- 'The website and api are available at hyperparam.app. ' +
7- 'Hyperparam uses LLMs to analyze their own training set. ' +
8- 'It can generate the perplexity, entropy, and other metrics of the training set. ' +
9- 'This allows users to find segments of their data set which are difficult to model. ' +
10- 'This could be because the data is junk, or because the data requires deeper understanding. ' +
11- 'This is essential for closing the loop on the ML lifecycle. ' +
12- 'The quickest way to get started is to upload a dataset and start exploring.'
3+ const systemPrompt = 'You are a machine learning web application named "Hyperparam".'
4+ + ' You assist users with building high quality ML models by introspecting on their training set data.'
5+ + ' The website and api are available at hyperparam.app.'
6+ + ' Hyperparam uses LLMs to analyze their own training set.'
7+ + ' It can generate the perplexity, entropy, and other metrics of the training set.'
8+ + ' This allows users to find segments of their data set which are difficult to model.'
9+ + ' This could be because the data is junk, or because the data requires deeper understanding.'
10+ + ' This is essential for closing the loop on the ML lifecycle.'
11+ + ' The quickest way to get started is to upload a dataset and start exploring.'
1312/** @type {Message } */
1413const systemMessage = { role : 'system' , content : systemPrompt }
1514
@@ -27,7 +26,7 @@ const colors = {
2726 * @returns {Promise<Message> }
2827 */
2928async function sendToServer ( chatInput ) {
30- const response = await fetch ( 'http ://localhost:3000 /api/functions/openai/chat' , {
29+ const response = await fetch ( 'https ://hyperparam.app /api/functions/openai/chat' , {
3130 method : 'POST' ,
3231 headers : { 'Content-Type' : 'application/json' } ,
3332 body : JSON . stringify ( chatInput ) ,
@@ -38,8 +37,10 @@ async function sendToServer(chatInput) {
3837 }
3938
4039 // Process the streaming response
40+ /** @type {Message } */
4141 const streamResponse = { role : 'assistant' , content : '' }
42- const reader = response . body . getReader ( )
42+ const reader = response . body ?. getReader ( )
43+ if ( ! reader ) throw new Error ( 'No response body' )
4344 const decoder = new TextDecoder ( )
4445 let buffer = ''
4546
@@ -53,19 +54,19 @@ async function sendToServer(chatInput) {
5354 for ( const line of lines ) {
5455 if ( ! line . trim ( ) ) continue
5556 try {
56- const jsonChunk = JSON . parse ( line )
57- const { content , error } = jsonChunk
58- if ( content ) {
59- streamResponse . content += content
60- write ( content )
57+ const chunk = JSON . parse ( line )
58+ const { type , error } = chunk
59+ if ( type === 'response.output_text.delta' ) {
60+ streamResponse . content += chunk . delta
61+ write ( chunk . delta )
6162 } else if ( error ) {
6263 console . error ( error )
6364 throw new Error ( error )
64- } else if ( jsonChunk . function ) {
65+ } else if ( chunk . function ) {
6566 streamResponse . tool_calls ??= [ ]
66- streamResponse . tool_calls . push ( jsonChunk )
67- } else if ( ! jsonChunk . key && jsonChunk . content !== '' ) {
68- console . log ( 'Unknown chunk' , jsonChunk )
67+ streamResponse . tool_calls . push ( chunk )
68+ } else if ( ! chunk . key ) {
69+ console . log ( 'Unknown chunk' , chunk )
6970 }
7071 } catch ( err ) {
7172 console . error ( 'Error parsing chunk' , err )
@@ -85,19 +86,21 @@ async function sendToServer(chatInput) {
8586 */
8687async function sendMessages ( messages ) {
8788 const chatInput = {
89+ model : 'gpt-4o' ,
8890 messages,
8991 tools : tools . map ( tool => tool . tool ) ,
9092 }
9193 const response = await sendToServer ( chatInput )
9294 messages . push ( response )
9395 // handle tool results
9496 if ( response . tool_calls ) {
95- /** @type {{ toolCall: ToolCall, tool: ToolHandler, result: Promise<Message > }[] } */
97+ /** @type {{ toolCall: ToolCall, tool: ToolHandler, result: Promise<string > }[] } */
9698 const toolResults = [ ]
9799 for ( const toolCall of response . tool_calls ) {
98100 const tool = tools . find ( tool => tool . tool . function . name === toolCall . function . name )
99101 if ( tool ) {
100- const result = tool . handleToolCall ( toolCall )
102+ const args = JSON . parse ( toolCall . function ?. arguments ?? '{}' )
103+ const result = tool . handleToolCall ( args )
101104 toolResults . push ( { toolCall, tool, result } )
102105 } else {
103106 throw new Error ( `Unknown tool: ${ toolCall . function . name } ` )
@@ -106,24 +109,27 @@ async function sendMessages(messages) {
106109 write ( '\n' )
107110 for ( const toolResult of toolResults ) {
108111 const { toolCall, tool } = toolResult
109- const result = await toolResult . result
112+ try {
113+ const content = await toolResult . result
110114
111- // Construct function call message
112- const args = JSON . parse ( toolCall . function ?. arguments ?? '{}' )
113- const keys = Object . keys ( args )
114- let func = toolCall . function . name
115- if ( keys . length === 0 ) {
116- func += '()'
117- } else if ( keys . length === 1 ) {
118- func += `(${ args [ keys [ 0 ] ] } )`
119- } else {
120- // transform to (arg1 = 111, arg2 = 222)
121- const pairs = keys . map ( key => `${ key } = ${ args [ key ] } ` )
122- func += `(${ pairs . join ( ', ' ) } )`
123- }
115+ // Construct function call message
116+ const args = JSON . parse ( toolCall . function ?. arguments ?? '{}' )
117+ const entries = Object . entries ( args )
118+ let func = toolCall . function . name
119+ if ( entries . length === 0 ) {
120+ func += '()'
121+ } else {
122+ // transform to (arg1 = 111, arg2 = 222)
123+ const pairs = entries . map ( ( [ key , value ] ) => `${ key } = ${ value } ` )
124+ func += `(${ pairs . join ( ', ' ) } )`
125+ }
124126
125- write ( colors . tool , `${ tool . emoji } ${ func } ` , colors . normal , '\n\n' )
126- messages . push ( result )
127+ write ( colors . tool , `${ tool . emoji } ${ func } ` , colors . normal , '\n\n' )
128+ messages . push ( { role : 'tool' , content, tool_call_id : toolCall . id } )
129+ } catch ( error ) {
130+ write ( colors . error , `\nError calling tool ${ toolCall . function . name } : ${ error . message } \n\n` , colors . normal )
131+ messages . push ( { role : 'tool' , content : `Error calling tool ${ toolCall . function . name } : ${ error . message } ` , tool_call_id : toolCall . id } )
132+ }
127133 }
128134 // send messages with tool results
129135 await sendMessages ( messages )
0 commit comments