UNPKG

@accounter/server

Version:
128 lines (126 loc) 4.83 kB
import { __decorate } from "tslib"; import { generateText, Output } from 'ai'; import { Injectable, Scope } from 'graphql-modules'; import stripIndent from 'strip-indent'; import { z } from 'zod'; import { anthropic } from '@ai-sdk/anthropic'; import { Currency, DocumentType } from '../../shared/enums.js'; const documentDataSchema = z.object({ type: z.enum(DocumentType).nullable().optional().describe('The type of financial document'), issuer: z.string().optional().describe('Legal name of the organization that issued the document'), recipient: z .string() .nullable() .optional() .describe('Legal name and details of the entity to whom the document is addressed'), fullAmount: z .number() .nullable() .optional() .describe('Total monetary amount including taxes and all charges'), currency: z.enum(Currency).optional().describe('ISO 4217 currency code'), vatAmount: z .number() .nullable() .optional() .describe('Value Added Tax amount if separately specified on the document'), date: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/) .nullable() .optional() .describe('Document issue date in ISO 8601 format (YYYY-MM-DD)'), referenceCode: z .string() .nullable() .optional() .describe('Complete document identifier including any separators (e.g., dashes, slashes)'), allocationNumber: z .string() .length(9) .nullable() .optional() .describe('Should be empty if no VAT amount. Unique document 9-digits allocation number (מספר הקצאה). Usually last 9 digits of a longer number.'), description: z .string() .nullable() .optional() .describe('Additional description or remarks found on the document'), }); const SUPPORTED_FILE_TYPES = [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf', ]; function isSupportedFileType(value) { return SUPPORTED_FILE_TYPES.includes(value); } let AnthropicProvider = class AnthropicProvider { /** * Convert File or Blob to Base64 * @param fileOrBlob File or Blob to convert * @returns Base64 encoded string */ async fileToBase64(fileOrBlob) { const buffer = await fileOrBlob.arrayBuffer(); const base64string = Buffer.from(buffer).toString('base64'); return base64string; } /** * Extract invoice details using Anthropic API * @param fileOrBlob File or Blob to process * @returns Parsed invoice data */ async extractInvoiceDetails(fileOrBlob) { const fileType = fileOrBlob.type.toLowerCase(); if (!isSupportedFileType(fileType)) { throw new Error('Unsupported file type. Please provide an image or PDF.'); } const fileData = await this.fileToBase64(fileOrBlob); const { output } = await generateText({ model: anthropic('claude-sonnet-4-5'), output: Output.object({ schema: documentDataSchema }), messages: [ { role: 'user', content: [ { type: 'text', text: stripIndent(`Please analyze the provided document and extract: - Document type - Issuer and recipient details - Monetary amounts (total and VAT) - Date and reference numbers - Allocation number (if VAT exists and applicable) - Description or remarks Note that some receipts (e.g. by Stripe) carry the invoice details; pay extra attention not to misclassify them as INVOICE_RECEIPT. Return only a JSON object without any explanation. Use NULL value for missing values, allocation number is optional.`), }, fileType === 'application/pdf' ? { type: 'file', data: fileData, mediaType: fileType, } : { type: 'image', image: fileData, mediaType: fileType, }, ], }, ], }); return output; } }; AnthropicProvider = __decorate([ Injectable({ scope: Scope.Singleton, global: true, }) ], AnthropicProvider); export { AnthropicProvider }; //# sourceMappingURL=anthropic.js.map