Last active
July 24, 2025 12:15
-
-
Save matejminar/17f296ab43a01073da83d214df18668a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as Sentry from "@sentry/node" | |
| // Initialize Sentry | |
| Sentry.init({ | |
| debug: true, | |
| dsn: "============================================YOUR DSN HERE============================================", | |
| tracesSampleRate: 1.0, // Capture 100% of the transactions | |
| sendDefaultPii: true, // Send default PII data to Sentry | |
| integrations: [Sentry.vercelAIIntegration()], | |
| }); | |
| import 'dotenv/config'; | |
| import { generateText, tool } from "ai" | |
| import { openai } from "@ai-sdk/openai" | |
| import { z } from "zod" | |
| // Tool: Get typical amount range for a category | |
| export const getTypicalAmountRange = tool({ | |
| description: "Get the typical min and max amount for a given expense category.", | |
| parameters: z.object({ | |
| category: z.string().describe("The expense category"), | |
| }), | |
| execute: async ({ category }) => { | |
| console.log('TOOL: getTypicalAmountRange') | |
| const ranges = { | |
| Groceries: { min: 10, max: 100 }, | |
| Restaurants: { min: 15, max: 80 }, | |
| Transportation: { min: 2, max: 50 }, | |
| Entertainment: { min: 5, max: 100 }, | |
| Shopping: { min: 10, max: 500 }, | |
| Health: { min: 5, max: 200 }, | |
| Education: { min: 20, max: 300 }, | |
| Housing: { min: 100, max: 2000 }, | |
| Utilities: { min: 20, max: 300 }, | |
| Microspends: { min: 0, max: 1 }, | |
| Other: { min: 0, max: 100 }, | |
| }; | |
| return ranges[category] || { min: 0, max: 100 }; | |
| }, | |
| }); | |
| // Tool: Get day of week for a given date | |
| export const getDayOfWeek = tool({ | |
| description: "Get the day of the week for a given date (ISO string).", | |
| parameters: z.object({ | |
| date: z.string().describe("Date in ISO format"), | |
| }), | |
| execute: async ({ date }) => { | |
| console.log('TOOL: getDayOfWeek') | |
| const day = new Date(date).toLocaleDateString('en-US', { weekday: 'long' }); | |
| return { dayOfWeek: day }; | |
| }, | |
| }); | |
| const simpleExpenseTools = { | |
| getTypicalAmountRange, | |
| getDayOfWeek, | |
| }; | |
| const prompt = `You are an AI assistant that helps categorize expenses based on location, amount, datetime, and spending patterns. | |
| You will be given the current location, amount, datetime, and nearby expenses (with their datetimes). Your task is to suggest the most likely category | |
| for a new expense at this location, along with a confidence score. | |
| IMPORTANT: | |
| 1. You must respond with a valid JSON object only, no other text. The response must be in this exact format: | |
| { | |
| "category": "string", | |
| "confidence": number, | |
| "reasoning": "string" | |
| } | |
| 2. The category MUST be one of these exact values: Groceries, Restaurants, Transportation, Entertainment, Shopping, Health, Education, Housing, Utilities, Other, Microspends. Do not suggest any other categories. | |
| Consider these factors when making your suggestion: | |
| 1. The frequency of categories in nearby expenses | |
| 2. The typical spending patterns in the area | |
| 3. The context of the location (e.g., shopping district, restaurant area) | |
| 4. The amount of the expense and typical amounts for different categories | |
| 5. Amount patterns in nearby expenses | |
| 6. The datetime and day of week for the current and nearby expenses (use the getDayOfWeek tool if needed) | |
| Current location: 48.215746389754266, 16.38314893288571 | |
| Current amount: €12 | |
| Current datetime: 2025-06-11T10:29:11.788Z | |
| Nearby expenses: [{"category":"Entertainment","amount":12,"distance":121.98723007443857,"datetime":"2025-06-10T19:15:12.023Z"},{"category":"Entertainment","amount":12,"distance":169.34362964091804,"datetime":"2025-06-04T09:43:54.570Z"},{"category":"Entertainment","amount":10,"distance":38.06182406558493,"datetime":"2025-06-04T09:43:28.983Z"}]`; | |
| async function run() { | |
| console.log('Sending request to OpenAI...', prompt); | |
| const { text } = await generateText({ | |
| model: openai("gpt-4o-mini"), | |
| prompt, | |
| temperature: 0.7, | |
| tools: simpleExpenseTools, | |
| experimental_telemetry: { | |
| isEnabled: true, | |
| recordInputs: true, | |
| recordOutputs: true, | |
| }, | |
| maxSteps: 10 | |
| }); | |
| console.log('Received response from OpenAI:', text); | |
| } | |
| Sentry.startSpan({ name: 'run', 'op': 'function' }, async () => run()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment