gcharanteja
feat: enhance search handling to provide user-friendly messages and formatted results
0c3ae10 | import { askOpenAI } from "./llm.js"; | |
| import { curateText } from "./curation.js"; | |
| import { queryCollectionDataEnhanced, queryCollectionData } from "./vector.js"; | |
| import { loadContextTreeDocuments } from "../utils.js"; | |
| export async function routeUserInput(input, config) { | |
| try { | |
| const intent = await classifyIntent(input, config); | |
| switch (intent.type) { | |
| case "search": | |
| return await handleSearch(input, intent, config); | |
| case "curate": | |
| return await handleCurate(input, intent, config); | |
| case "add": | |
| return await handleAdd(input, intent, config); | |
| case "list": | |
| return await handleList(input, intent, config); | |
| default: | |
| return { | |
| error: "Could not determine intent", | |
| input, | |
| intent: intent.type, | |
| }; | |
| } | |
| } catch (error) { | |
| return { | |
| error: `Routing failed: ${error.message}`, | |
| input, | |
| }; | |
| } | |
| } | |
| async function classifyIntent(input, config) { | |
| const prompt = `Analyze this user input and classify the intent. Return ONLY valid JSON: | |
| Input: "${input}" | |
| Classify as one of these intents: | |
| - "search": User is asking questions to find knowledge | |
| - "curate": User is teaching/storing new knowledge | |
| - "add": User is adding documents to the knowledge base | |
| - "list": User wants to see all stored knowledge | |
| Response format (valid JSON only): | |
| { | |
| "type": "search|curate|add|list", | |
| "confidence": 0.0-1.0, | |
| "reasoning": "brief explanation", | |
| "hints": { | |
| "enhanced": false, | |
| "rerank": false, | |
| "extractText": null | |
| } | |
| }`; | |
| try { | |
| const response = await askOpenAI(input, prompt); | |
| const parsed = JSON.parse(response); | |
| return parsed; | |
| } catch (error) { | |
| console.error("Intent classification failed:", error.message); | |
| return { type: "search", confidence: 0.5, reasoning: "Fallback to search" }; | |
| } | |
| } | |
| async function handleSearch(input, intent, config) { | |
| try { | |
| const searchParams = { | |
| query: input, | |
| nResults: 5, | |
| enhanced: intent.hints?.enhanced || false, | |
| rerank: intent.hints?.rerank || false, | |
| }; | |
| const results = searchParams.enhanced | |
| ? await queryCollectionDataEnhanced(searchParams) | |
| : await queryCollectionData(searchParams); | |
| const documents = results.ids?.[0] || []; | |
| const contents = results.documents?.[0] || []; | |
| const metadatas = results.metadatas?.[0] || []; | |
| if (documents.length === 0) { | |
| return { | |
| intent: "search", | |
| query: input, | |
| answer: "No matching knowledge found. Please curate relevant documentation first.", | |
| }; | |
| } | |
| const answer = contents | |
| .map((content, idx) => { | |
| const meta = metadatas[idx] || {}; | |
| return `**${meta.title || documents[idx]}** (${meta.topic || "general"})\n${content}`; | |
| }) | |
| .join("\n\n---\n\n"); | |
| return { | |
| intent: "search", | |
| query: input, | |
| answer, | |
| }; | |
| } catch (error) { | |
| return { | |
| intent: "search", | |
| error: `Search failed: ${error.message}`, | |
| query: input, | |
| }; | |
| } | |
| } | |
| async function handleCurate(input, intent, config) { | |
| try { | |
| const textToCurate = intent.hints?.extractText || input; | |
| const result = await curateText(textToCurate, config); | |
| return { | |
| intent: "curate", | |
| action: "extracted_and_stored", | |
| result, | |
| }; | |
| } catch (error) { | |
| return { | |
| intent: "curate", | |
| error: `Curation failed: ${error.message}`, | |
| input, | |
| }; | |
| } | |
| } | |
| async function handleAdd(input, intent, config) { | |
| return { | |
| intent: "add", | |
| message: | |
| "To add documents, use the add_documents tool with an array of {id, text, metadata}", | |
| guidance: input, | |
| }; | |
| } | |
| async function handleList(input, intent, config) { | |
| try { | |
| const dataDir = process.env.DATA_DIR || "/data"; | |
| const docs = await loadContextTreeDocuments(dataDir); | |
| return { | |
| intent: "list", | |
| count: docs.length, | |
| documents: docs.map((d) => ({ | |
| id: d.id, | |
| title: d.title, | |
| topic: d.topic, | |
| type: d.type, | |
| importance: d.importance, | |
| filePath: d.filePath, | |
| })), | |
| }; | |
| } catch (error) { | |
| return { | |
| intent: "list", | |
| error: `List failed: ${error.message}`, | |
| }; | |
| } | |
| } | |