receipt-ocr 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/processors/image.ts","../src/adapters/gemini.ts","../src/adapters/verifier.ts","../src/utils/prompt.ts","../src/processors/parser.ts","../src/extract.ts"],"names":["GoogleGenerativeAI","getGeminiConfig","result"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ImageInput } from '../types.js';\r\n\r\n/**\r\n * 图片数据接口,用于传递给 Gemini API\r\n */\r\nexport interface ProcessedImage {\r\n /** 图片的 MIME 类型 */\r\n mimeType: string;\r\n /** base64 编码的图片数据(不包含 data URI 前缀) */\r\n data?: string;\r\n /** 图片 URL(如果输入是 URL) */\r\n url?: string;\r\n}\r\n\r\n/**\r\n * 检测是否为 URL\r\n */\r\nfunction isUrl(input: string): boolean {\r\n return input.startsWith('http://') || input.startsWith('https://');\r\n}\r\n\r\n/**\r\n * 检测是否为 base64 字符串\r\n */\r\nfunction isBase64(input: string): boolean {\r\n // 简单检测:如果以 data: 开头,或者看起来像 base64\r\n if (input.startsWith('data:')) {\r\n return true;\r\n }\r\n // Base64 字符串通常很长,且只包含特定字符\r\n return input.length > 100 && /^[A-Za-z0-9+/=]+$/.test(input);\r\n}\r\n\r\n/**\r\n * 从 data URI 中提取 MIME 类型和数据\r\n */\r\nfunction parseDataUri(dataUri: string): { mimeType: string; data: string } {\r\n const match = dataUri.match(/^data:([^;,]+);base64,(.+)$/);\r\n if (match) {\r\n return {\r\n mimeType: match[1],\r\n data: match[2],\r\n };\r\n }\r\n // 如果没有匹配到,假设是纯 base64,默认 MIME 类型\r\n return {\r\n mimeType: 'image/jpeg',\r\n data: dataUri,\r\n };\r\n}\r\n\r\n/**\r\n * 从文件扩展名推断 MIME 类型\r\n */\r\nfunction getMimeTypeFromUrl(url: string): string {\r\n const lower = url.toLowerCase();\r\n if (lower.includes('.png')) return 'image/png';\r\n if (lower.includes('.jpg') || lower.includes('.jpeg')) return 'image/jpeg';\r\n if (lower.includes('.webp')) return 'image/webp';\r\n if (lower.includes('.gif')) return 'image/gif';\r\n // 默认\r\n return 'image/jpeg';\r\n}\r\n\r\n/**\r\n * 处理图片输入,转换为 Gemini API 可用的格式\r\n * \r\n * @param image - 图片输入(Buffer、base64 字符串或 URL)\r\n * @returns 处理后的图片数据\r\n */\r\nexport function processImage(image: ImageInput): ProcessedImage {\r\n // 如果是 Buffer\r\n if (Buffer.isBuffer(image)) {\r\n return {\r\n mimeType: 'image/jpeg', // 默认,实际中可能需要更精确的检测\r\n data: image.toString('base64'),\r\n };\r\n }\r\n\r\n // 如果是字符串\r\n if (typeof image === 'string') {\r\n // URL\r\n if (isUrl(image)) {\r\n return {\r\n mimeType: getMimeTypeFromUrl(image),\r\n url: image,\r\n };\r\n }\r\n\r\n // data URI\r\n if (image.startsWith('data:')) {\r\n const { mimeType, data } = parseDataUri(image);\r\n return { mimeType, data };\r\n }\r\n\r\n // 纯 base64\r\n if (isBase64(image)) {\r\n return {\r\n mimeType: 'image/jpeg',\r\n data: image,\r\n };\r\n }\r\n\r\n // 无法识别,抛出错误\r\n throw new Error('Unsupported image format: string is not a valid URL or base64');\r\n }\r\n\r\n throw new Error('Unsupported image input type');\r\n}\r\n","import { GoogleGenerativeAI } from '@google/generative-ai';\nimport type { ImageInput } from '../types.js';\nimport { processImage } from '../processors/image.js';\n\n/**\n * 从环境变量读取 Gemini API 配置\n */\nfunction getGeminiConfig() {\n const apiKey = process.env.GEMINI_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'GEMINI_API_KEY environment variable is not set. Please set it to use the Gemini adapter.'\n );\n }\n\n const model = process.env.GEMINI_MODEL || 'gemini-2.0-flash';\n\n return { apiKey, model };\n}\n\n/**\n * 调用 Gemini API 进行图片分析\n * \n * @param image - 图片输入(Buffer、base64 或 URL)\n * @param prompt - 提示词\n * @param useGrounding - 是否使用 Google Search grounding\n * @returns LLM 返回的文本响应\n */\nexport async function callGemini(\n image: ImageInput,\n prompt: string,\n useGrounding?: boolean\n): Promise<string> {\n const { apiKey, model } = getGeminiConfig();\n\n // 初始化 Gemini API 客户端\n const genAI = new GoogleGenerativeAI(apiKey);\n const geminiModel = genAI.getGenerativeModel({ model });\n\n // 处理图片\n const processedImage = processImage(image);\n\n // 构建请求内容\n const contents = [];\n\n // 添加图片部分\n if (processedImage.url) {\n // 如果是 URL,使用 fileData\n contents.push({\n fileData: {\n mimeType: processedImage.mimeType,\n fileUri: processedImage.url,\n },\n });\n } else if (processedImage.data) {\n // 如果是 base64 数据,使用 inlineData\n contents.push({\n inlineData: {\n mimeType: processedImage.mimeType,\n data: processedImage.data,\n },\n });\n }\n\n // 添加文本提示\n contents.push({\n text: prompt,\n });\n\n try {\n // 调用 Gemini API\n // 如果启用 Google Search grounding,直接将 tools 作为顶级参数\n const requestParams: any = {\n contents: [{ role: 'user', parts: contents }],\n };\n \n if (useGrounding) {\n requestParams.tools = [{ googleSearch: {} }];\n }\n \n const result = await geminiModel.generateContent(requestParams);\n\n const response = result.response;\n const text = response.text();\n\n if (!text) {\n throw new Error('Gemini API returned empty response');\n }\n\n return text;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Gemini API call failed: ${error.message}`);\n }\n throw new Error('Gemini API call failed with unknown error');\n }\n}\n","/**\r\n * 使用 Google Search grounding 验证商品名称\r\n */\r\n\r\nimport { GoogleGenerativeAI } from '@google/generative-ai';\r\nimport type { ReceiptItem } from '../types.js';\r\n\r\n/**\r\n * 从环境变量读取 Gemini API 配置\r\n */\r\nfunction getGeminiConfig() {\r\n const apiKey = process.env.GEMINI_API_KEY;\r\n if (!apiKey) {\r\n throw new Error(\r\n 'GEMINI_API_KEY environment variable is not set. Please set it to use the Gemini adapter.'\r\n );\r\n }\r\n\r\n const model = process.env.GEMINI_MODEL || 'gemini-2.0-flash';\r\n\r\n return { apiKey, model };\r\n}\r\n\r\n/**\r\n * 构建批量验证 prompt\r\n */\r\nfunction buildVerificationPrompt(items: Partial<ReceiptItem>[]): string {\r\n const itemList = items\r\n .map((item, index) => `${index + 1}. \"${item.name}\"`)\r\n .join('\\n');\r\n\r\n return `这是从 Costco 超市小票中识别出的商品名称,部分名称可能不完整或有缩写。\r\n请使用 Google Search 查找并补全这些商品的完整正确名称。\r\n\r\n需要验证的商品:\r\n${itemList}\r\n\r\n验证方法建议:\r\n- 在搜索引擎中输入:商品原名 + \"Costco\"(例如:\"CEMOI 6X Costco\")\r\n- 这样能更准确地找到 Costco 销售的对应商品\r\n- 注意确认商品的包装规格(如数量、容量等)\r\n\r\n请返回 JSON 数组格式,每个商品包含:\r\n- index: 序号(1-based)\r\n- originalName: 原始名称\r\n- verifiedName: 验证后的完整名称(如果找到)\r\n- found: 是否找到匹配(布尔值)\r\n\r\n示例输出:\r\n[\r\n {\"index\": 1, \"originalName\": \"ORG MLK\", \"verifiedName\": \"Kirkland Signature Organic 2% Milk 1L\", \"found\": true},\r\n {\"index\": 2, \"originalName\": \"CEMΟΙ 6Χ\", \"verifiedName\": \"CEMOI 82% Dark Chocolate Bars, 6 × 100 g\", \"found\": true}\r\n]\r\n\r\n只返回 JSON 数组,不要其他文字。`;\r\n}\r\n\r\n/**\r\n * 解析验证响应\r\n */\r\ninterface VerificationResult {\r\n index: number;\r\n originalName: string;\r\n verifiedName: string;\r\n found: boolean;\r\n}\r\n\r\nfunction parseVerificationResponse(responseText: string): VerificationResult[] {\r\n try {\r\n // 移除可能的 markdown 代码块标记\r\n let cleaned = responseText.trim();\r\n const codeBlockMatch = cleaned.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\r\n if (codeBlockMatch) {\r\n cleaned = codeBlockMatch[1].trim();\r\n }\r\n\r\n const parsed = JSON.parse(cleaned);\r\n \r\n if (!Array.isArray(parsed)) {\r\n throw new Error('Response is not an array');\r\n }\r\n\r\n return parsed;\r\n } catch (error) {\r\n console.error('Failed to parse verification response:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * 批量验证商品名称\r\n * 使用 Google Search grounding 查找完整商品名\r\n * \r\n * @param items - 需要验证的商品列表\r\n * @returns 验证结果映射 (原始名称 -> 验证后名称)\r\n */\r\nexport async function batchVerifyItems(\r\n items: Partial<ReceiptItem>[]\r\n): Promise<Map<string, string>> {\r\n if (items.length === 0) {\r\n return new Map();\r\n }\r\n\r\n const { apiKey, model } = getGeminiConfig();\r\n const genAI = new GoogleGenerativeAI(apiKey);\r\n const geminiModel = genAI.getGenerativeModel({ model });\r\n\r\n // 构建验证 prompt\r\n const prompt = buildVerificationPrompt(items);\r\n\r\n try {\r\n // 使用 Google Search grounding\r\n // 注意:tools 应该直接作为 generateContent 的顶级参数,而不是嵌套在 config 里\r\n const result = await geminiModel.generateContent({\r\n contents: [{ role: 'user', parts: [{ text: prompt }] }],\r\n tools: [{ googleSearch: {} }],\r\n } as any);\r\n\r\n const response = result.response;\r\n const text = response.text();\r\n\r\n if (!text) {\r\n console.warn('Verification returned empty response');\r\n return new Map();\r\n }\r\n\r\n // 解析验证结果\r\n const verificationResults = parseVerificationResponse(text);\r\n\r\n // 构建映射\r\n const resultMap = new Map<string, string>();\r\n verificationResults.forEach((result) => {\r\n if (result.found && result.verifiedName) {\r\n resultMap.set(result.originalName, result.verifiedName);\r\n }\r\n });\r\n\r\n return resultMap;\r\n } catch (error) {\r\n console.error('Batch verification failed:', error);\r\n return new Map();\r\n }\r\n}\r\n","/**\n * 小票商品提取的 Prompt 模板\n * \n * 该模板要求 LLM:\n * 1. 从小票图片中提取所有商品信息\n * 2. 直接判断每个商品名称是否需要验证(needsVerification)\n * 3. 识别附加费用(押金、折扣)并标记归属关系\n * 4. 返回结构化的 JSON 数组\n */\nexport const EXTRACTION_PROMPT = `分析这张购物小票图片,提取所有商品信息。\n\n输出格式为 JSON 数组,每个商品包含:\n- name: 商品名称(字符串)\n- price: 单价(数字)\n- quantity: 数量(数字,默认 1)\n- needsVerification: 是否需要验证(布尔值)\n- hasTax: 是否含税(布尔值)\n- taxAmount: 税额(数字,可选)\n\n关于 needsVerification 的判断规则:\n- 如果商品名称是缩写、不完整、被截断或存在歧义,设为 true\n- 如果商品名称清晰完整,设为 false\n- 不要猜测不确定的名称,而是保留原样并设 needsVerification 为 true\n\n**重要:附加费用处理规则**\n对于押金(Deposit、deposit、押金等)和折扣(TPD、discount、折扣等)这类附加费用:\n- 添加额外字段 isAttachment: true\n- 添加 attachmentType: \"deposit\" 或 \"discount\"\n- **重要**:将附加费用紧跟在它所属的商品后面排列\n- 系统会自动将附加费用合并到它前面的商品中\n- 这些附加费用不会作为独立商品返回\n\n归属规则(按照这个顺序排列):\n- 商品A\n- 商品A的押金(如果有)\n- 商品A的折扣(如果有)\n- 商品B\n- 商品B的押金(如果有)\n- ...\n\n只返回 JSON 数组,不要其他文字。\n\n示例输出:\n[\n {\"name\": \"有机牛奶 1L\", \"price\": 12.5, \"quantity\": 1, \"needsVerification\": false, \"hasTax\": false},\n {\"name\": \"可口可乐瓶装\", \"price\": 3.5, \"quantity\": 2, \"needsVerification\": false, \"hasTax\": true, \"taxAmount\": 0.35},\n {\"name\": \"Deposit VL\", \"price\": 0.5, \"quantity\": 2, \"needsVerification\": false, \"hasTax\": false, \"isAttachment\": true, \"attachmentType\": \"deposit\"},\n {\"name\": \"TPD\", \"price\": -0.5, \"quantity\": 1, \"needsVerification\": false, \"hasTax\": false, \"isAttachment\": true, \"attachmentType\": \"discount\"},\n {\"name\": \"ORG BRD\", \"price\": 8.0, \"quantity\": 1, \"needsVerification\": true, \"hasTax\": true, \"taxAmount\": 0.8}\n]`;\n","import type { InternalReceiptItem } from '../types.js';\n\n/**\n * LLM 返回的原始商品数据结构\n */\ninterface RawReceiptItem {\n name: string;\n price: number;\n quantity: number; // 必填,normalizeRawItem 会提供默认值 1\n needsVerification: boolean;\n hasTax: boolean;\n taxAmount?: number;\n deposit?: number;\n discount?: number;\n // 附加费用标记(用于解析时的临时字段)\n isAttachment?: boolean;\n attachmentType?: 'deposit' | 'discount';\n attachedTo?: number;\n}\n\n/**\n * 从 LLM 响应中提取 JSON\n * 处理可能的 markdown 代码块包裹\n */\nfunction extractJson(text: string): string {\n // 移除可能的 markdown 代码块标记\n let cleaned = text.trim();\n \n // 匹配 ```json ... ``` 或 ``` ... ```\n const codeBlockMatch = cleaned.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n if (codeBlockMatch) {\n cleaned = codeBlockMatch[1].trim();\n }\n \n return cleaned;\n}\n\n/**\n * 验证并规范化原始商品数据\n */\nfunction normalizeRawItem(raw: any): RawReceiptItem {\n if (!raw || typeof raw !== 'object') {\n throw new Error('Invalid item: not an object');\n }\n\n if (typeof raw.name !== 'string' || !raw.name) {\n throw new Error('Invalid item: missing or invalid name field');\n }\n\n if (typeof raw.price !== 'number' || raw.price < 0) {\n throw new Error('Invalid item: missing or invalid price field');\n }\n\n return {\n name: raw.name,\n price: raw.price,\n quantity: typeof raw.quantity === 'number' ? raw.quantity : 1,\n needsVerification: Boolean(raw.needsVerification),\n hasTax: Boolean(raw.hasTax),\n taxAmount: typeof raw.taxAmount === 'number' ? raw.taxAmount : undefined,\n deposit: typeof raw.deposit === 'number' ? raw.deposit : undefined,\n discount: typeof raw.discount === 'number' ? raw.discount : undefined,\n // 保留附加费用标记用于后续处理\n isAttachment: raw.isAttachment === true ? true : undefined,\n attachmentType: raw.attachmentType,\n attachedTo: typeof raw.attachedTo === 'number' ? raw.attachedTo : undefined,\n };\n}\n\n/**\n * 合并附加费用(押金、折扣)到对应的商品中\n * 使用位置关系:附加费用紧跟在对应商品后面\n * \n * @param items - 包含附加费用标记的商品列表\n * @returns 合并后的商品列表(不包含独立的附加费用项)\n */\nfunction mergeAttachments(items: RawReceiptItem[]): RawReceiptItem[] {\n const result: RawReceiptItem[] = [];\n let currentItem: RawReceiptItem | null = null;\n \n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n \n if (!item.isAttachment) {\n // 如果之前有商品,先保存\n if (currentItem) {\n result.push(currentItem);\n }\n // 开始新商品(深拷贝)\n currentItem = { ...item };\n } else {\n // 这是附加费用,合并到当前商品\n if (currentItem) {\n if (item.attachmentType === 'deposit') {\n // 押金:累加(考虑数量)\n currentItem.deposit = (currentItem.deposit || 0) + (item.price * item.quantity);\n } else if (item.attachmentType === 'discount') {\n // 折扣:累加(通常已经是负数)\n currentItem.discount = (currentItem.discount || 0) + item.price;\n }\n }\n // 如果没有前置商品,跳过这个孤立的附加费用\n }\n }\n \n // 保存最后一个商品\n if (currentItem) {\n result.push(currentItem);\n }\n \n // 移除临时字段\n return result.map(item => {\n const { isAttachment, attachmentType, attachedTo, ...cleanItem } = item;\n return cleanItem;\n });\n}\n\n/**\n * 解析 LLM 返回的 JSON 响应为内部商品数组\n * \n * @param responseText - LLM 返回的文本响应\n * @returns 解析后的商品数组(包含 needsVerification 内部字段)\n * @throws 如果解析失败\n */\nexport function parseResponse(responseText: string): InternalReceiptItem[] {\n try {\n // 提取 JSON\n const jsonText = extractJson(responseText);\n\n // 解析 JSON\n const parsed = JSON.parse(jsonText);\n\n // 确保是数组\n if (!Array.isArray(parsed)) {\n throw new Error('Response is not an array');\n }\n\n // 验证并规范化每个商品\n const items = parsed.map((raw, index) => {\n try {\n return normalizeRawItem(raw);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new Error(`Invalid item at index ${index}: ${message}`);\n }\n });\n\n // 合并附加费用到对应的商品\n const mergedItems = mergeAttachments(items);\n\n return mergedItems;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to parse LLM response: ${error.message}\\n\\nResponse:\\n${responseText}`);\n }\n throw new Error(`Failed to parse LLM response with unknown error\\n\\nResponse:\\n${responseText}`);\n }\n}\n\n","import type { ImageInput, ExtractOptions, ReceiptItem, VerificationContext } from './types.js';\nimport { callGemini } from './adapters/gemini.js';\nimport { batchVerifyItems } from './adapters/verifier.js';\nimport { EXTRACTION_PROMPT } from './utils/prompt.js';\nimport { parseResponse } from './processors/parser.js';\n\n/**\n * 从小票图片中提取商品数据\n * \n * 这是一个无状态的异步函数,每次调用独立执行。\n * \n * @param image - 图片输入(Buffer、base64 字符串或 URL)\n * @param options - 可选配置(包括验证回调)\n * @returns 商品列表\n * \n * @throws 如果环境变量 GEMINI_API_KEY 未设置\n * @throws 如果 API 调用失败\n * @throws 如果响应解析失败\n * \n * @example\n * ```typescript\n * // 基础用法\n * const items = await extractReceiptItems(imageBuffer);\n * \n * // 使用自动验证(Google Search)\n * const items = await extractReceiptItems(imageBuffer, {\n * autoVerify: true\n * });\n * \n * // 带自定义验证回调\n * const items = await extractReceiptItems(imageBuffer, {\n * verifyCallback: async (name, context) => {\n * const result = await myProductSearch(name);\n * return result ? { verifiedName: result.name } : null;\n * }\n * });\n * ```\n */\nexport async function extractReceiptItems(\n image: ImageInput,\n options?: ExtractOptions\n): Promise<ReceiptItem[]> {\n // 1. 调用 Gemini API\n const responseText = await callGemini(image, EXTRACTION_PROMPT);\n\n // 2. 解析响应\n const parsedItems = parseResponse(responseText);\n\n // 3. 处理需要验证的商品\n const itemsNeedingVerification = parsedItems.filter(item => item.needsVerification);\n \n // 3a. 自动验证(使用 Google Search grounding)\n if (options?.autoVerify && itemsNeedingVerification.length > 0) {\n try {\n const verificationMap = await batchVerifyItems(itemsNeedingVerification);\n \n // 应用验证结果\n for (const item of parsedItems) {\n if (item.needsVerification) {\n const verifiedName = verificationMap.get(item.name);\n if (verifiedName) {\n item.name = verifiedName;\n item.needsVerification = false;\n }\n // 如果未找到,保持原名称和 needsVerification=true\n }\n }\n } catch (error) {\n console.error('Auto verification failed:', error);\n // 失败时保持原始数据\n }\n }\n \n // 3b. 用户提供的验证回调(可与 autoVerify 共存)\n if (options?.verifyCallback) {\n // 准备验证上下文(转换为公开类型)\n const publicItems: ReceiptItem[] = parsedItems.map(({ needsVerification, ...item }) => item);\n const verificationContext: VerificationContext = {\n rawText: responseText,\n allItems: publicItems,\n };\n\n for (const item of parsedItems) {\n if (item.needsVerification) {\n try {\n const result = await options.verifyCallback(item.name, verificationContext);\n if (result && result.verifiedName) {\n // 更新商品名称\n item.name = result.verifiedName;\n // 验证成功后,标记为不再需要验证\n item.needsVerification = false;\n }\n } catch (error) {\n // 验证失败,静默忽略,保留原始数据\n console.error(`Verification failed for item \"${item.name}\":`, error);\n }\n }\n }\n }\n\n // 4. 转换为公开类型:移除内部字段 needsVerification\n const finalItems: ReceiptItem[] = parsedItems.map(({ needsVerification, ...item }) => item);\n\n return finalItems;\n}\n"]}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * 对外公开的商品数据结构
3
+ * 这是 extractReceiptItems 函数返回的类型
4
+ */
5
+ interface ReceiptItem {
6
+ /** 商品名称 */
7
+ name: string;
8
+ /** 商品单价 */
9
+ price: number;
10
+ /** 商品数量,默认为 1 */
11
+ quantity: number;
12
+ /** 该商品是否产生税费 */
13
+ hasTax: boolean;
14
+ /** 该商品对应的具体税费金额(可选) */
15
+ taxAmount?: number;
16
+ /** 押金金额(可选,正数表示收押金,负数表示退押金) */
17
+ deposit?: number;
18
+ /** 折扣金额(可选,负数表示折扣) */
19
+ discount?: number;
20
+ }
21
+ /**
22
+ * 验证上下文,提供给验证回调/策略的额外信息
23
+ */
24
+ interface VerificationContext {
25
+ /** OCR 识别的原始文本 */
26
+ rawText: string;
27
+ /** 当前已解析的所有商品(只包含公开字段) */
28
+ allItems: ReceiptItem[];
29
+ }
30
+ /**
31
+ * 验证结果
32
+ */
33
+ interface VerificationResult {
34
+ /** 验证/补全后的商品名称 */
35
+ verifiedName: string;
36
+ }
37
+ /**
38
+ * 验证策略接口(B 的形状)
39
+ * 这是预留的完整策略接口,用于未来扩展
40
+ */
41
+ interface VerificationStrategy {
42
+ /**
43
+ * 验证商品名称
44
+ * @param name 原始商品名称
45
+ * @param context 验证上下文
46
+ * @returns 验证结果
47
+ */
48
+ verify(name: string, context: VerificationContext): Promise<VerificationResult>;
49
+ }
50
+ /**
51
+ * 验证回调函数类型(A 的形态,但符合 B 的接口)
52
+ * 这是当前使用的简化版本
53
+ */
54
+ type VerificationCallback = (name: string, context: VerificationContext) => Promise<VerificationResult | null>;
55
+ /**
56
+ * 图片输入类型
57
+ * 支持 Buffer、base64 字符串或图片 URL
58
+ */
59
+ type ImageInput = Buffer | string;
60
+ /**
61
+ * 提取选项
62
+ */
63
+ interface ExtractOptions {
64
+ /**
65
+ * 可选的验证回调函数
66
+ * 当库内部检测到不确定的商品名称时自动调用
67
+ */
68
+ verifyCallback?: VerificationCallback;
69
+ /**
70
+ * 自动使用 Google Search 验证不确定的商品名称
71
+ * 默认 false
72
+ */
73
+ autoVerify?: boolean;
74
+ }
75
+
76
+ /**
77
+ * 从小票图片中提取商品数据
78
+ *
79
+ * 这是一个无状态的异步函数,每次调用独立执行。
80
+ *
81
+ * @param image - 图片输入(Buffer、base64 字符串或 URL)
82
+ * @param options - 可选配置(包括验证回调)
83
+ * @returns 商品列表
84
+ *
85
+ * @throws 如果环境变量 GEMINI_API_KEY 未设置
86
+ * @throws 如果 API 调用失败
87
+ * @throws 如果响应解析失败
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * // 基础用法
92
+ * const items = await extractReceiptItems(imageBuffer);
93
+ *
94
+ * // 使用自动验证(Google Search)
95
+ * const items = await extractReceiptItems(imageBuffer, {
96
+ * autoVerify: true
97
+ * });
98
+ *
99
+ * // 带自定义验证回调
100
+ * const items = await extractReceiptItems(imageBuffer, {
101
+ * verifyCallback: async (name, context) => {
102
+ * const result = await myProductSearch(name);
103
+ * return result ? { verifiedName: result.name } : null;
104
+ * }
105
+ * });
106
+ * ```
107
+ */
108
+ declare function extractReceiptItems(image: ImageInput, options?: ExtractOptions): Promise<ReceiptItem[]>;
109
+
110
+ /**
111
+ * 使用 Google Search grounding 验证商品名称
112
+ */
113
+
114
+ /**
115
+ * 批量验证商品名称
116
+ * 使用 Google Search grounding 查找完整商品名
117
+ *
118
+ * @param items - 需要验证的商品列表
119
+ * @returns 验证结果映射 (原始名称 -> 验证后名称)
120
+ */
121
+ declare function batchVerifyItems(items: Partial<ReceiptItem>[]): Promise<Map<string, string>>;
122
+
123
+ export { type ExtractOptions, type ImageInput, type ReceiptItem, type VerificationCallback, type VerificationContext, type VerificationResult, type VerificationStrategy, batchVerifyItems, extractReceiptItems };
@@ -0,0 +1,123 @@
1
+ /**
2
+ * 对外公开的商品数据结构
3
+ * 这是 extractReceiptItems 函数返回的类型
4
+ */
5
+ interface ReceiptItem {
6
+ /** 商品名称 */
7
+ name: string;
8
+ /** 商品单价 */
9
+ price: number;
10
+ /** 商品数量,默认为 1 */
11
+ quantity: number;
12
+ /** 该商品是否产生税费 */
13
+ hasTax: boolean;
14
+ /** 该商品对应的具体税费金额(可选) */
15
+ taxAmount?: number;
16
+ /** 押金金额(可选,正数表示收押金,负数表示退押金) */
17
+ deposit?: number;
18
+ /** 折扣金额(可选,负数表示折扣) */
19
+ discount?: number;
20
+ }
21
+ /**
22
+ * 验证上下文,提供给验证回调/策略的额外信息
23
+ */
24
+ interface VerificationContext {
25
+ /** OCR 识别的原始文本 */
26
+ rawText: string;
27
+ /** 当前已解析的所有商品(只包含公开字段) */
28
+ allItems: ReceiptItem[];
29
+ }
30
+ /**
31
+ * 验证结果
32
+ */
33
+ interface VerificationResult {
34
+ /** 验证/补全后的商品名称 */
35
+ verifiedName: string;
36
+ }
37
+ /**
38
+ * 验证策略接口(B 的形状)
39
+ * 这是预留的完整策略接口,用于未来扩展
40
+ */
41
+ interface VerificationStrategy {
42
+ /**
43
+ * 验证商品名称
44
+ * @param name 原始商品名称
45
+ * @param context 验证上下文
46
+ * @returns 验证结果
47
+ */
48
+ verify(name: string, context: VerificationContext): Promise<VerificationResult>;
49
+ }
50
+ /**
51
+ * 验证回调函数类型(A 的形态,但符合 B 的接口)
52
+ * 这是当前使用的简化版本
53
+ */
54
+ type VerificationCallback = (name: string, context: VerificationContext) => Promise<VerificationResult | null>;
55
+ /**
56
+ * 图片输入类型
57
+ * 支持 Buffer、base64 字符串或图片 URL
58
+ */
59
+ type ImageInput = Buffer | string;
60
+ /**
61
+ * 提取选项
62
+ */
63
+ interface ExtractOptions {
64
+ /**
65
+ * 可选的验证回调函数
66
+ * 当库内部检测到不确定的商品名称时自动调用
67
+ */
68
+ verifyCallback?: VerificationCallback;
69
+ /**
70
+ * 自动使用 Google Search 验证不确定的商品名称
71
+ * 默认 false
72
+ */
73
+ autoVerify?: boolean;
74
+ }
75
+
76
+ /**
77
+ * 从小票图片中提取商品数据
78
+ *
79
+ * 这是一个无状态的异步函数,每次调用独立执行。
80
+ *
81
+ * @param image - 图片输入(Buffer、base64 字符串或 URL)
82
+ * @param options - 可选配置(包括验证回调)
83
+ * @returns 商品列表
84
+ *
85
+ * @throws 如果环境变量 GEMINI_API_KEY 未设置
86
+ * @throws 如果 API 调用失败
87
+ * @throws 如果响应解析失败
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * // 基础用法
92
+ * const items = await extractReceiptItems(imageBuffer);
93
+ *
94
+ * // 使用自动验证(Google Search)
95
+ * const items = await extractReceiptItems(imageBuffer, {
96
+ * autoVerify: true
97
+ * });
98
+ *
99
+ * // 带自定义验证回调
100
+ * const items = await extractReceiptItems(imageBuffer, {
101
+ * verifyCallback: async (name, context) => {
102
+ * const result = await myProductSearch(name);
103
+ * return result ? { verifiedName: result.name } : null;
104
+ * }
105
+ * });
106
+ * ```
107
+ */
108
+ declare function extractReceiptItems(image: ImageInput, options?: ExtractOptions): Promise<ReceiptItem[]>;
109
+
110
+ /**
111
+ * 使用 Google Search grounding 验证商品名称
112
+ */
113
+
114
+ /**
115
+ * 批量验证商品名称
116
+ * 使用 Google Search grounding 查找完整商品名
117
+ *
118
+ * @param items - 需要验证的商品列表
119
+ * @returns 验证结果映射 (原始名称 -> 验证后名称)
120
+ */
121
+ declare function batchVerifyItems(items: Partial<ReceiptItem>[]): Promise<Map<string, string>>;
122
+
123
+ export { type ExtractOptions, type ImageInput, type ReceiptItem, type VerificationCallback, type VerificationContext, type VerificationResult, type VerificationStrategy, batchVerifyItems, extractReceiptItems };