@@ -40,6 +40,7 @@ import { z } from "zod";
4040import { analyzeQuery } from "../utils/analyzeQuery" ;
4141import { includeFilters } from "../utils/includeFilters" ;
4242import { TimetableFormSchema } from "../models/timetable-form" ;
43+ import { CreateTimetableArgs } from "../models/timetable-generate" ;
4344
4445const openai = createOpenAI ( {
4546 baseURL : process . env . OPENAI_BASE_URL ,
@@ -55,7 +56,7 @@ const pinecone = new Pinecone({
5556} ) ;
5657
5758const index : Index < RecordMetadata > = pinecone . Index (
58- process . env . PINECONE_INDEX_NAME ! ,
59+ process . env . PINECONE_INDEX_NAME !
5960) ;
6061
6162console . log ( "Connected to OpenAI API" ) ;
@@ -64,7 +65,7 @@ export async function searchSelectedNamespaces(
6465 query : string ,
6566 k : number ,
6667 namespaces : string [ ] ,
67- filters ?: Object ,
68+ filters ?: Object
6869) : Promise < Document [ ] > {
6970 let allResults : Document [ ] = [ ] ;
7071
@@ -86,7 +87,7 @@ export async function searchSelectedNamespaces(
8687 const results = await namespaceStore . similaritySearch (
8788 query ,
8889 Math . max ( k , namespaceToMinResults . get ( namespace ) ) ,
89- namespace === "courses_v3" ? filters : undefined ,
90+ namespace === "courses_v3" ? filters : undefined
9091 ) ;
9192 console . log ( `Found ${ results . length } results in namespace: ${ namespace } ` ) ;
9293 allResults = [ ...allResults , ...results ] ;
@@ -107,7 +108,7 @@ export async function searchSelectedNamespaces(
107108// Reformulate user query to make more concise query to database, taking into consideration context
108109export async function reformulateQuery (
109110 latestQuery : string ,
110- conversationHistory : any [ ] ,
111+ conversationHistory : any [ ]
111112) : Promise < string > {
112113 try {
113114 const openai2 = new OpenAI ( {
@@ -248,7 +249,8 @@ export const chat = asyncHandler(async (req: Request, res: Response) => {
248249
249250 ## Tool call guidelines
250251 - Include the timetable ID in all getTimetbles tool call responses
251- - If the tool call is a getTimetables call, then at the end of each timetable listed, include a link displayed as "View timetable" to ${ process . env . CLIENT_APP_URL } /dashboard/timetable?edit=[[TIMETABLE_ID]] , where TIMETABLE_ID is the id of the respective timetable.
252+ - For every tool call, for each timetable that it gets/deletes/modifies/creates, include a link underneath it displayed as "View timetable" to ${ process . env . CLIENT_APP_URL } /dashboard/timetable?edit=[[TIMETABLE_ID]] , where TIMETABLE_ID is the id of the respective timetable.
253+ - If the user provides a course code of length 6 like CSCA08, then assume they mean CSCA08H3 (H3 appended)
252254 ` ,
253255 messages,
254256 tools : {
@@ -282,13 +284,23 @@ export const chat = asyncHandler(async (req: Request, res: Response) => {
282284 return await availableFunctions . deleteTimetable ( args , req ) ;
283285 } ,
284286 } ) ,
287+ createTimetable : tool ( {
288+ description :
289+ "Create a timetable with the provided meeting sections" ,
290+ parameters : CreateTimetableArgs ,
291+ execute : async ( args ) => {
292+ return await availableFunctions . createTimetable ( args , req ) ;
293+ } ,
294+ } ) ,
285295 generateTimetable : tool ( {
286- description : "Generate a timetable based on selected courses and restrictions" ,
296+ description :
297+ "Return a list of possible timetables based on provided courses and restrictions" ,
287298 parameters : TimetableFormSchema ,
288299 execute : async ( args ) => {
289- return await availableFunctions . generateTimetable ( args , req )
290- }
291- } )
300+ console . log ( "Args: " , args ) ;
301+ return await availableFunctions . generateTimetable ( args , req ) ;
302+ } ,
303+ } ) ,
292304 } ,
293305 maxSteps : CHATBOT_TOOL_CALL_MAX_STEPS , // Controls how many back and forths the model can take with user or calling multiple tools
294306 experimental_repairToolCall : async ( {
@@ -305,10 +317,10 @@ export const chat = asyncHandler(async (req: Request, res: Response) => {
305317 console . log (
306318 `The model tried to call the tool "${ toolCall . toolName } "` +
307319 ` with the following arguments:` ,
308- JSON . stringify ( toolCall . args ) ,
320+ toolCall . args ,
309321 `The tool accepts the following schema:` ,
310- JSON . stringify ( parameterSchema ( toolCall ) ) ,
311- "Please fix the arguments." ,
322+ parameterSchema ( toolCall ) ,
323+ "Please fix the arguments."
312324 ) ;
313325
314326 const { object : repairedArgs } = await generateObject ( {
@@ -343,7 +355,7 @@ export const chat = asyncHandler(async (req: Request, res: Response) => {
343355 // Use GPT-4o to reformulate the query based on conversation history
344356 const reformulatedQuery = await reformulateQuery (
345357 latestMessage ,
346- conversationHistory . slice ( - CHATBOT_MEMORY_THRESHOLD ) , // last K messages
358+ conversationHistory . slice ( - CHATBOT_MEMORY_THRESHOLD ) // last K messages
347359 ) ;
348360 console . log ( ">>>> Original query:" , latestMessage ) ;
349361 console . log ( ">>>> Reformulated query:" , reformulatedQuery ) ;
@@ -357,8 +369,8 @@ export const chat = asyncHandler(async (req: Request, res: Response) => {
357369 if ( requiresSearch ) {
358370 console . log (
359371 `Query requires knowledge retrieval, searching namespaces: ${ relevantNamespaces . join (
360- ", " ,
361- ) } `,
372+ ", "
373+ ) } `
362374 ) ;
363375
364376 const filters = includeFilters ( reformulatedQuery ) ;
@@ -369,7 +381,7 @@ export const chat = asyncHandler(async (req: Request, res: Response) => {
369381 reformulatedQuery ,
370382 3 ,
371383 relevantNamespaces ,
372- Object . keys ( filters ) . length === 0 ? undefined : filters ,
384+ Object . keys ( filters ) . length === 0 ? undefined : filters
373385 ) ;
374386 // console.log("Search Results: ", searchResults);
375387
@@ -379,7 +391,7 @@ export const chat = asyncHandler(async (req: Request, res: Response) => {
379391 }
380392 } else {
381393 console . log (
382- "Query does not require knowledge retrieval, skipping search" ,
394+ "Query does not require knowledge retrieval, skipping search"
383395 ) ;
384396 }
385397
@@ -444,15 +456,15 @@ export const testSimilaritySearch = asyncHandler(
444456 if ( requiresSearch ) {
445457 console . log (
446458 `Query requires knowledge retrieval, searching namespaces: ${ relevantNamespaces . join (
447- ", " ,
448- ) } `,
459+ ", "
460+ ) } `
449461 ) ;
450462
451463 // Search only the relevant namespaces
452464 const searchResults = await searchSelectedNamespaces (
453465 message ,
454466 3 ,
455- relevantNamespaces ,
467+ relevantNamespaces
456468 ) ;
457469 console . log ( "Search Results: " , searchResults ) ;
458470
@@ -462,11 +474,11 @@ export const testSimilaritySearch = asyncHandler(
462474 }
463475 } else {
464476 console . log (
465- "Query does not require knowledge retrieval, skipping search" ,
477+ "Query does not require knowledge retrieval, skipping search"
466478 ) ;
467479 }
468480
469481 console . log ( "CONTEXT: " , context ) ;
470482 res . status ( 200 ) . send ( context ) ;
471- } ,
483+ }
472484) ;
0 commit comments