1+ import util from 'node:util' ;
2+
13// This is a simple client for dllama-api.
24//
35// Usage:
79
810const HOST = process . env . HOST ? process . env . HOST : '127.0.0.1' ;
911const PORT = process . env . PORT ? Number ( process . env . PORT ) : 9990 ;
12+ const DEBUG = [ '1' , 'true' ] . includes ( process . env . DEBUG ) ;
13+
14+ function debug ( name , content ) {
15+ if ( DEBUG ) {
16+ console . log ( name , util . inspect ( content , {
17+ colors : true ,
18+ depth : null ,
19+ compact : false ,
20+ } ) ) ;
21+ }
22+ }
1023
11- async function chat ( messages , maxTokens ) {
24+ async function complete ( messages , maxTokens , extra = { } ) {
25+ const body = {
26+ messages,
27+ temperature : 0.7 ,
28+ stop : [ '<|eot_id|>' ] ,
29+ max_tokens : maxTokens ,
30+ ...extra
31+ } ;
32+ debug ( '🔵 Request' , body ) ;
1233 const response = await fetch ( `http://${ HOST } :${ PORT } /v1/chat/completions` , {
1334 method : 'POST' ,
1435 headers : {
1536 'Content-Type' : 'application/json' ,
1637 } ,
17- body : JSON . stringify ( {
18- messages,
19- temperature : 0.7 ,
20- stop : [ '<|eot_id|>' ] ,
21- max_tokens : maxTokens
22- } ) ,
38+ body : JSON . stringify ( body ) ,
2339 } ) ;
24- return await response . json ( ) ;
40+ const json = await response . json ( ) ;
41+ debug ( '🔴 Response' , json ) ;
42+ return json ;
2543}
2644
2745async function ask ( system , user , maxTokens ) {
2846 console . log ( `> system: ${ system } ` ) ;
2947 console . log ( `> user: ${ user } ` ) ;
30- const response = await chat ( [
48+ const response = await complete ( [
3149 {
3250 role : 'system' ,
3351 content : system
@@ -41,9 +59,92 @@ async function ask(system, user, maxTokens) {
4159 console . log ( response . choices [ 0 ] . message . content ) ;
4260}
4361
62+ async function askWithTools ( companyName , maxTokens ) {
63+ const tools = [
64+ {
65+ type : 'function' ,
66+ function : {
67+ name : 'get_most_popular_car_by_company' ,
68+ description : 'Return the most popular car model for a given company name.' ,
69+ parameters : {
70+ type : 'object' ,
71+ properties : {
72+ companyName : {
73+ type : 'string' ,
74+ description : 'Car company name, e.g., `Toyota`, `Ford`'
75+ }
76+ } ,
77+ required : [ 'companyName' ]
78+ }
79+ }
80+ } ,
81+ {
82+ type : 'function' ,
83+ function : {
84+ name : 'get_car_sales_this_year' ,
85+ description : 'Return total sales for the given car company for the current calendar year.' ,
86+ parameters : {
87+ type : 'object' ,
88+ properties : {
89+ companyNameAndCarName : {
90+ type : 'string' ,
91+ description : 'Car company name and car name concatenated, e.g., `Toyota - Corolla`'
92+ }
93+ } ,
94+ required : [ 'companyNameAndCarName' ]
95+ }
96+ }
97+ } ] ;
98+
99+ const messages = [
100+ { role : 'system' , content : 'You can use only 1 tool at the time.' } ,
101+ { role : 'user' , content : `Tell me about the most popular car from ${ companyName } and its sales this year.` }
102+ ] ;
103+
104+ console . log ( `> user: ${ messages [ 1 ] . content } ` ) ;
105+
106+ let response ;
107+ for ( let i = 0 ; ; i ++ ) {
108+ response = await complete ( messages , maxTokens , { tools, tool_choice : 'auto' } ) ;
109+ const choice = response . choices [ 0 ] ;
110+
111+ if ( choice . finish_reason !== 'tool_calls' || ! choice . message . tool_calls ?. length ) {
112+ break ;
113+ }
114+ messages . push ( choice . message ) ;
115+ for ( const call of choice . message . tool_calls ) {
116+ switch ( call . function . name ) {
117+ case 'get_most_popular_car_by_company' :
118+ messages . push ( {
119+ role : 'tool' ,
120+ tool_call_id : call . id ,
121+ content : JSON . stringify ( {
122+ carName : 'Corolla'
123+ } )
124+ } ) ;
125+ break ;
126+ case 'get_car_sales_this_year' :
127+ messages . push ( {
128+ role : 'tool' ,
129+ tool_call_id : call . id ,
130+ content : JSON . stringify ( {
131+ salesThisYear : 250000
132+ } )
133+ } ) ;
134+ break ;
135+ default :
136+ throw new Error ( `Unsupported tool: ${ call . function . name } ` ) ;
137+ }
138+ }
139+ }
140+
141+ console . log ( response . choices [ 0 ] . message . content ) ;
142+ }
143+
44144async function main ( ) {
45- await ask ( 'You are an excellent math teacher.' , 'What is 1 + 2?' , 128 ) ;
46- await ask ( 'You are a romantic.' , 'Where is Europe?' , 128 ) ;
145+ await ask ( 'You are an excellent math teacher.' , 'What is 1 + 2?' , 256 ) ;
146+ await ask ( 'You are a romantic.' , 'Where is Europe?' , 256 ) ;
147+ await askWithTools ( 'Toyota' , 5000 ) ;
47148}
48149
49150main ( ) ;
0 commit comments