1 line
2.7 KiB
JSON
1 line
2.7 KiB
JSON
{"repo": "415geek/app-restaurantiq", "files": {"lib/funnel/llm/mimo-client.ts": {"1c7478e201e9bb717fddbf65f986a20c0458c499": {"t": 1785595155.5897706, "n": 2477, "h": "09dbfe4a634f2e2f", "c": "/**\n * Xiaomi MiMo — OpenAI-compatible chat completions for IQ funnel.\n * @see https://api.xiaomimimo.com/v1\n */\nimport OpenAI from 'openai';\n\nconst MIMO_BASE_URL = process.env.MIMO_API_BASE?.trim() || 'https://api.xiaomimimo.com/v1';\n\nexport function getMimoClient(): OpenAI | null {\n const apiKey = process.env.MIMO_API_KEY?.trim();\n if (!apiKey) return null;\n return new OpenAI({ apiKey, baseURL: MIMO_BASE_URL });\n}\n\nexport function parseJsonFromLlmText(text: string): Record<string, unknown> | null {\n const trimmed = text.trim();\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n } catch {\n /* fall through */\n }\n const start = trimmed.indexOf('{');\n const end = trimmed.lastIndexOf('}');\n if (start >= 0 && end > start) {\n try {\n const sliced = JSON.parse(trimmed.slice(start, end + 1)) as unknown;\n if (sliced && typeof sliced === 'object' && !Array.isArray(sliced)) {\n return sliced as Record<string, unknown>;\n }\n } catch {\n return null;\n }\n }\n return null;\n}\n\nexport async function runMimoJson(opts: {\n model: string;\n system: string;\n user: string;\n thinking?: boolean;\n maxTokens?: number;\n temperature?: number;\n}): Promise<{ raw: Record<string, unknown>; model: string } | null> {\n const client = getMimoClient();\n if (!client) return null;\n\n const body: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming = {\n model: opts.model,\n messages: [\n { role: 'system', content: opts.system },\n { role: 'user', content: opts.user },\n ],\n response_format: { type: 'json_object' },\n max_tokens: opts.maxTokens ?? 16_000,\n temperature: opts.temperature ?? 0.2,\n };\n if (opts.thinking !== undefined) {\n (body as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming & {\n extra_body?: { enable_thinking?: boolean };\n }).extra_body = { enable_thinking: opts.thinking };\n }\n\n try {\n const completion = await client.chat.completions.create(body);\n\n const text = completion.choices[0]?.message?.content;\n if (!text) return null;\n const raw = parseJsonFromLlmText(text);\n if (!raw) return null;\n return { raw, model: opts.model };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n console.warn('[mimo] chat completion failed:', msg.slice(0, 400));\n return null;\n }\n}\n"}}}} |