import { anthropic } from "@ai-sdk/anthropic"; import { convertToCoreMessages, streamText, tool } from "ai"; import { CodeInterpreter } from "@e2b/code-interpreter"; import { z } from "zod"; import { geolocation } from "@vercel/functions"; // Allow streaming responses up to 30 seconds export const maxDuration = 60; export async function POST(req: Request) { const { messages, model } = await req.json(); const { latitude, longitude, city } = geolocation(req) const ansmodel = anthropic(model); const result = await streamText({ model: ansmodel, messages: convertToCoreMessages(messages), temperature: 0, maxTokens: 800, system: "You are an AI web search engine that helps users find information on the internet.\n" + "Always start with running the tool(s) and then and then only write your response AT ALL COSTS!!\n" + "Your basic task to first and foremost gather information from a tool and then write your response with images(with web_search)!.\n" + "Never write a response without running the tool(s) first!\n" + "Do not announce or inform the user in any way that your going to run a tool at ALL COSTS!! Just `run` it and then write your response AT ALL COSTS!!!!!." + "Tool Usage Instructions:\n" + "The user is located in " + city + " at latitude " + latitude + " and longitude " + longitude + "." + "Use this geolocation data for weather tool, when the user doesn't provide a specific location." + "You use the 'web_search' tool to search for information on the internet before saying anyting to the user." + "Incomplete details or any other said words before the search tool result in a bad response." + "Always call the 'web_search' tool to get the information, no need to do a chain of thought or say anything else, go straight to the point." + "Once you have found the information, you provide the user with the information you found in brief like a news paper detail." + "The detail should be 3-5 paragraphs in 10-12 sentences and put citations using the markdown link format like this always: [](link to the site) in the end of each paragraph!" + "Citations will the render in the client side, so please make sure you format them correctly!" + "Never use pointers, unless asked to." + "Do not start the responses with newline characters, always start with the first sentence." + "When the user asks about a Stock, you should 'always' first gather news about it with web search tool, then show the chart and then write your response. Follow these steps in this order only!" + "Never use the retrieve tool for general search. Always use it when the user provides an url! " + "For weather related questions, use get_weather_data tool and write your response. No need to call any other tool. DO NOT put citation to OpenWeatherMaps API EVER!" + "Use the 'programming' tool to execute Python code for cases like calculating, sorting, etc. that require computation. " + "The environment is like a jupyter notebook so don't write print statements at all costs!, just write variables in the end.\n\n" + "The current date is: " + new Date() .toLocaleDateString("en-US", { year: "numeric", month: "short", day: "2-digit", weekday: "short", }) .replace(/(\w+), (\w+) (\d+), (\d+)/, "$4-$2-$3 ($1)") + "." + "Rules for the response:\n" + "Please do not use tags like , or in the response. it breaks the reader's attention to these stupid mistakes." + "Remember to always use the 'web_search' tool to gather information before writing a response." + "You are a graduate level AI, so please write responses accordingly." + "Never start with 'based on the search results,...' EVER! Always start with the information you found like an article!" + "Never use the heading format in your response!." + "Do not use print statements in the code execution tool, just the variables." + "Don't say things like 'Okay I am going to perform some action.' OR 'Certainly! To count the number of 'r's in the word 'strawberry', we can use a simple Python code. Let's use the programming tool to execute this task.' The user's DO NOT LIKE TO WAIT! REMEMBER THE THING ABOUT PRINT STATEMENTS! NEVER WRITE 'EM!" + "IMPORTANT!!!: Refrain from saying things like that mention that your going to perform a certain action, example: 'Certainly! I'll search for information about using the web search tool.'", tools: { web_search: tool({ description: "Search the web for information with the given query, max results and search depth.", parameters: z.object({ query: z.string().describe("The search query to look up on the web."), maxResults: z .number() .describe( "The maximum number of results to return. Default to be used is 10.", ), searchDepth: z .enum(["basic", "advanced"]) .describe( "The search depth to use for the search. Default is basic.", ), exclude_domains: z .array(z.string()) .optional() .describe( "A list of domains to specifically exclude from the search results. Default is None, which doesn't exclude any domains.", ), }), execute: async ({ query, maxResults, searchDepth, exclude_domains, }: { query: string; maxResults: number; searchDepth: "basic" | "advanced"; exclude_domains?: string[]; }) => { const apiKey = process.env.TAVILY_API_KEY; const response = await fetch("https://api.tavily.com/search", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ api_key: apiKey, query, max_results: maxResults < 5 ? 5 : maxResults, search_depth: searchDepth, include_answers: true, exclude_domains: exclude_domains, }), }); const data = await response.json(); let context = data.results.map( (obj: { url: any; content: any; title: any; raw_content: any }) => { return { url: obj.url, title: obj.title, content: obj.content, raw_content: obj.raw_content, }; }, ); return { results: context, }; }, }), retrieve: tool({ description: "Retrieve the information from a URL.", parameters: z.object({ url: z.string().describe("The URL to retrieve the information from."), }), execute: async ({ url }: { url: string }) => { let hasError = false; let results; try { const response = await fetch(`https://r.jina.ai/${url}`, { method: "GET", headers: { Accept: "application/json", "X-With-Generated-Alt": "true", }, }); const json = await response.json(); if (!json.data || json.data.length === 0) { hasError = true; } else { // Limit the content to 5000 characters if (json.data.content.length > 5000) { json.data.content = json.data.content.slice(0, 5000); } results = { results: [ { title: json.data.title, content: json.data.content, url: json.data.url, }, ], query: "", images: [], }; } } catch (error) { hasError = true; console.error("Retrieve API error:", error); } if (hasError || !results) { return results; } return results; }, }), get_weather_data: tool({ description: "Get the weather data for the given coordinates.", parameters: z.object({ lat: z.number().describe("The latitude of the location."), lon: z.number().describe("The longitude of the location."), }), execute: async ({ lat, lon }: { lat: number; lon: number }) => { const apiKey = process.env.OPENWEATHER_API_KEY; const response = await fetch( `https://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${lon}&appid=${apiKey}`, ); const data = await response.json(); return data; }, }), stock_chart_ui: tool({ description: "Display the stock chart for the given stock symbol after web search.", parameters: z.object({ symbol: z .string() .describe("The stock symbol to display the chart for."), }), }), programming: tool({ description: "Write and execute Python code.", parameters: z.object({ code: z.string().describe("The Python code to execute."), }), execute: async ({ code }: { code: string }) => { const sandbox = await CodeInterpreter.create(); const execution = await sandbox.notebook.execCell(code); if (execution.results.length > 0) { let message: string = ""; for (const result of execution.results) { if (result.isMainResult) { message += `${result.text}\n`; } else { message += `${result.text}\n`; } if (result.formats().length > 0) { message += `It has following formats: ${result.formats()}\n`; } } return message; } if ( execution.logs.stdout.length > 0 || execution.logs.stderr.length > 0 ) { let message = ""; if (execution.logs.stdout.length > 0) { message += `${execution.logs.stdout.join("\n")}\n`; } if (execution.logs.stderr.length > 0) { message += `${execution.logs.stderr.join("\n")}\n`; } return message; } return "There was no output of the execution."; }, }), }, }); return result.toAIStreamResponse(); }