1// MEES Assistant API Endpoint with v2 API
2// Remember to add your environment variables in Val settings:
3// - OPENAI_API_KEY
4// - PINECONE_API_KEY
5// - ASSISTANT_ID
6// - PARSER_ASSISTANT_ID (optional)
7
8import { OpenAI } from "https://deno.land/x/openai@v4.20.1/mod.ts";
9import { Pinecone } from "https://esm.sh/@pinecone-database/pinecone@2.0.0";
10
11// Use OpenAI client only for embeddings
12const openai = new OpenAI({
13 apiKey: Deno.env.get("OPENAI_API_KEY"),
14});
15
42async function parseQueryIntent(query: string) {
43 try {
44 const OPENAI_API_KEY = Deno.env.get("OPENAI_API_KEY");
45
46 // Create a quick thread for parsing
47 const threadResponse = await fetch("https://api.openai.com/v1/threads", {
48 method: "POST",
49 headers: {
50 "Authorization": `Bearer ${OPENAI_API_KEY}`,
51 "Content-Type": "application/json",
52 "OpenAI-Beta": "assistants=v2",
53 },
54 body: JSON.stringify({}),
58
59 // Add the query
60 await fetch(`https://api.openai.com/v1/threads/${thread.id}/messages`, {
61 method: "POST",
62 headers: {
63 "Authorization": `Bearer ${OPENAI_API_KEY}`,
64 "Content-Type": "application/json",
65 "OpenAI-Beta": "assistants=v2",
66 },
67 body: JSON.stringify({
72
73 // Run the parser assistant
74 const runResponse = await fetch(`https://api.openai.com/v1/threads/${thread.id}/runs`, {
75 method: "POST",
76 headers: {
77 "Authorization": `Bearer ${OPENAI_API_KEY}`,
78 "Content-Type": "application/json",
79 "OpenAI-Beta": "assistants=v2",
80 },
81 body: JSON.stringify({
100
101 const statusResponse = await fetch(
102 `https://api.openai.com/v1/threads/${thread.id}/runs/${run.id}`,
103 {
104 headers: {
105 "Authorization": `Bearer ${OPENAI_API_KEY}`,
106 "OpenAI-Beta": "assistants=v2",
107 },
108 },
114 // Get the response
115 const messagesResponse = await fetch(
116 `https://api.openai.com/v1/threads/${thread.id}/messages?order=desc&limit=1`,
117 {
118 headers: {
119 "Authorization": `Bearer ${OPENAI_API_KEY}`,
120 "OpenAI-Beta": "assistants=v2",
121 },
122 },
156
157 // Get embedding for query
158 const embeddingResponse = await openai.embeddings.create({
159 model: "text-embedding-3-small",
160 input: query,
327 });
328
329 // Step 4: Format data for OpenAI
330 debugInfo += `\n\nš¦ STEP 4: DATA FORMATTING FOR OPENAI\n${"-".repeat(40)}\n`;
331
332 const formattedResults = searchResults.slice(0, 10).map((match) => {
336 const mediaInText = extractMediaFromText(meta.text || "");
337
338 // Truncate text for OpenAI
339 let textContent = meta.text || "";
340 const maxTextLength = 500;
368 });
369
370 debugInfo += `ā
Formatted ${formattedResults.length} results for OpenAI\n`;
371 debugInfo += `š Sample formatted result:\n${
372 JSON.stringify(formattedResults[0], null, 2).substring(0, 800)
542 }
543
544 const OPENAI_API_KEY = Deno.env.get("OPENAI_API_KEY");
545 if (!OPENAI_API_KEY) {
546 throw new Error("OPENAI_API_KEY not found in environment variables");
547 }
548
551 }
552
553 // IMPORTANT: All OpenAI API calls use these headers with assistants=v2
554 const baseHeaders = {
555 "Authorization": `Bearer ${OPENAI_API_KEY}`,
556 "Content-Type": "application/json",
557 "OpenAI-Beta": "assistants=v2",
558 };
559
560 console.log("Assistant ID:", ASSISTANT_ID);
561 console.log("Using OpenAI-Beta: assistants=v2");
562
563 // Parse the query first (if parser assistant is configured)
594 let thread;
595 if (threadId) {
596 const threadResponse = await fetch(`https://api.openai.com/v1/threads/${threadId}`, {
597 headers: baseHeaders,
598 });
602 thread = await threadResponse.json();
603 } else {
604 const threadResponse = await fetch("https://api.openai.com/v1/threads", {
605 method: "POST",
606 headers: baseHeaders,
627
628 // Add message to thread with v2 headers
629 const messageResponse = await fetch(`https://api.openai.com/v1/threads/${thread.id}/messages`, {
630 method: "POST",
631 headers: baseHeaders,
641
642 // Run the assistant with v2 headers
643 const runResponse = await fetch(`https://api.openai.com/v1/threads/${thread.id}/runs`, {
644 method: "POST",
645 headers: baseHeaders,
693 const mediaInText = extractMediaFromText(meta.text || "");
694
695 // OPTIMIZATION: Only send text excerpts to OpenAI
696 let textContent = meta.text || "";
697 const maxTextLength = 500;
876
877 const statusResponse = await fetch(
878 `https://api.openai.com/v1/threads/${thread.id}/runs/${run.id}`,
879 { headers: baseHeaders },
880 );
905 // Submit tool outputs with v2 headers
906 const toolOutputResponse = await fetch(
907 `https://api.openai.com/v1/threads/${thread.id}/runs/${run.id}/submit_tool_outputs`,
908 {
909 method: "POST",
929 // Get the assistant's response with v2 headers
930 const messagesResponse = await fetch(
931 `https://api.openai.com/v1/threads/${thread.id}/messages?order=desc&limit=20`,
932 { headers: baseHeaders },
933 );