Files

1 line
194 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "andershi666/lobehub-hr-demo", "files": {"lobehub/docs/usage/providers/infiniai.mdx": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785595457.6197107, "n": 1442, "h": "7fb74bf027110266", "c": "---\ntitle: Using Infini-AI in LobeHub\ndescription: >-\n Learn how to configure and use Infini-AI's API Key in LobeHub to enable\n AI-powered conversations.\ntags:\n - LobeHub\n - Infini-AI\n - API Key\n - Large Model Deployment\n---\n\n# Using Infini-AI in LobeHub\n\n[Infini-AI](https://cloud.infini-ai.com/) is a large model service platform optimized for diverse chip architectures, offering a high-performance and unified AGI infrastructure solution.\n\nThis guide will walk you through the steps to quickly integrate Infini-AI's capabilities into LobeHub.\n\n<Callout type=\"info\">\n Infini-AI enforces a whitelist mechanism for image URLs. Currently, image links from services like Alibaba Cloud OSS and AWS S3 are supported.\\\n If you encounter a 400 error when using image-based conversations, try [uploading images using base64 encoding](/docs/self-hosting/environment-variables/s3#llm-vision-image-use-base-64).\n</Callout>\n\n<Steps>\n ### Step 1: Obtain an Infini-AI API Key\n\n - Log in to the [Large Model Service Platform](https://cloud.infini-ai.com/genstudio/model)\n - In the left-hand navigation menu, select \"API KEY Management\"\n - On the newly opened page, click the \"Create API KEY\" button, enter a name, and click \"Create\"\n\n ### Step 2: Configure the Model Service in LobeHub\n\n - Open LobeHub and go to the \"Settings\" page\n - In the \"Language Model\" section, select \"Infini-AI\"\n - Paste the API Key you obtained earlier\n</Steps>\n"}}, "lobehub/docs/usage/providers/infiniai.zh-CN.mdx": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785595458.9483073, "n": 751, "h": "de6bfeabb5bca530", "c": "---\ntitle: 在 LobeHub 中使用无问芯穹\ndescription: 学习如何在 LobeHub 中配置和使用无问芯穹的 API Key,实现 AI 对话交互。\ntags:\n - LobeHub\n - 无问芯穹\n - API密钥\n - 大模型部署\n---\n\n# 在 LobeHub 中使用无问芯穹\n\n[无问芯穹](https://cloud.infini-ai.com/)是基于多元芯片优化的大模型服务平台,提供高效统一的 AGI 基础设施解决方案。\n\n本文将指导你如何在 LobeHub 中快速接入无问芯穹的 AI 能力。\n\n<Callout type=\"info\">\n 无问芯穹的图片链接输入有白名单机制,目前已知支持阿里云 OSS / AWS S3\n 等服务的图片链接。如果您在使用图片对话时遇到 400 报错,请尝试[使用 base64\n 编码上传图片](/docs/self-hosting/environment-variables/s3#llm-vision-image-use-base-64)。\n</Callout>\n\n<Steps>\n ### 步骤一:获取无问芯穹 API Key\n\n - 登录[大模型服务平台](https://cloud.infini-ai.com/genstudio/model)\n - 在左侧导航栏选择「API KEY 管理」\n - 在新打开的页面中,点击「创建 API KEY」按钮,填入名称,点击「创建」\n\n ### 步骤二:配置 LobeHub 模型服务\n\n - 打开 LobeHub 进入「设置」界面\n - 在「语言模型」模块选择「Infini-AI」\n - 粘贴已获取的 API 密钥\n</Steps>\n"}}, "lobehub/packages/model-runtime/src/providers/infiniai/index.ts": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785595468.9546497, "n": 994, "h": "1ffb16a9931882b9", "c": "import { ModelProvider } from 'model-bank';\n\nimport { createOpenAICompatibleRuntime } from '../../core/openaiCompatibleFactory';\nimport { processMultiProviderModelList } from '../../utils/modelParse';\n\nexport interface InfiniAIModelCard {\n id: string;\n}\n\nexport const LobeInfiniAI = createOpenAICompatibleRuntime({\n baseURL: 'https://cloud.infini-ai.com/maas/v1',\n chatCompletion: {\n handlePayload: (payload) => {\n const { model, thinking, ...rest } = payload;\n\n return {\n ...rest,\n enable_thinking: thinking !== undefined ? thinking.type === 'enabled' : false,\n model,\n } as any;\n },\n },\n debug: {\n chatCompletion: () => process.env.DEBUG_INFINIAI_CHAT_COMPLETION === '1',\n },\n models: async ({ client }) => {\n const modelsPage = (await client.models.list()) as any;\n const modelList: InfiniAIModelCard[] = modelsPage.data;\n\n return processMultiProviderModelList(modelList, 'infiniai');\n },\n provider: ModelProvider.InfiniAI,\n});\n"}}, "lobehub/packages/model-bank/src/aiModels/infiniai.ts": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785595493.5362127, "n": 36207, "h": "e7f4f5863a0af971", "c": "import { type AIChatModelCard } from '../types/aiModel';\n\n// https://cloud.infini-ai.com/genstudio/model\n\nconst infiniaiChatModels: AIChatModelCard[] = [\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 204_800,\n description:\n 'MiniMax-M2.7 has reached or refreshed the latest SOTA benchmark in programming, tool calling and search, office productivity and many other scenarios, officially starting the journey of model recursive self-improvement.',\n displayName: 'MiniMax M2.7',\n enabled: true,\n id: 'minimax-m2.7',\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.1, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8.4, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n releasedAt: '2026-03-17',\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'DeepSeek-V3.2 is a model that balances high computational efficiency with excellent reasoning and agent performance.',\n displayName: 'DeepSeek V3.2',\n id: 'deepseek-v3.2',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 3, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n releasedAt: '2025-12-02',\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'DeepSeek-V3.2 Thinking is the thinking mode variant of DeepSeek-V3.2, focused on reasoning tasks.',\n displayName: 'DeepSeek V3.2 Thinking',\n enabled: true,\n id: 'deepseek-v3.2-thinking',\n maxOutput: 65_536,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 3, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n releasedAt: '2025-12-02',\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n vision: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'GLM-4.6V (106B) is a foundational model designed for cloud and high-performance cluster scenarios. GLM-4.6V extends the context window to 128k tokens and achieves SOTA visual understanding performance among models of the same parameter scale. The key is that GLM-4.6V integrates native Function Calling capabilities for the first time, effectively bridging the gap between visual perception and executable actions, providing a unified technical foundation for multimodal Agents in real business scenarios.',\n displayName: 'GLM-4.6V',\n id: 'glm-4.6v',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 6, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 198_000,\n description:\n 'A strong reasoning and agentic model from Z.ai with 744B total parameters (40B active), built for complex systems engineering and long-horizon tasks.',\n displayName: 'GLM-5',\n enabled: true,\n id: 'glm-5',\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 6, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 22, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n releasedAt: '2026-02-13',\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 204_800,\n description:\n 'MiniMax-M2.5 is a state-of-the-art large language model designed for real-world productivity and coding tasks.',\n displayName: 'MiniMax M2.5',\n id: 'minimax-m2.5',\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.1, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8.4, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n releasedAt: '2026-02-13',\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 262_144,\n description:\n \"Kimi K2 Thinking is the latest and most powerful open-source reasoning model. It significantly expands multi-step reasoning depth and maintains stable tool use across 200-300 consecutive tool calls, setting new records on Humanity's Last Exam (HLE), BrowseComp, and other benchmarks. It also excels in coding, math, logical reasoning, and agent scenarios. Built on a MoE architecture with about 1T total parameters, it supports a 256K context window and tool calling.\",\n displayName: 'Kimi K2 Thinking',\n id: 'kimi-k2-thinking',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 16, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n releasedAt: '2025-11-07',\n type: 'chat',\n },\n {\n abilities: {\n vision: true,\n },\n contextWindowTokens: 8192,\n description:\n 'DeepSeek-OCR is a vision-language model from DeepSeek AI focused on OCR and \"contextual optical compression.\" It explores compressing contextual information from images, efficiently processes documents, and converts them into structured text formats such as Markdown. It accurately recognizes text in images, making it ideal for document digitization, text extraction, and structured processing.',\n displayName: 'DeepSeek OCR',\n id: 'deepseek-ocr',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 0, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 0, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n releasedAt: '2025-10-20',\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 200_000,\n description:\n 'MiniMax-M2.1 is the latest version of the MiniMax series, optimized for multilingual programming and real-world complex tasks. As an AI-native model, MiniMax-M2.1 achieves significant improvements in model performance, agent framework support, and multi-scenario adaptation, aiming to help enterprises and individuals find AI-native work and lifestyle more quickly.',\n displayName: 'MiniMax M2.1',\n id: 'minimax-m2.1',\n maxOutput: 200_000,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.1, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8.4, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 200_000,\n description:\n 'MiniMax-M2 is a Mixture of Experts (MoE) language model optimized for coding and agent workflows, with approximately 230B total parameters and approximately 10B active parameters. While maintaining strong general intelligence, it is deeply enhanced for developer scenarios such as multi-file editing, code-run-fix loops, and test validation fixes, demonstrating stable and efficient performance in real environments like terminals, IDEs, and CI.',\n displayName: 'MiniMax M2',\n id: 'minimax-m2',\n maxOutput: 200_000,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.1, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8.4, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'GLM-4.7 is the latest large language model launched by Zhipu AI, with enhanced reasoning and generation capabilities.',\n displayName: 'GLM-4.7',\n id: 'glm-4.7',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 3, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 14, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'GLM-4.6 is the latest large language model launched by Zhipu AI, with enhanced reasoning and generation capabilities.',\n displayName: 'GLM-4.6',\n id: 'glm-4.6',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 3, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 14, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'DeepSeek-V3.2-Exp is an experimental DeepSeek LLM with stronger reasoning and generation.',\n displayName: 'DeepSeek V3.2 Exp',\n id: 'deepseek-v3.2-exp',\n maxOutput: 65_536,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 3, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n vision: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'Qwen3 VL 235B A22B Instruct is a multimodal model from Qwen, supporting vision understanding and reasoning.',\n displayName: 'Qwen3 VL 235B A22B Instruct',\n id: 'qwen3-vl-235b-a22b-instruct',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n vision: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'Qwen3 VL 235B A22B Thinking is a multimodal reasoning model from Qwen, supporting vision understanding and reasoning.',\n displayName: 'Qwen3 VL 235B A22B Thinking',\n id: 'qwen3-vl-235b-a22b-thinking',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 20, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'DeepSeek-V3.1-Terminus is a terminal-optimized LLM from DeepSeek, tailored for terminal devices.',\n displayName: 'DeepSeek V3.1 Terminus',\n id: 'deepseek-v3.1-terminus',\n maxOutput: 65_536,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 12, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'A next-generation thinking-mode open-source model based on Qwen3. Compared to the previous version (Qwen3-235B-A22B-Thinking-2507), it improves instruction following and provides more concise summaries.',\n displayName: 'Qwen3 Next 80B A3B Thinking',\n id: 'qwen3-next-80b-a3b-thinking',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 1, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 10, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'A next-generation non-thinking open-source model based on Qwen3. Compared to the previous version (Qwen3-235B-A22B-Instruct-2507), it has better Chinese text understanding, stronger logical reasoning, and improved text generation performance.',\n displayName: 'Qwen3 Next 80B A3B Instruct',\n id: 'qwen3-next-80b-a3b-instruct',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 1, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 10, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'DeepSeek V3.1 uses a hybrid reasoning architecture with both thinking and non-thinking modes.',\n displayName: 'DeepSeek V3.1',\n id: 'deepseek-v3.1',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 12, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n reasoning: true,\n },\n contextWindowTokens: 64_000,\n description: 'Baichuan M2 32B is a MoE model from Baichuan Intelligence with strong reasoning.',\n displayName: 'Baichuan M2 32B',\n id: 'baichuan-m2-32b',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 11.6, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n vision: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'GLM-4.5V is a multimodal model from Zhipu AI for vision understanding and reasoning.',\n displayName: 'GLM-4.5V',\n id: 'glm-4.5v',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 12, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'GLM-4.5 is a hybrid reasoning model from Zhipu AI built for agents, with thinking and non-thinking modes.',\n displayName: 'GLM-4.5',\n id: 'glm-4.5',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n contextWindowTokens: 131_072,\n description: 'GLM-4.5-Air is a lightweight LLM from Zhipu AI with efficient reasoning.',\n displayName: 'GLM-4.5-Air',\n id: 'glm-4.5-air',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 0.6, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n },\n contextWindowTokens: 262_144,\n description:\n 'The open-source Qwen code model. The latest qwen3-coder-480b-a35b-instruct is a Qwen3-based code generation model with strong coding-agent capabilities, good at tool use and environment interaction, enabling autonomous programming while retaining strong general abilities.',\n displayName: 'Qwen3 Coder 480B A35B',\n id: 'qwen3-coder-480b-a35b-instruct',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 9, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 36, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'A non-thinking open-source model based on Qwen3. Compared to the previous version (Qwen3-235B-A22B), it slightly improves subjective creative ability and model safety.',\n displayName: 'Qwen3 235B A22B Instruct 2507',\n id: 'qwen3-235b-a22b-instruct-2507',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n },\n contextWindowTokens: 131_072,\n description: 'Kimi K2 Instruct is a Moonshot AI LLM with ultra-long context handling.',\n displayName: 'Kimi K2 Instruct',\n id: 'kimi-k2-instruct',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 16, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n reasoning: true,\n },\n contextWindowTokens: 32_000,\n description:\n 'ERNIE 4.5 300B A47B is Baidu ERNIE’s ultra-large MoE model with excellent reasoning.',\n displayName: 'ERNIE 4.5 300B A47B',\n id: 'ernie-4.5-300b-a47b',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n contextWindowTokens: 120_000,\n description:\n 'ERNIE 4.5 21B A3B is Baidu ERNIE’s MoE model with strong reasoning and multilingual abilities.',\n displayName: 'ERNIE 4.5 21B A3B',\n id: 'ernie-4.5-21b-a3b',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 1, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 1, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'Qwen3-8B is the third-generation Qwen LLM with 8.2B parameters, designed for efficient reasoning and multilingual tasks. It supports seamless switching between thinking mode (complex reasoning) and non-thinking mode (general chat), excelling in math, coding, commonsense reasoning, and multilingual instruction following.',\n displayName: 'Qwen3 8B',\n id: 'qwen3-8b',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 1, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'Qwen3-14B is the third-generation Qwen LLM with 14.8B parameters, designed for efficient reasoning and multilingual tasks. It supports seamless switching between thinking mode (complex reasoning) and non-thinking mode (general chat), excelling in math, coding, commonsense reasoning, and multilingual instruction following.',\n displayName: 'Qwen3 14B',\n id: 'qwen3-14b',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'Qwen3-32B is the third-generation Qwen LLM with 32.8B parameters, designed for efficient reasoning and multilingual tasks. It supports seamless switching between thinking mode (complex reasoning) and non-thinking mode (general chat), excelling in math, coding, commonsense reasoning, and multilingual instruction following.',\n displayName: 'Qwen3 32B',\n id: 'qwen3-32b',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 11.6, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'Qwen3-30B-A3B is a third-generation Qwen LLM using a MoE architecture with 30.5B total parameters and 3.3B active per token. It supports seamless switching between thinking mode (complex reasoning) and non-thinking mode (general chat), excelling in math, coding, commonsense reasoning, and multilingual instruction following.',\n displayName: 'Qwen3 30B A3B',\n id: 'qwen3-30b-a3b',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8.7, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'Qwen3-235B-A22B is a third-generation Qwen LLM using a MoE architecture with 235B total parameters and 22B active per token. It supports seamless switching between thinking mode (complex reasoning) and non-thinking mode (general chat), excelling in math, coding, commonsense reasoning, and multilingual instruction following.',\n displayName: 'Qwen3 235B A22B',\n id: 'qwen3-235b-a22b',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 5, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 20, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n settings: {\n extendParams: ['enableReasoning'],\n },\n type: 'chat',\n },\n {\n abilities: {\n vision: true,\n },\n contextWindowTokens: 125_000,\n description:\n 'The Qwen2.5-VL series improves intelligence, practicality, and applicability, performing better in natural dialogue, content creation, professional knowledge services, and code development. The flagship Qwen2.5-VL-72B-Instruct is highly competitive across benchmarks spanning many domains and tasks, including college-level QA, math, document understanding, general QA, video understanding, and visual agent tasks.',\n displayName: 'Qwen2.5 VL 72B Instruct',\n id: 'qwen2.5-vl-72b-instruct',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 10, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 10, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n vision: true,\n },\n contextWindowTokens: 125_000,\n description:\n 'The Qwen2.5-VL series improves intelligence, practicality, and applicability, performing better in natural dialogue, content creation, professional knowledge services, and code development. Qwen2.5-VL-32B-Instruct is highly competitive across benchmarks spanning many domains and tasks, including college-level QA, math, document understanding, general QA, video understanding, and visual agent tasks.',\n displayName: 'Qwen2.5 VL 32B Instruct',\n id: 'qwen2.5-vl-32b-instruct',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 5.8, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 5.8, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n vision: true,\n },\n contextWindowTokens: 125_000,\n description:\n 'The Qwen2.5-VL series improves intelligence, practicality, and applicability, performing better in natural dialogue, content creation, professional knowledge services, and code development. Qwen2.5-VL-7B-Instruct is highly competitive across benchmarks spanning many domains and tasks, including college-level QA, math, document understanding, general QA, video understanding, and visual agent tasks.',\n displayName: 'Qwen2.5 VL 7B Instruct',\n id: 'qwen2.5-vl-7b-instruct',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n reasoning: true,\n },\n contextWindowTokens: 32_000,\n description: 'QwQ 32B is a Qwen reasoning-focused model built for reasoning tasks.',\n displayName: 'QwQ 32B',\n id: 'qwq-32b',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n contextWindowTokens: 131_072,\n description:\n 'DeepSeek-V3-0324 is a powerful MoE LLM with 671B total parameters and 37B active per token. It uses Multi-Head Latent Attention (MLA) and the DeepSeekMoE architecture for efficient reasoning and economical training, and significantly improves over the previous DeepSeek-V3.',\n displayName: 'DeepSeek V3 0324',\n id: 'deepseek-v3',\n maxOutput: 16_384,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description:\n 'DeepSeek-R1 is an LLM focused on reasoning, achieving performance comparable to OpenAI o1 on math, code, and reasoning tasks through an innovative training pipeline. It is trained with a combination of cold-start data and large-scale reinforcement learning.',\n displayName: 'DeepSeek R1',\n id: 'deepseek-r1',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 16, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n reasoning: true,\n },\n contextWindowTokens: 32_000,\n description: 'DeepSeek R1 Distill Qwen 32B is a DeepSeek distilled model based on Qwen.',\n displayName: 'DeepSeek R1 Distill Qwen 32B',\n id: 'deepseek-r1-distill-qwen-32b',\n maxOutput: 8192,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n contextWindowTokens: 32_000,\n description: 'Megrez 3B Instruct is a small, efficient model from Wuwen Xinqiong.',\n displayName: 'Megrez 3B Instruct',\n id: 'megrez-3b-instruct',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 0, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 0, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n },\n contextWindowTokens: 32_768,\n description:\n 'Qwen2.5 is the latest in the Qwen LLM series. It releases base and instruction-tuned models ranging from 0.5B to 72B parameters. Compared with Qwen2, Qwen2.5 brings:\\nSignificantly more knowledge, with major gains in coding and math.\\nStronger instruction following, long-text generation, structured data understanding (e.g., tables), and structured output especially JSON. More robust to diverse system prompts, improving roleplay and conditioning in chatbots.\\nLong-context support.\\nMultilingual support for 29+ languages, including Chinese, English, French, Spanish, Portuguese, German, Italian, Russian, Japanese, Korean, Vietnamese, Thai, Arabic, and more.',\n displayName: 'Qwen2.5 32B Instruct',\n id: 'qwen2.5-32b-instruct',\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n },\n contextWindowTokens: 32_768,\n description:\n 'Qwen2.5 is the latest in the Qwen LLM series. It releases base and instruction-tuned models ranging from 0.5B to 72B parameters. Compared with Qwen2, Qwen2.5 brings:\\nSignificantly more knowledge, with major gains in coding and math.\\nStronger instruction following, long-text generation, structured data understanding (e.g., tables), and structured output especially JSON. More robust to diverse system prompts, improving roleplay and conditioning in chatbots.\\nLong-context support.\\nMultilingual support for 29+ languages, including Chinese, English, French, Spanish, Portuguese, German, Italian, Russian, Japanese, Korean, Vietnamese, Thai, Arabic, and more.',\n displayName: 'Qwen2.5 72B Instruct',\n id: 'qwen2.5-72b-instruct',\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 5, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 5, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n contextWindowTokens: 32_768,\n description:\n 'Qwen2.5 is the latest in the Qwen LLM series. It releases base and instruction-tuned models ranging from 0.5B to 72B parameters. Compared with Qwen2, Qwen2.5 brings:\\nSignificantly more knowledge, with major gains in coding and math.\\nStronger instruction following, long-text generation, structured data understanding (e.g., tables), and structured output especially JSON. More robust to diverse system prompts, improving roleplay and conditioning in chatbots.\\nLong-context support.\\nMultilingual support for 29+ languages, including Chinese, English, French, Spanish, Portuguese, German, Italian, Russian, Japanese, Korean, Vietnamese, Thai, Arabic, and more.',\n displayName: 'Qwen2.5 14B Instruct',\n id: 'qwen2.5-14b-instruct',\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n },\n contextWindowTokens: 32_768,\n description:\n 'Qwen2.5 is the latest in the Qwen LLM series. It releases base and instruction-tuned models ranging from 0.5B to 72B parameters. Compared with Qwen2, Qwen2.5 brings:\\nSignificantly more knowledge, with major gains in coding and math.\\nStronger instruction following, long-text generation, structured data understanding (e.g., tables), and structured output especially JSON. More robust to diverse system prompts, improving roleplay and conditioning in chatbots.\\nLong-context support.\\nMultilingual support for 29+ languages, including Chinese, English, French, Spanish, Portuguese, German, Italian, Russian, Japanese, Korean, Vietnamese, Thai, Arabic, and more.',\n displayName: 'Qwen2.5 7B Instruct',\n id: 'qwen2.5-7b-instruct',\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 1, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 1, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n functionCall: true,\n },\n contextWindowTokens: 32_768,\n description:\n 'Qwen2.5-Coder is the latest code-focused Qwen LLM series. Compared to CodeQwen1.5, it brings:\\nSignificant improvements in code generation, code reasoning, and code repair.\\nSupport for real-world applications such as code agents, improving coding plus math and general abilities.\\nLong-context support.',\n displayName: 'Qwen2.5 Coder 32B Instruct',\n id: 'qwen2.5-coder-32b-instruct',\n maxOutput: 4096,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 2.9, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n contextWindowTokens: 131_072,\n description:\n 'Access requires an application. GPT-OSS-120B is an open-source large language model from OpenAI with strong text generation capability.',\n displayName: 'GPT-OSS-120B',\n id: 'gpt-oss-120b',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 0.8, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 3.2, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n contextWindowTokens: 131_072,\n description:\n 'Access requires an application. GPT-OSS-20B is an open-source mid-size language model from OpenAI with efficient text generation.',\n displayName: 'GPT-OSS-20B',\n id: 'gpt-oss-20b',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 0.4, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 1.6, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n abilities: {\n reasoning: true,\n },\n contextWindowTokens: 131_072,\n description: 'Enterprise dedicated service model with bundled concurrency.',\n displayName: 'DeepSeek R1 (Pro)',\n id: 'pro-deepseek-r1',\n maxOutput: 32_768,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 16, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n {\n contextWindowTokens: 131_072,\n description: 'Enterprise dedicated service model with bundled concurrency.',\n displayName: 'DeepSeek V3 (Pro)',\n id: 'pro-deepseek-v3',\n maxOutput: 16_384,\n pricing: {\n currency: 'CNY',\n units: [\n { name: 'textInput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },\n { name: 'textOutput', rate: 8, strategy: 'fixed', unit: 'millionTokens' },\n ],\n },\n type: 'chat',\n },\n];\n\nexport const allModels = [...infiniaiChatModels];\n\nexport default allModels;\n"}}, "lobehub/Dockerfile": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785595561.5761967, "n": 11429, "h": "069b94de0659e79a", "c": "## Set global build ENV\nARG NODEJS_VERSION=\"24\"\n\n## Base image for all building stages\nFROM node:${NODEJS_VERSION}-slim AS base\n\nARG USE_CN_MIRROR\n\nENV DEBIAN_FRONTEND=\"noninteractive\"\n\nRUN set -e && \\\n if [ \"${USE_CN_MIRROR:-false}\" = \"true\" ]; then \\\n sed -i \"s/deb.debian.org/mirrors.ustc.edu.cn/g\" \"/etc/apt/sources.list.d/debian.sources\"; \\\n fi && \\\n apt update && \\\n apt install ca-certificates proxychains-ng -qy && \\\n mkdir -p /distroless/bin /distroless/etc /distroless/etc/ssl/certs /distroless/lib && \\\n cp /usr/lib/$(arch)-linux-gnu/libproxychains.so.4 /distroless/lib/libproxychains.so.4 && \\\n cp /usr/lib/$(arch)-linux-gnu/libdl.so.2 /distroless/lib/libdl.so.2 && \\\n cp /usr/bin/proxychains4 /distroless/bin/proxychains && \\\n cp /etc/proxychains4.conf /distroless/etc/proxychains4.conf && \\\n cp /usr/lib/$(arch)-linux-gnu/libstdc++.so.6 /distroless/lib/libstdc++.so.6 && \\\n cp /usr/lib/$(arch)-linux-gnu/libgcc_s.so.1 /distroless/lib/libgcc_s.so.1 && \\\n cp /usr/lib/$(arch)-linux-gnu/librt.so.1 /distroless/lib/librt.so.1 && \\\n cp /usr/local/bin/node /distroless/bin/node && \\\n cp /etc/ssl/certs/ca-certificates.crt /distroless/etc/ssl/certs/ca-certificates.crt && \\\n rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*\n\n## Builder image, install all the dependencies and build the app\nFROM base AS builder\n\nARG USE_CN_MIRROR\nARG NEXT_PUBLIC_BASE_PATH\nARG NEXT_PUBLIC_SENTRY_DSN\nARG NEXT_PUBLIC_ANALYTICS_POSTHOG\nARG NEXT_PUBLIC_POSTHOG_HOST\nARG NEXT_PUBLIC_POSTHOG_KEY\nARG NEXT_PUBLIC_ANALYTICS_UMAMI\nARG NEXT_PUBLIC_UMAMI_SCRIPT_URL\nARG NEXT_PUBLIC_UMAMI_WEBSITE_ID\nARG FEATURE_FLAGS\n\nENV NEXT_PUBLIC_BASE_PATH=\"${NEXT_PUBLIC_BASE_PATH}\" \\\n FEATURE_FLAGS=\"${FEATURE_FLAGS}\"\n\nENV APP_URL=\"http://app.com\" \\\n DATABASE_DRIVER=\"node\" \\\n DATABASE_URL=\"postgres://postgres:password@localhost:5432/postgres\" \\\n KEY_VAULTS_SECRET=\"use-for-build\" \\\n AUTH_SECRET=\"use-for-build\"\n\n# Sentry\nENV NEXT_PUBLIC_SENTRY_DSN=\"${NEXT_PUBLIC_SENTRY_DSN}\" \\\n SENTRY_ORG=\"\" \\\n SENTRY_PROJECT=\"\"\n\n# Posthog\nENV NEXT_PUBLIC_ANALYTICS_POSTHOG=\"${NEXT_PUBLIC_ANALYTICS_POSTHOG}\" \\\n NEXT_PUBLIC_POSTHOG_HOST=\"${NEXT_PUBLIC_POSTHOG_HOST}\" \\\n NEXT_PUBLIC_POSTHOG_KEY=\"${NEXT_PUBLIC_POSTHOG_KEY}\"\n\n# Umami\nENV NEXT_PUBLIC_ANALYTICS_UMAMI=\"${NEXT_PUBLIC_ANALYTICS_UMAMI}\" \\\n NEXT_PUBLIC_UMAMI_SCRIPT_URL=\"${NEXT_PUBLIC_UMAMI_SCRIPT_URL}\" \\\n NEXT_PUBLIC_UMAMI_WEBSITE_ID=\"${NEXT_PUBLIC_UMAMI_WEBSITE_ID}\"\n\n# Node\nENV NODE_OPTIONS=\"--max-old-space-size=8192\"\n\nWORKDIR /app\n\nCOPY package.json pnpm-workspace.yaml ./\nCOPY .npmrc ./\nCOPY packages ./packages\nCOPY patches ./patches\n# bring in desktop workspace manifest so pnpm can resolve it\nCOPY apps/desktop/src/main/package.json ./apps/desktop/src/main/package.json\n\nRUN set -e && \\\n if [ \"${USE_CN_MIRROR:-false}\" = \"true\" ]; then \\\n export SENTRYCLI_CDNURL=\"https://npmmirror.com/mirrors/sentry-cli\"; \\\n npm config set registry \"https://registry.npmmirror.com/\"; \\\n echo 'canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas' >> .npmrc; \\\n fi && \\\n export COREPACK_NPM_REGISTRY=$(npm config get registry | sed 's/\\/$//') && \\\n npm i -g corepack@latest && \\\n corepack enable && \\\n corepack use $(sed -n 's/.*\"packageManager\": \"\\(.*\\)\".*/\\1/p' package.json) && \\\n pnpm i && \\\n mkdir -p /deps && \\\n cd /deps && \\\n pnpm init && \\\n pnpm add pg drizzle-orm\n\nCOPY . .\n\n# Prebuild: env checks (checkDeprecatedAuth, checkRequiredEnvVars, printEnvInfo) then remove desktop-only code\nRUN pnpm exec tsx scripts/dockerPrebuild.mts\nRUN rm -rf src/app/desktop \"src/app/(backend)/trpc/desktop\"\n\n# run build standalone for docker version\nRUN npm run build:docker\n\n## Application image, copy all the files for production\nFROM busybox:latest AS app\n\nCOPY --from=base /distroless/ /\n\n# Automatically leverage output traces to reduce image size\n# https://nextjs.org/docs/advanced-features/output-file-tracing\nCOPY --from=builder /app/.next/standalone /app/\nCOPY --from=builder /app/.next/static /app/.next/static\n# Copy SPA assets (Vite build output)\nCOPY --from=builder /app/public/_spa /app/public/_spa\n# Copy database migrations\nCOPY --from=builder /app/packages/database/migrations /app/migrations\nCOPY --from=builder /app/scripts/migrateServerDB/docker.cjs /app/docker.cjs\nCOPY --from=builder /app/scripts/migrateServerDB/errorHint.js /app/errorHint.js\n\n# copy dependencies\nCOPY --from=builder /deps/node_modules/.pnpm /app/node_modules/.pnpm\nCOPY --from=builder /deps/node_modules/pg /app/node_modules/pg\nCOPY --from=builder /deps/node_modules/drizzle-orm /app/node_modules/drizzle-orm\n\n# Copy server launcher and shared scripts\nCOPY --from=builder /app/scripts/serverLauncher/startServer.js /app/startServer.js\nCOPY --from=builder /app/scripts/_shared /app/scripts/_shared\n\nRUN set -e && \\\n addgroup -S -g 1001 nodejs && \\\n adduser -D -G nodejs -H -S -h /app -u 1001 nextjs && \\\n chown -R nextjs:nodejs /app /etc/proxychains4.conf\n\n## Production image, copy all the files and run next\nFROM scratch\n\n# Copy all the files from app, set the correct permission for prerender cache\nCOPY --from=app / /\n\nENV NODE_ENV=\"production\" \\\n NODE_OPTIONS=\"--dns-result-order=ipv4first --use-openssl-ca\" \\\n NODE_EXTRA_CA_CERTS=\"\" \\\n NODE_TLS_REJECT_UNAUTHORIZED=\"\" \\\n SSL_CERT_FILE=\"/etc/ssl/certs/ca-certificates.crt\"\n\n# Make the middleware rewrite through local as default\n# refs: https://github.com/lobehub/lobehub/issues/5876\nENV MIDDLEWARE_REWRITE_THROUGH_LOCAL=\"1\"\n\n# set hostname to localhost\nENV HOSTNAME=\"0.0.0.0\" \\\n PORT=\"3210\"\n\n# General Variables\nENV APP_URL=\"\" \\\n API_KEY_SELECT_MODE=\"\" \\\n DEFAULT_AGENT_CONFIG=\"\" \\\n SYSTEM_AGENT=\"\" \\\n FEATURE_FLAGS=\"\" \\\n PROXY_URL=\"\"\n\n# Database\nENV KEY_VAULTS_SECRET=\"\" \\\n DATABASE_DRIVER=\"node\" \\\n DATABASE_URL=\"\"\n\n# Better Auth\nENV AUTH_SECRET=\"\" \\\n AUTH_SSO_PROVIDERS=\"\" \\\n AUTH_ALLOWED_EMAILS=\"\" \\\n AUTH_TRUSTED_ORIGINS=\"\" \\\n AUTH_DISABLE_EMAIL_PASSWORD=\"\" \\\n AUTH_EMAIL_VERIFICATION=\"\" \\\n AUTH_ENABLE_MAGIC_LINK=\"\" \\\n # Google\n AUTH_GOOGLE_ID=\"\" \\\n AUTH_GOOGLE_SECRET=\"\" \\\n # GitHub\n AUTH_GITHUB_ID=\"\" \\\n AUTH_GITHUB_SECRET=\"\" \\\n # Microsoft\n AUTH_MICROSOFT_ID=\"\" \\\n AUTH_MICROSOFT_SECRET=\"\" \\\n AUTH_MICROSOFT_AUTHORITY_URL=\"\" \\\n AUTH_MICROSOFT_TENANT_ID=\"\"\n\n# Redis\nENV REDIS_URL=\"\" \\\n REDIS_PREFIX=\"\" \\\n REDIS_TLS=\"\"\n\n# Email\nENV EMAIL_SERVICE_PROVIDER=\"\" \\\n SMTP_HOST=\"\" \\\n SMTP_PORT=\"\" \\\n SMTP_SECURE=\"\" \\\n SMTP_USER=\"\" \\\n SMTP_PASS=\"\" \\\n SMTP_FROM=\"\" \\\n RESEND_API_KEY=\"\" \\\n RESEND_FROM=\"\"\n\n# S3\nENV NEXT_PUBLIC_S3_DOMAIN=\"\" \\\n S3_PUBLIC_DOMAIN=\"\" \\\n S3_ACCESS_KEY_ID=\"\" \\\n S3_BUCKET=\"\" \\\n S3_ENDPOINT=\"\" \\\n S3_SECRET_ACCESS_KEY=\"\" \\\n S3_ENABLE_PATH_STYLE=\"\" \\\n S3_SET_ACL=\"\"\n\n# Model Variables\nENV \\\n # AI21\n AI21_API_KEY=\"\" AI21_MODEL_LIST=\"\" \\\n # Ai360\n AI360_API_KEY=\"\" AI360_MODEL_LIST=\"\" \\\n # AiHubMix\n AIHUBMIX_API_KEY=\"\" AIHUBMIX_MODEL_LIST=\"\" \\\n # Anthropic\n ANTHROPIC_API_KEY=\"\" ANTHROPIC_MODEL_LIST=\"\" ANTHROPIC_PROXY_URL=\"\" \\\n # Amazon Bedrock\n ENABLED_AWS_BEDROCK=\"\" AWS_ACCESS_KEY_ID=\"\" AWS_SECRET_ACCESS_KEY=\"\" AWS_REGION=\"\" AWS_BEDROCK_MODEL_LIST=\"\" \\\n # Azure OpenAI\n AZURE_API_KEY=\"\" AZURE_API_VERSION=\"\" AZURE_ENDPOINT=\"\" AZURE_MODEL_LIST=\"\" \\\n # Baichuan\n BAICHUAN_API_KEY=\"\" BAICHUAN_MODEL_LIST=\"\" \\\n # Cloudflare\n CLOUDFLARE_API_KEY=\"\" CLOUDFLARE_BASE_URL_OR_ACCOUNT_ID=\"\" CLOUDFLARE_MODEL_LIST=\"\" \\\n # Cohere\n COHERE_API_KEY=\"\" COHERE_MODEL_LIST=\"\" COHERE_PROXY_URL=\"\" \\\n # ComfyUI\n ENABLED_COMFYUI=\"\" COMFYUI_BASE_URL=\"\" COMFYUI_AUTH_TYPE=\"\" \\\n COMFYUI_API_KEY=\"\" COMFYUI_USERNAME=\"\" COMFYUI_PASSWORD=\"\" COMFYUI_CUSTOM_HEADERS=\"\" \\\n # DeepSeek\n DEEPSEEK_API_KEY=\"\" DEEPSEEK_MODEL_LIST=\"\" \\\n # Fireworks AI\n FIREWORKSAI_API_KEY=\"\" FIREWORKSAI_MODEL_LIST=\"\" \\\n # Gitee AI\n GITEE_AI_API_KEY=\"\" GITEE_AI_MODEL_LIST=\"\" \\\n # GitHub\n GITHUB_TOKEN=\"\" GITHUB_MODEL_LIST=\"\" \\\n # Google\n GOOGLE_API_KEY=\"\" GOOGLE_MODEL_LIST=\"\" GOOGLE_PROXY_URL=\"\" \\\n # Vertex AI\n VERTEXAI_CREDENTIALS=\"\" VERTEXAI_PROJECT=\"\" VERTEXAI_LOCATION=\"\" VERTEXAI_MODEL_LIST=\"\" \\\n # Groq\n GROQ_API_KEY=\"\" GROQ_MODEL_LIST=\"\" GROQ_PROXY_URL=\"\" \\\n # Higress\n HIGRESS_API_KEY=\"\" HIGRESS_MODEL_LIST=\"\" HIGRESS_PROXY_URL=\"\" \\\n # HuggingFace\n HUGGINGFACE_API_KEY=\"\" HUGGINGFACE_MODEL_LIST=\"\" HUGGINGFACE_PROXY_URL=\"\" \\\n # Hunyuan\n HUNYUAN_API_KEY=\"\" HUNYUAN_MODEL_LIST=\"\" \\\n # InternLM\n INTERNLM_API_KEY=\"\" INTERNLM_MODEL_LIST=\"\" \\\n # Jina\n JINA_API_KEY=\"\" JINA_MODEL_LIST=\"\" JINA_PROXY_URL=\"\" \\\n # Minimax\n MINIMAX_API_KEY=\"\" MINIMAX_MODEL_LIST=\"\" \\\n # Mistral\n MISTRAL_API_KEY=\"\" MISTRAL_MODEL_LIST=\"\" \\\n # ModelScope\n MODELSCOPE_API_KEY=\"\" MODELSCOPE_MODEL_LIST=\"\" MODELSCOPE_PROXY_URL=\"\" \\\n # Moonshot\n MOONSHOT_API_KEY=\"\" MOONSHOT_MODEL_LIST=\"\" MOONSHOT_PROXY_URL=\"\" \\\n # Nebius\n NEBIUS_API_KEY=\"\" NEBIUS_MODEL_LIST=\"\" NEBIUS_PROXY_URL=\"\" \\\n # NewAPI\n NEWAPI_API_KEY=\"\" NEWAPI_PROXY_URL=\"\" \\\n # Novita\n NOVITA_API_KEY=\"\" NOVITA_MODEL_LIST=\"\" \\\n # Nvidia NIM\n NVIDIA_API_KEY=\"\" NVIDIA_MODEL_LIST=\"\" NVIDIA_PROXY_URL=\"\" \\\n # Ollama\n ENABLED_OLLAMA=\"\" OLLAMA_MODEL_LIST=\"\" OLLAMA_PROXY_URL=\"\" \\\n # OpenAI\n ENABLED_OPENAI=\"\" OPENAI_API_KEY=\"\" OPENAI_MODEL_LIST=\"\" OPENAI_PROXY_URL=\"\" \\\n # OpenRouter\n OPENROUTER_API_KEY=\"\" OPENROUTER_MODEL_LIST=\"\" \\\n # Perplexity\n PERPLEXITY_API_KEY=\"\" PERPLEXITY_MODEL_LIST=\"\" PERPLEXITY_PROXY_URL=\"\" \\\n # PPIO\n PPIO_API_KEY=\"\" PPIO_MODEL_LIST=\"\" \\\n # Qiniu\n QINIU_API_KEY=\"\" QINIU_MODEL_LIST=\"\" QINIU_PROXY_URL=\"\" \\\n # Qwen\n QWEN_API_KEY=\"\" QWEN_MODEL_LIST=\"\" QWEN_PROXY_URL=\"\" \\\n # SambaNova\n SAMBANOVA_API_KEY=\"\" SAMBANOVA_MODEL_LIST=\"\" \\\n # Search1API\n SEARCH1API_API_KEY=\"\" SEARCH1API_MODEL_LIST=\"\" \\\n # SenseNova\n SENSENOVA_API_KEY=\"\" SENSENOVA_MODEL_LIST=\"\" \\\n # SiliconCloud\n SILICONCLOUD_API_KEY=\"\" SILICONCLOUD_MODEL_LIST=\"\" SILICONCLOUD_PROXY_URL=\"\" \\\n # Spark\n SPARK_API_KEY=\"\" SPARK_MODEL_LIST=\"\" SPARK_PROXY_URL=\"\" SPARK_SEARCH_MODE=\"\" \\\n # Stepfun\n STEPFUN_API_KEY=\"\" STEPFUN_MODEL_LIST=\"\" \\\n # Taichu\n TAICHU_API_KEY=\"\" TAICHU_MODEL_LIST=\"\" \\\n # TogetherAI\n TOGETHERAI_API_KEY=\"\" TOGETHERAI_MODEL_LIST=\"\" \\\n # Upstage\n UPSTAGE_API_KEY=\"\" UPSTAGE_MODEL_LIST=\"\" \\\n # v0 (Vercel)\n V0_API_KEY=\"\" V0_MODEL_LIST=\"\" \\\n # vLLM\n VLLM_API_KEY=\"\" VLLM_MODEL_LIST=\"\" VLLM_PROXY_URL=\"\" \\\n # Wenxin\n WENXIN_API_KEY=\"\" WENXIN_MODEL_LIST=\"\" \\\n # xAI\n XAI_API_KEY=\"\" XAI_MODEL_LIST=\"\" XAI_PROXY_URL=\"\" \\\n # Xinference\n XINFERENCE_API_KEY=\"\" XINFERENCE_MODEL_LIST=\"\" XINFERENCE_PROXY_URL=\"\" \\\n # 01.AI\n ZEROONE_API_KEY=\"\" ZEROONE_MODEL_LIST=\"\" \\\n # Zhipu\n ZHIPU_API_KEY=\"\" ZHIPU_MODEL_LIST=\"\" \\\n # Tencent Cloud\n TENCENT_CLOUD_API_KEY=\"\" TENCENT_CLOUD_MODEL_LIST=\"\" \\\n # Infini-AI\n INFINIAI_API_KEY=\"\" INFINIAI_MODEL_LIST=\"\" \\\n # 302.AI\n AI302_API_KEY=\"\" AI302_MODEL_LIST=\"\" \\\n # FAL\n ENABLED_FAL=\"\" FAL_API_KEY=\"\" FAL_MODEL_LIST=\"\" \\\n # BFL\n BFL_API_KEY=\"\" BFL_MODEL_LIST=\"\" \\\n # Vercel AI Gateway\n VERCELAIGATEWAY_API_KEY=\"\" VERCELAIGATEWAY_MODEL_LIST=\"\" \\\n # Cerebras\n CEREBRAS_API_KEY=\"\" CEREBRAS_MODEL_LIST=\"\"\n\nUSER nextjs\n\nEXPOSE 3210/tcp\n\nENTRYPOINT [\"/bin/node\"]\n\nCMD [\"/app/startServer.js\"]\n"}, "59c48f96d2b6731a99062e8ed8800f1f3683ee19": {"t": 1785769734.7645574, "n": 11429, "h": "069b94de0659e79a", "c": "## Set global build ENV\nARG NODEJS_VERSION=\"24\"\n\n## Base image for all building stages\nFROM node:${NODEJS_VERSION}-slim AS base\n\nARG USE_CN_MIRROR\n\nENV DEBIAN_FRONTEND=\"noninteractive\"\n\nRUN set -e && \\\n if [ \"${USE_CN_MIRROR:-false}\" = \"true\" ]; then \\\n sed -i \"s/deb.debian.org/mirrors.ustc.edu.cn/g\" \"/etc/apt/sources.list.d/debian.sources\"; \\\n fi && \\\n apt update && \\\n apt install ca-certificates proxychains-ng -qy && \\\n mkdir -p /distroless/bin /distroless/etc /distroless/etc/ssl/certs /distroless/lib && \\\n cp /usr/lib/$(arch)-linux-gnu/libproxychains.so.4 /distroless/lib/libproxychains.so.4 && \\\n cp /usr/lib/$(arch)-linux-gnu/libdl.so.2 /distroless/lib/libdl.so.2 && \\\n cp /usr/bin/proxychains4 /distroless/bin/proxychains && \\\n cp /etc/proxychains4.conf /distroless/etc/proxychains4.conf && \\\n cp /usr/lib/$(arch)-linux-gnu/libstdc++.so.6 /distroless/lib/libstdc++.so.6 && \\\n cp /usr/lib/$(arch)-linux-gnu/libgcc_s.so.1 /distroless/lib/libgcc_s.so.1 && \\\n cp /usr/lib/$(arch)-linux-gnu/librt.so.1 /distroless/lib/librt.so.1 && \\\n cp /usr/local/bin/node /distroless/bin/node && \\\n cp /etc/ssl/certs/ca-certificates.crt /distroless/etc/ssl/certs/ca-certificates.crt && \\\n rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*\n\n## Builder image, install all the dependencies and build the app\nFROM base AS builder\n\nARG USE_CN_MIRROR\nARG NEXT_PUBLIC_BASE_PATH\nARG NEXT_PUBLIC_SENTRY_DSN\nARG NEXT_PUBLIC_ANALYTICS_POSTHOG\nARG NEXT_PUBLIC_POSTHOG_HOST\nARG NEXT_PUBLIC_POSTHOG_KEY\nARG NEXT_PUBLIC_ANALYTICS_UMAMI\nARG NEXT_PUBLIC_UMAMI_SCRIPT_URL\nARG NEXT_PUBLIC_UMAMI_WEBSITE_ID\nARG FEATURE_FLAGS\n\nENV NEXT_PUBLIC_BASE_PATH=\"${NEXT_PUBLIC_BASE_PATH}\" \\\n FEATURE_FLAGS=\"${FEATURE_FLAGS}\"\n\nENV APP_URL=\"http://app.com\" \\\n DATABASE_DRIVER=\"node\" \\\n DATABASE_URL=\"postgres://postgres:password@localhost:5432/postgres\" \\\n KEY_VAULTS_SECRET=\"use-for-build\" \\\n AUTH_SECRET=\"use-for-build\"\n\n# Sentry\nENV NEXT_PUBLIC_SENTRY_DSN=\"${NEXT_PUBLIC_SENTRY_DSN}\" \\\n SENTRY_ORG=\"\" \\\n SENTRY_PROJECT=\"\"\n\n# Posthog\nENV NEXT_PUBLIC_ANALYTICS_POSTHOG=\"${NEXT_PUBLIC_ANALYTICS_POSTHOG}\" \\\n NEXT_PUBLIC_POSTHOG_HOST=\"${NEXT_PUBLIC_POSTHOG_HOST}\" \\\n NEXT_PUBLIC_POSTHOG_KEY=\"${NEXT_PUBLIC_POSTHOG_KEY}\"\n\n# Umami\nENV NEXT_PUBLIC_ANALYTICS_UMAMI=\"${NEXT_PUBLIC_ANALYTICS_UMAMI}\" \\\n NEXT_PUBLIC_UMAMI_SCRIPT_URL=\"${NEXT_PUBLIC_UMAMI_SCRIPT_URL}\" \\\n NEXT_PUBLIC_UMAMI_WEBSITE_ID=\"${NEXT_PUBLIC_UMAMI_WEBSITE_ID}\"\n\n# Node\nENV NODE_OPTIONS=\"--max-old-space-size=8192\"\n\nWORKDIR /app\n\nCOPY package.json pnpm-workspace.yaml ./\nCOPY .npmrc ./\nCOPY packages ./packages\nCOPY patches ./patches\n# bring in desktop workspace manifest so pnpm can resolve it\nCOPY apps/desktop/src/main/package.json ./apps/desktop/src/main/package.json\n\nRUN set -e && \\\n if [ \"${USE_CN_MIRROR:-false}\" = \"true\" ]; then \\\n export SENTRYCLI_CDNURL=\"https://npmmirror.com/mirrors/sentry-cli\"; \\\n npm config set registry \"https://registry.npmmirror.com/\"; \\\n echo 'canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas' >> .npmrc; \\\n fi && \\\n export COREPACK_NPM_REGISTRY=$(npm config get registry | sed 's/\\/$//') && \\\n npm i -g corepack@latest && \\\n corepack enable && \\\n corepack use $(sed -n 's/.*\"packageManager\": \"\\(.*\\)\".*/\\1/p' package.json) && \\\n pnpm i && \\\n mkdir -p /deps && \\\n cd /deps && \\\n pnpm init && \\\n pnpm add pg drizzle-orm\n\nCOPY . .\n\n# Prebuild: env checks (checkDeprecatedAuth, checkRequiredEnvVars, printEnvInfo) then remove desktop-only code\nRUN pnpm exec tsx scripts/dockerPrebuild.mts\nRUN rm -rf src/app/desktop \"src/app/(backend)/trpc/desktop\"\n\n# run build standalone for docker version\nRUN npm run build:docker\n\n## Application image, copy all the files for production\nFROM busybox:latest AS app\n\nCOPY --from=base /distroless/ /\n\n# Automatically leverage output traces to reduce image size\n# https://nextjs.org/docs/advanced-features/output-file-tracing\nCOPY --from=builder /app/.next/standalone /app/\nCOPY --from=builder /app/.next/static /app/.next/static\n# Copy SPA assets (Vite build output)\nCOPY --from=builder /app/public/_spa /app/public/_spa\n# Copy database migrations\nCOPY --from=builder /app/packages/database/migrations /app/migrations\nCOPY --from=builder /app/scripts/migrateServerDB/docker.cjs /app/docker.cjs\nCOPY --from=builder /app/scripts/migrateServerDB/errorHint.js /app/errorHint.js\n\n# copy dependencies\nCOPY --from=builder /deps/node_modules/.pnpm /app/node_modules/.pnpm\nCOPY --from=builder /deps/node_modules/pg /app/node_modules/pg\nCOPY --from=builder /deps/node_modules/drizzle-orm /app/node_modules/drizzle-orm\n\n# Copy server launcher and shared scripts\nCOPY --from=builder /app/scripts/serverLauncher/startServer.js /app/startServer.js\nCOPY --from=builder /app/scripts/_shared /app/scripts/_shared\n\nRUN set -e && \\\n addgroup -S -g 1001 nodejs && \\\n adduser -D -G nodejs -H -S -h /app -u 1001 nextjs && \\\n chown -R nextjs:nodejs /app /etc/proxychains4.conf\n\n## Production image, copy all the files and run next\nFROM scratch\n\n# Copy all the files from app, set the correct permission for prerender cache\nCOPY --from=app / /\n\nENV NODE_ENV=\"production\" \\\n NODE_OPTIONS=\"--dns-result-order=ipv4first --use-openssl-ca\" \\\n NODE_EXTRA_CA_CERTS=\"\" \\\n NODE_TLS_REJECT_UNAUTHORIZED=\"\" \\\n SSL_CERT_FILE=\"/etc/ssl/certs/ca-certificates.crt\"\n\n# Make the middleware rewrite through local as default\n# refs: https://github.com/lobehub/lobehub/issues/5876\nENV MIDDLEWARE_REWRITE_THROUGH_LOCAL=\"1\"\n\n# set hostname to localhost\nENV HOSTNAME=\"0.0.0.0\" \\\n PORT=\"3210\"\n\n# General Variables\nENV APP_URL=\"\" \\\n API_KEY_SELECT_MODE=\"\" \\\n DEFAULT_AGENT_CONFIG=\"\" \\\n SYSTEM_AGENT=\"\" \\\n FEATURE_FLAGS=\"\" \\\n PROXY_URL=\"\"\n\n# Database\nENV KEY_VAULTS_SECRET=\"\" \\\n DATABASE_DRIVER=\"node\" \\\n DATABASE_URL=\"\"\n\n# Better Auth\nENV AUTH_SECRET=\"\" \\\n AUTH_SSO_PROVIDERS=\"\" \\\n AUTH_ALLOWED_EMAILS=\"\" \\\n AUTH_TRUSTED_ORIGINS=\"\" \\\n AUTH_DISABLE_EMAIL_PASSWORD=\"\" \\\n AUTH_EMAIL_VERIFICATION=\"\" \\\n AUTH_ENABLE_MAGIC_LINK=\"\" \\\n # Google\n AUTH_GOOGLE_ID=\"\" \\\n AUTH_GOOGLE_SECRET=\"\" \\\n # GitHub\n AUTH_GITHUB_ID=\"\" \\\n AUTH_GITHUB_SECRET=\"\" \\\n # Microsoft\n AUTH_MICROSOFT_ID=\"\" \\\n AUTH_MICROSOFT_SECRET=\"\" \\\n AUTH_MICROSOFT_AUTHORITY_URL=\"\" \\\n AUTH_MICROSOFT_TENANT_ID=\"\"\n\n# Redis\nENV REDIS_URL=\"\" \\\n REDIS_PREFIX=\"\" \\\n REDIS_TLS=\"\"\n\n# Email\nENV EMAIL_SERVICE_PROVIDER=\"\" \\\n SMTP_HOST=\"\" \\\n SMTP_PORT=\"\" \\\n SMTP_SECURE=\"\" \\\n SMTP_USER=\"\" \\\n SMTP_PASS=\"\" \\\n SMTP_FROM=\"\" \\\n RESEND_API_KEY=\"\" \\\n RESEND_FROM=\"\"\n\n# S3\nENV NEXT_PUBLIC_S3_DOMAIN=\"\" \\\n S3_PUBLIC_DOMAIN=\"\" \\\n S3_ACCESS_KEY_ID=\"\" \\\n S3_BUCKET=\"\" \\\n S3_ENDPOINT=\"\" \\\n S3_SECRET_ACCESS_KEY=\"\" \\\n S3_ENABLE_PATH_STYLE=\"\" \\\n S3_SET_ACL=\"\"\n\n# Model Variables\nENV \\\n # AI21\n AI21_API_KEY=\"\" AI21_MODEL_LIST=\"\" \\\n # Ai360\n AI360_API_KEY=\"\" AI360_MODEL_LIST=\"\" \\\n # AiHubMix\n AIHUBMIX_API_KEY=\"\" AIHUBMIX_MODEL_LIST=\"\" \\\n # Anthropic\n ANTHROPIC_API_KEY=\"\" ANTHROPIC_MODEL_LIST=\"\" ANTHROPIC_PROXY_URL=\"\" \\\n # Amazon Bedrock\n ENABLED_AWS_BEDROCK=\"\" AWS_ACCESS_KEY_ID=\"\" AWS_SECRET_ACCESS_KEY=\"\" AWS_REGION=\"\" AWS_BEDROCK_MODEL_LIST=\"\" \\\n # Azure OpenAI\n AZURE_API_KEY=\"\" AZURE_API_VERSION=\"\" AZURE_ENDPOINT=\"\" AZURE_MODEL_LIST=\"\" \\\n # Baichuan\n BAICHUAN_API_KEY=\"\" BAICHUAN_MODEL_LIST=\"\" \\\n # Cloudflare\n CLOUDFLARE_API_KEY=\"\" CLOUDFLARE_BASE_URL_OR_ACCOUNT_ID=\"\" CLOUDFLARE_MODEL_LIST=\"\" \\\n # Cohere\n COHERE_API_KEY=\"\" COHERE_MODEL_LIST=\"\" COHERE_PROXY_URL=\"\" \\\n # ComfyUI\n ENABLED_COMFYUI=\"\" COMFYUI_BASE_URL=\"\" COMFYUI_AUTH_TYPE=\"\" \\\n COMFYUI_API_KEY=\"\" COMFYUI_USERNAME=\"\" COMFYUI_PASSWORD=\"\" COMFYUI_CUSTOM_HEADERS=\"\" \\\n # DeepSeek\n DEEPSEEK_API_KEY=\"\" DEEPSEEK_MODEL_LIST=\"\" \\\n # Fireworks AI\n FIREWORKSAI_API_KEY=\"\" FIREWORKSAI_MODEL_LIST=\"\" \\\n # Gitee AI\n GITEE_AI_API_KEY=\"\" GITEE_AI_MODEL_LIST=\"\" \\\n # GitHub\n GITHUB_TOKEN=\"\" GITHUB_MODEL_LIST=\"\" \\\n # Google\n GOOGLE_API_KEY=\"\" GOOGLE_MODEL_LIST=\"\" GOOGLE_PROXY_URL=\"\" \\\n # Vertex AI\n VERTEXAI_CREDENTIALS=\"\" VERTEXAI_PROJECT=\"\" VERTEXAI_LOCATION=\"\" VERTEXAI_MODEL_LIST=\"\" \\\n # Groq\n GROQ_API_KEY=\"\" GROQ_MODEL_LIST=\"\" GROQ_PROXY_URL=\"\" \\\n # Higress\n HIGRESS_API_KEY=\"\" HIGRESS_MODEL_LIST=\"\" HIGRESS_PROXY_URL=\"\" \\\n # HuggingFace\n HUGGINGFACE_API_KEY=\"\" HUGGINGFACE_MODEL_LIST=\"\" HUGGINGFACE_PROXY_URL=\"\" \\\n # Hunyuan\n HUNYUAN_API_KEY=\"\" HUNYUAN_MODEL_LIST=\"\" \\\n # InternLM\n INTERNLM_API_KEY=\"\" INTERNLM_MODEL_LIST=\"\" \\\n # Jina\n JINA_API_KEY=\"\" JINA_MODEL_LIST=\"\" JINA_PROXY_URL=\"\" \\\n # Minimax\n MINIMAX_API_KEY=\"\" MINIMAX_MODEL_LIST=\"\" \\\n # Mistral\n MISTRAL_API_KEY=\"\" MISTRAL_MODEL_LIST=\"\" \\\n # ModelScope\n MODELSCOPE_API_KEY=\"\" MODELSCOPE_MODEL_LIST=\"\" MODELSCOPE_PROXY_URL=\"\" \\\n # Moonshot\n MOONSHOT_API_KEY=\"\" MOONSHOT_MODEL_LIST=\"\" MOONSHOT_PROXY_URL=\"\" \\\n # Nebius\n NEBIUS_API_KEY=\"\" NEBIUS_MODEL_LIST=\"\" NEBIUS_PROXY_URL=\"\" \\\n # NewAPI\n NEWAPI_API_KEY=\"\" NEWAPI_PROXY_URL=\"\" \\\n # Novita\n NOVITA_API_KEY=\"\" NOVITA_MODEL_LIST=\"\" \\\n # Nvidia NIM\n NVIDIA_API_KEY=\"\" NVIDIA_MODEL_LIST=\"\" NVIDIA_PROXY_URL=\"\" \\\n # Ollama\n ENABLED_OLLAMA=\"\" OLLAMA_MODEL_LIST=\"\" OLLAMA_PROXY_URL=\"\" \\\n # OpenAI\n ENABLED_OPENAI=\"\" OPENAI_API_KEY=\"\" OPENAI_MODEL_LIST=\"\" OPENAI_PROXY_URL=\"\" \\\n # OpenRouter\n OPENROUTER_API_KEY=\"\" OPENROUTER_MODEL_LIST=\"\" \\\n # Perplexity\n PERPLEXITY_API_KEY=\"\" PERPLEXITY_MODEL_LIST=\"\" PERPLEXITY_PROXY_URL=\"\" \\\n # PPIO\n PPIO_API_KEY=\"\" PPIO_MODEL_LIST=\"\" \\\n # Qiniu\n QINIU_API_KEY=\"\" QINIU_MODEL_LIST=\"\" QINIU_PROXY_URL=\"\" \\\n # Qwen\n QWEN_API_KEY=\"\" QWEN_MODEL_LIST=\"\" QWEN_PROXY_URL=\"\" \\\n # SambaNova\n SAMBANOVA_API_KEY=\"\" SAMBANOVA_MODEL_LIST=\"\" \\\n # Search1API\n SEARCH1API_API_KEY=\"\" SEARCH1API_MODEL_LIST=\"\" \\\n # SenseNova\n SENSENOVA_API_KEY=\"\" SENSENOVA_MODEL_LIST=\"\" \\\n # SiliconCloud\n SILICONCLOUD_API_KEY=\"\" SILICONCLOUD_MODEL_LIST=\"\" SILICONCLOUD_PROXY_URL=\"\" \\\n # Spark\n SPARK_API_KEY=\"\" SPARK_MODEL_LIST=\"\" SPARK_PROXY_URL=\"\" SPARK_SEARCH_MODE=\"\" \\\n # Stepfun\n STEPFUN_API_KEY=\"\" STEPFUN_MODEL_LIST=\"\" \\\n # Taichu\n TAICHU_API_KEY=\"\" TAICHU_MODEL_LIST=\"\" \\\n # TogetherAI\n TOGETHERAI_API_KEY=\"\" TOGETHERAI_MODEL_LIST=\"\" \\\n # Upstage\n UPSTAGE_API_KEY=\"\" UPSTAGE_MODEL_LIST=\"\" \\\n # v0 (Vercel)\n V0_API_KEY=\"\" V0_MODEL_LIST=\"\" \\\n # vLLM\n VLLM_API_KEY=\"\" VLLM_MODEL_LIST=\"\" VLLM_PROXY_URL=\"\" \\\n # Wenxin\n WENXIN_API_KEY=\"\" WENXIN_MODEL_LIST=\"\" \\\n # xAI\n XAI_API_KEY=\"\" XAI_MODEL_LIST=\"\" XAI_PROXY_URL=\"\" \\\n # Xinference\n XINFERENCE_API_KEY=\"\" XINFERENCE_MODEL_LIST=\"\" XINFERENCE_PROXY_URL=\"\" \\\n # 01.AI\n ZEROONE_API_KEY=\"\" ZEROONE_MODEL_LIST=\"\" \\\n # Zhipu\n ZHIPU_API_KEY=\"\" ZHIPU_MODEL_LIST=\"\" \\\n # Tencent Cloud\n TENCENT_CLOUD_API_KEY=\"\" TENCENT_CLOUD_MODEL_LIST=\"\" \\\n # Infini-AI\n INFINIAI_API_KEY=\"\" INFINIAI_MODEL_LIST=\"\" \\\n # 302.AI\n AI302_API_KEY=\"\" AI302_MODEL_LIST=\"\" \\\n # FAL\n ENABLED_FAL=\"\" FAL_API_KEY=\"\" FAL_MODEL_LIST=\"\" \\\n # BFL\n BFL_API_KEY=\"\" BFL_MODEL_LIST=\"\" \\\n # Vercel AI Gateway\n VERCELAIGATEWAY_API_KEY=\"\" VERCELAIGATEWAY_MODEL_LIST=\"\" \\\n # Cerebras\n CEREBRAS_API_KEY=\"\" CEREBRAS_MODEL_LIST=\"\"\n\nUSER nextjs\n\nEXPOSE 3210/tcp\n\nENTRYPOINT [\"/bin/node\"]\n\nCMD [\"/app/startServer.js\"]\n"}}, "lobehub/src/envs/llm.ts": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785595567.9679468, "n": 15156, "h": "533cfe99aef766e3", "c": "import { createEnv } from '@t3-oss/env-core';\nimport { z } from 'zod';\n\nexport const getLLMConfig = () => {\n return createEnv({\n server: {\n API_KEY_SELECT_MODE: z.string().optional(),\n\n ENABLED_OPENAI: z.boolean(),\n OPENAI_API_KEY: z.string().optional(),\n\n ENABLED_AZURE_OPENAI: z.boolean(),\n AZURE_API_KEY: z.string().optional(),\n AZURE_API_VERSION: z.string().optional(),\n AZURE_ENDPOINT: z.string().optional(),\n\n ENABLED_AZUREAI: z.boolean(),\n AZUREAI_ENDPOINT: z.string().optional(),\n AZUREAI_ENDPOINT_KEY: z.string().optional(),\n\n ENABLED_ZHIPU: z.boolean(),\n ZHIPU_API_KEY: z.string().optional(),\n\n ENABLED_DEEPSEEK: z.boolean(),\n DEEPSEEK_API_KEY: z.string().optional(),\n\n ENABLED_GOOGLE: z.boolean(),\n GOOGLE_API_KEY: z.string().optional(),\n\n ENABLED_VERTEXAI: z.boolean(),\n\n ENABLED_MOONSHOT: z.boolean(),\n MOONSHOT_API_KEY: z.string().optional(),\n\n ENABLED_PERPLEXITY: z.boolean(),\n PERPLEXITY_API_KEY: z.string().optional(),\n\n ENABLED_ANTHROPIC: z.boolean(),\n ANTHROPIC_API_KEY: z.string().optional(),\n\n ENABLED_MINIMAX: z.boolean(),\n MINIMAX_API_KEY: z.string().optional(),\n\n ENABLED_MISTRAL: z.boolean(),\n MISTRAL_API_KEY: z.string().optional(),\n\n ENABLED_GROQ: z.boolean(),\n GROQ_API_KEY: z.string().optional(),\n\n ENABLED_GITHUB: z.boolean(),\n GITHUB_TOKEN: z.string().optional(),\n\n ENABLED_OPENROUTER: z.boolean(),\n OPENROUTER_API_KEY: z.string().optional(),\n\n ENABLED_ZEROONE: z.boolean(),\n ZEROONE_API_KEY: z.string().optional(),\n\n ENABLED_TOGETHERAI: z.boolean(),\n TOGETHERAI_API_KEY: z.string().optional(),\n\n ENABLED_FIREWORKSAI: z.boolean(),\n FIREWORKSAI_API_KEY: z.string().optional(),\n\n ENABLED_AWS_BEDROCK: z.boolean(),\n AWS_REGION: z.string().optional(),\n AWS_ACCESS_KEY_ID: z.string().optional(),\n AWS_SECRET_ACCESS_KEY: z.string().optional(),\n AWS_SESSION_TOKEN: z.string().optional(),\n\n ENABLED_WENXIN: z.boolean(),\n WENXIN_API_KEY: z.string().optional(),\n\n ENABLED_OLLAMA: z.boolean(),\n ENABLED_OLLAMA_CLOUD: z.boolean(),\n OLLAMA_CLOUD_API_KEY: z.string().optional(),\n\n ENABLED_VLLM: z.boolean(),\n VLLM_API_KEY: z.string().optional(),\n\n ENABLED_XINFERENCE: z.boolean(),\n XINFERENCE_API_KEY: z.string().optional(),\n\n ENABLED_LMSTUDIO: z.boolean(),\n LMSTUDIO_API_KEY: z.string().optional(),\n\n ENABLED_QINIU: z.boolean(),\n QINIU_API_KEY: z.string().optional(),\n\n ENABLED_QWEN: z.boolean(),\n QWEN_API_KEY: z.string().optional(),\n\n ENABLED_STEPFUN: z.boolean(),\n STEPFUN_API_KEY: z.string().optional(),\n\n ENABLED_NEBIUS: z.boolean(),\n NEBIUS_API_KEY: z.string().optional(),\n\n ENABLED_NOVITA: z.boolean(),\n NOVITA_API_KEY: z.string().optional(),\n\n ENABLED_NVIDIA: z.boolean(),\n NVIDIA_API_KEY: z.string().optional(),\n\n ENABLED_BAICHUAN: z.boolean(),\n BAICHUAN_API_KEY: z.string().optional(),\n\n ENABLED_TAICHU: z.boolean(),\n TAICHU_API_KEY: z.string().optional(),\n\n ENABLED_CLOUDFLARE: z.boolean(),\n CLOUDFLARE_API_KEY: z.string().optional(),\n CLOUDFLARE_BASE_URL_OR_ACCOUNT_ID: z.string().optional(),\n\n ENABLED_AI360: z.boolean(),\n AI360_API_KEY: z.string().optional(),\n\n ENABLED_SILICONCLOUD: z.boolean(),\n SILICONCLOUD_API_KEY: z.string().optional(),\n\n ENABLED_GITEE_AI: z.boolean(),\n GITEE_AI_API_KEY: z.string().optional(),\n\n ENABLED_UPSTAGE: z.boolean(),\n UPSTAGE_API_KEY: z.string().optional(),\n\n ENABLED_SPARK: z.boolean(),\n SPARK_API_KEY: z.string().optional(),\n\n ENABLED_AI21: z.boolean(),\n AI21_API_KEY: z.string().optional(),\n\n ENABLED_HUNYUAN: z.boolean(),\n HUNYUAN_API_KEY: z.string().optional(),\n\n ENABLED_HUGGINGFACE: z.boolean(),\n HUGGINGFACE_API_KEY: z.string().optional(),\n\n ENABLED_SENSENOVA: z.boolean(),\n SENSENOVA_API_KEY: z.string().optional(),\n\n ENABLED_XAI: z.boolean(),\n XAI_API_KEY: z.string().optional(),\n\n ENABLED_INTERNLM: z.boolean(),\n INTERNLM_API_KEY: z.string().optional(),\n\n ENABLED_HIGRESS: z.boolean(),\n HIGRESS_API_KEY: z.string().optional(),\n\n ENABLED_VOLCENGINE: z.boolean(),\n VOLCENGINE_API_KEY: z.string().optional(),\n\n ENABLED_TENCENT_CLOUD: z.boolean(),\n TENCENT_CLOUD_API_KEY: z.string().optional(),\n\n ENABLED_JINA: z.boolean(),\n JINA_API_KEY: z.string().optional(),\n\n ENABLED_SAMBANOVA: z.boolean(),\n SAMBANOVA_API_KEY: z.string().optional(),\n\n ENABLED_PPIO: z.boolean(),\n PPIO_API_KEY: z.string().optional(),\n\n ENABLED_SEARCH1API: z.boolean(),\n SEARCH1API_API_KEY: z.string().optional(),\n\n ENABLED_COHERE: z.boolean(),\n COHERE_API_KEY: z.string().optional(),\n\n ENABLED_INFINIAI: z.boolean(),\n INFINIAI_API_KEY: z.string().optional(),\n\n ENABLED_FAL: z.boolean(),\n FAL_API_KEY: z.string().optional(),\n\n ENABLED_BFL: z.boolean(),\n BFL_API_KEY: z.string().optional(),\n\n ENABLED_COMFYUI: z.boolean(),\n COMFYUI_BASE_URL: z.string().optional(),\n COMFYUI_AUTH_TYPE: z.string().optional(),\n COMFYUI_API_KEY: z.string().optional(),\n COMFYUI_USERNAME: z.string().optional(),\n COMFYUI_PASSWORD: z.string().optional(),\n COMFYUI_CUSTOM_HEADERS: z.string().optional(),\n\n ENABLED_MODELSCOPE: z.boolean(),\n MODELSCOPE_API_KEY: z.string().optional(),\n\n ENABLED_V0: z.boolean(),\n V0_API_KEY: z.string().optional(),\n\n ENABLED_VERCELAIGATEWAY: z.boolean(),\n VERCELAIGATEWAY_API_KEY: z.string().optional(),\n\n ENABLED_AI302: z.boolean(),\n AI302_API_KEY: z.string().optional(),\n\n ENABLED_AKASHCHAT: z.boolean(),\n AKASHCHAT_API_KEY: z.string().optional(),\n\n ENABLED_COMETAPI: z.boolean(),\n COMETAPI_KEY: z.string().optional(),\n\n ENABLED_AIHUBMIX: z.boolean(),\n AIHUBMIX_API_KEY: z.string().optional(),\n\n ENABLED_NEWAPI: z.boolean(),\n NEWAPI_API_KEY: z.string().optional(),\n NEWAPI_PROXY_URL: z.string().optional(),\n\n ENABLED_CEREBRAS: z.boolean(),\n CEREBRAS_API_KEY: z.string().optional(),\n\n ENABLED_ZENMUX: z.boolean(),\n ZENMUX_API_KEY: z.string().optional(),\n\n ENABLED_STRAICO: z.boolean(),\n STRAICO_API_KEY: z.string().optional(),\n\n ENABLED_LOBEHUB: z.boolean(),\n\n ENABLED_XIAOMIMIMO: z.boolean(),\n XIAOMIMIMO_API_KEY: z.string().optional(),\n\n ENABLED_LONGCAT: z.boolean(),\n LONGCAT_API_KEY: z.string().optional(),\n },\n runtimeEnv: {\n API_KEY_SELECT_MODE: process.env.API_KEY_SELECT_MODE,\n\n ENABLED_OPENAI: process.env.ENABLED_OPENAI !== '0',\n OPENAI_API_KEY: process.env.OPENAI_API_KEY,\n\n ENABLED_AZURE_OPENAI: !!process.env.AZURE_API_KEY,\n AZURE_API_KEY: process.env.AZURE_API_KEY,\n AZURE_API_VERSION: process.env.AZURE_API_VERSION,\n AZURE_ENDPOINT: process.env.AZURE_ENDPOINT,\n\n ENABLED_AZUREAI: !!process.env.AZUREAI_ENDPOINT_KEY,\n AZUREAI_ENDPOINT_KEY: process.env.AZUREAI_ENDPOINT_KEY,\n AZUREAI_ENDPOINT: process.env.AZUREAI_ENDPOINT,\n\n ENABLED_ZHIPU: !!process.env.ZHIPU_API_KEY,\n ZHIPU_API_KEY: process.env.ZHIPU_API_KEY,\n\n ENABLED_DEEPSEEK: !!process.env.DEEPSEEK_API_KEY,\n DEEPSEEK_API_KEY: process.env.DEEPSEEK_API_KEY,\n\n ENABLED_GOOGLE: process.env.ENABLED_GOOGLE !== '0',\n GOOGLE_API_KEY: process.env.GOOGLE_API_KEY,\n\n ENABLED_VERTEXAI: !!process.env.VERTEXAI_CREDENTIALS,\n\n ENABLED_VOLCENGINE: !!process.env.VOLCENGINE_API_KEY,\n VOLCENGINE_API_KEY: process.env.VOLCENGINE_API_KEY,\n\n ENABLED_PERPLEXITY: !!process.env.PERPLEXITY_API_KEY,\n PERPLEXITY_API_KEY: process.env.PERPLEXITY_API_KEY,\n\n ENABLED_ANTHROPIC: process.env.ENABLED_ANTHROPIC !== '0',\n ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,\n\n ENABLED_MINIMAX: !!process.env.MINIMAX_API_KEY,\n MINIMAX_API_KEY: process.env.MINIMAX_API_KEY,\n\n ENABLED_MISTRAL: !!process.env.MISTRAL_API_KEY,\n MISTRAL_API_KEY: process.env.MISTRAL_API_KEY,\n\n ENABLED_OPENROUTER: !!process.env.OPENROUTER_API_KEY,\n OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY,\n\n ENABLED_TOGETHERAI: !!process.env.TOGETHERAI_API_KEY,\n TOGETHERAI_API_KEY: process.env.TOGETHERAI_API_KEY,\n\n ENABLED_FIREWORKSAI: !!process.env.FIREWORKSAI_API_KEY,\n FIREWORKSAI_API_KEY: process.env.FIREWORKSAI_API_KEY,\n\n ENABLED_MOONSHOT: !!process.env.MOONSHOT_API_KEY,\n MOONSHOT_API_KEY: process.env.MOONSHOT_API_KEY,\n\n ENABLED_GROQ: !!process.env.GROQ_API_KEY,\n GROQ_API_KEY: process.env.GROQ_API_KEY,\n\n ENABLED_GITHUB: !!process.env.GITHUB_TOKEN,\n GITHUB_TOKEN: process.env.GITHUB_TOKEN,\n\n ENABLED_ZEROONE: !!process.env.ZEROONE_API_KEY,\n ZEROONE_API_KEY: process.env.ZEROONE_API_KEY,\n\n ENABLED_AWS_BEDROCK: process.env.ENABLED_AWS_BEDROCK === '1',\n AWS_REGION: process.env.AWS_REGION,\n AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID,\n AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY,\n AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN,\n\n ENABLED_WENXIN: !!process.env.WENXIN_API_KEY,\n WENXIN_API_KEY: process.env.WENXIN_API_KEY,\n\n ENABLED_OLLAMA: process.env.ENABLED_OLLAMA !== '0',\n ENABLED_OLLAMA_CLOUD: !!process.env.OLLAMA_CLOUD_API_KEY,\n OLLAMA_CLOUD_API_KEY: process.env.OLLAMA_CLOUD_API_KEY,\n\n ENABLED_VLLM: !!process.env.VLLM_API_KEY,\n VLLM_API_KEY: process.env.VLLM_API_KEY,\n\n ENABLED_XINFERENCE: !!process.env.XINFERENCE_API_KEY,\n XINFERENCE_API_KEY: process.env.XINFERENCE_API_KEY,\n\n ENABLED_LMSTUDIO: !!process.env.LMSTUDIO_API_KEY,\n LMSTUDIO_API_KEY: process.env.LMSTUDIO_API_KEY,\n\n ENABLED_QINIU: !!process.env.QINIU_API_KEY,\n QINIU_API_KEY: process.env.QINIU_API_KEY,\n\n ENABLED_QWEN: !!process.env.QWEN_API_KEY,\n QWEN_API_KEY: process.env.QWEN_API_KEY,\n\n ENABLED_STEPFUN: !!process.env.STEPFUN_API_KEY,\n STEPFUN_API_KEY: process.env.STEPFUN_API_KEY,\n\n ENABLED_NOVITA: !!process.env.NOVITA_API_KEY,\n NOVITA_API_KEY: process.env.NOVITA_API_KEY,\n\n ENABLED_NVIDIA: !!process.env.NVIDIA_API_KEY,\n NVIDIA_API_KEY: process.env.NVIDIA_API_KEY,\n\n ENABLED_BAICHUAN: !!process.env.BAICHUAN_API_KEY,\n BAICHUAN_API_KEY: process.env.BAICHUAN_API_KEY,\n\n ENABLED_TAICHU: !!process.env.TAICHU_API_KEY,\n TAICHU_API_KEY: process.env.TAICHU_API_KEY,\n\n ENABLED_CLOUDFLARE:\n !!process.env.CLOUDFLARE_API_KEY && !!process.env.CLOUDFLARE_BASE_URL_OR_ACCOUNT_ID,\n CLOUDFLARE_API_KEY: process.env.CLOUDFLARE_API_KEY,\n CLOUDFLARE_BASE_URL_OR_ACCOUNT_ID: process.env.CLOUDFLARE_BASE_URL_OR_ACCOUNT_ID,\n\n ENABLED_AI360: !!process.env.AI360_API_KEY,\n AI360_API_KEY: process.env.AI360_API_KEY,\n\n ENABLED_SILICONCLOUD: !!process.env.SILICONCLOUD_API_KEY,\n SILICONCLOUD_API_KEY: process.env.SILICONCLOUD_API_KEY,\n\n ENABLED_GITEE_AI: !!process.env.GITEE_AI_API_KEY,\n GITEE_AI_API_KEY: process.env.GITEE_AI_API_KEY,\n\n ENABLED_UPSTAGE: !!process.env.UPSTAGE_API_KEY,\n UPSTAGE_API_KEY: process.env.UPSTAGE_API_KEY,\n\n ENABLED_SPARK: !!process.env.SPARK_API_KEY,\n SPARK_API_KEY: process.env.SPARK_API_KEY,\n\n ENABLED_AI21: !!process.env.AI21_API_KEY,\n AI21_API_KEY: process.env.AI21_API_KEY,\n\n ENABLED_HUNYUAN: !!process.env.HUNYUAN_API_KEY,\n HUNYUAN_API_KEY: process.env.HUNYUAN_API_KEY,\n\n ENABLED_HUGGINGFACE: !!process.env.HUGGINGFACE_API_KEY,\n HUGGINGFACE_API_KEY: process.env.HUGGINGFACE_API_KEY,\n\n ENABLED_SENSENOVA: !!process.env.SENSENOVA_API_KEY,\n SENSENOVA_API_KEY: process.env.SENSENOVA_API_KEY,\n\n ENABLED_XAI: !!process.env.XAI_API_KEY,\n XAI_API_KEY: process.env.XAI_API_KEY,\n\n ENABLED_INTERNLM: !!process.env.INTERNLM_API_KEY,\n INTERNLM_API_KEY: process.env.INTERNLM_API_KEY,\n\n ENABLED_HIGRESS: !!process.env.HIGRESS_API_KEY,\n HIGRESS_API_KEY: process.env.HIGRESS_API_KEY,\n\n ENABLED_TENCENT_CLOUD: !!process.env.TENCENT_CLOUD_API_KEY,\n TENCENT_CLOUD_API_KEY: process.env.TENCENT_CLOUD_API_KEY,\n\n ENABLED_JINA: !!process.env.JINA_API_KEY,\n JINA_API_KEY: process.env.JINA_API_KEY,\n\n ENABLED_SAMBANOVA: !!process.env.SAMBANOVA_API_KEY,\n SAMBANOVA_API_KEY: process.env.SAMBANOVA_API_KEY,\n\n ENABLED_PPIO: !!process.env.PPIO_API_KEY,\n PPIO_API_KEY: process.env.PPIO_API_KEY,\n\n ENABLED_SEARCH1API: !!process.env.SEARCH1API_API_KEY,\n SEARCH1API_API_KEY: process.env.SEARCH1API_API_KEY,\n\n ENABLED_COHERE: !!process.env.COHERE_API_KEY,\n COHERE_API_KEY: process.env.COHERE_API_KEY,\n\n ENABLED_INFINIAI: !!process.env.INFINIAI_API_KEY,\n INFINIAI_API_KEY: process.env.INFINIAI_API_KEY,\n\n ENABLED_FAL: process.env.ENABLED_FAL !== '0',\n FAL_API_KEY: process.env.FAL_API_KEY,\n\n ENABLED_BFL: !!process.env.BFL_API_KEY,\n BFL_API_KEY: process.env.BFL_API_KEY,\n\n ENABLED_COMFYUI: process.env.ENABLED_COMFYUI !== '0',\n COMFYUI_BASE_URL: process.env.COMFYUI_BASE_URL,\n COMFYUI_AUTH_TYPE: process.env.COMFYUI_AUTH_TYPE,\n COMFYUI_API_KEY: process.env.COMFYUI_API_KEY,\n COMFYUI_USERNAME: process.env.COMFYUI_USERNAME,\n COMFYUI_PASSWORD: process.env.COMFYUI_PASSWORD,\n COMFYUI_CUSTOM_HEADERS: process.env.COMFYUI_CUSTOM_HEADERS,\n\n ENABLED_MODELSCOPE: !!process.env.MODELSCOPE_API_KEY,\n MODELSCOPE_API_KEY: process.env.MODELSCOPE_API_KEY,\n\n ENABLED_V0: !!process.env.V0_API_KEY,\n V0_API_KEY: process.env.V0_API_KEY,\n\n ENABLED_VERCELAIGATEWAY: !!process.env.VERCELAIGATEWAY_API_KEY,\n VERCELAIGATEWAY_API_KEY: process.env.VERCELAIGATEWAY_API_KEY,\n\n ENABLED_AI302: !!process.env.AI302_API_KEY,\n AI302_API_KEY: process.env.AI302_API_KEY,\n\n ENABLED_AKASHCHAT: !!process.env.AKASHCHAT_API_KEY,\n AKASHCHAT_API_KEY: process.env.AKASHCHAT_API_KEY,\n\n ENABLED_COMETAPI: !!process.env.COMETAPI_KEY,\n COMETAPI_KEY: process.env.COMETAPI_KEY,\n\n ENABLED_AIHUBMIX: !!process.env.AIHUBMIX_API_KEY,\n AIHUBMIX_API_KEY: process.env.AIHUBMIX_API_KEY,\n\n ENABLED_NEWAPI: !!process.env.NEWAPI_API_KEY,\n NEWAPI_API_KEY: process.env.NEWAPI_API_KEY,\n NEWAPI_PROXY_URL: process.env.NEWAPI_PROXY_URL,\n\n ENABLED_NEBIUS: !!process.env.NEBIUS_API_KEY,\n NEBIUS_API_KEY: process.env.NEBIUS_API_KEY,\n\n ENABLED_CEREBRAS: !!process.env.CEREBRAS_API_KEY,\n CEREBRAS_API_KEY: process.env.CEREBRAS_API_KEY,\n\n ENABLED_ZENMUX: !!process.env.ZENMUX_API_KEY,\n ZENMUX_API_KEY: process.env.ZENMUX_API_KEY,\n\n ENABLED_STRAICO: !!process.env.STRAICO_API_KEY,\n STRAICO_API_KEY: process.env.STRAICO_API_KEY,\n\n ENABLED_LOBEHUB: !!process.env.ENABLED_LOBEHUB,\n\n ENABLED_XIAOMIMIMO: !!process.env.XIAOMIMIMO_API_KEY,\n XIAOMIMIMO_API_KEY: process.env.XIAOMIMIMO_API_KEY,\n\n ENABLED_LONGCAT: !!process.env.LONGCAT_API_KEY,\n LONGCAT_API_KEY: process.env.LONGCAT_API_KEY,\n },\n });\n};\n\nexport const llmEnv = getLLMConfig();\n"}}, "lobehub/docs/self-hosting/environment-variables/model-provider.zh-CN.mdx": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785595581.0570252, "n": 17531, "h": "f7ac086d425d7182", "c": "---\ntitle: LobeHub 模型服务商相关环境变量配置指南\ndescription: 了解如何配置各个模型服务商的环境变量以在 LobeHub 中使用不同的AI模型服务。\ntags:\n - LobeHub\n - 模型服务商\n - 环境变量\n - AI模型\n - 配置指南\n---\n\n# 模型服务商\n\nLobeHub 在部署时提供了丰富的模型服务商相关的环境变量,你可以使用这些环境变量轻松定义需要在 LobeHub 中开启的模型服务商。\n\n## OpenAI\n\n### `ENABLED_OPENAI`\n\n- 类型:可选\n- 描述:默认启用 OpenAI 作为模型供应商,当设为 0 时关闭 OpenAI 服务\n- 默认值:`1`\n- 示例:`0`\n\n### `OPENAI_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 OpenAI 账户页面申请的 API 密钥,可以前往 [这里](https://platform.openai.com/api-keys) 查看\n- 默认值:-\n- 示例:`sk-xxxxxx...xxxxxx`\n\n### `OPENAI_PROXY_URL`\n\n- 类型:可选\n- 描述:如果你手动配置了 OpenAI 接口代理,可以使用此配置项来覆盖默认的 OpenAI API 请求基础 URL\n- 默认值:`https://api.openai.com/v1`\n- 示例:`https://api.chatanywhere.cn` 或 `https://aihubmix.com/v1`\n\n<Callout type={'warning'}>\n 请检查你的代理服务商的请求后缀,有的代理服务商会在请求后缀添加\n `/v1`,有的则不会。如果你在测试时发现 AI 返回的消息为空,请尝试添加 `/v1` 后缀后重试。\n</Callout>\n\n<Callout type={'info'}>\n 是否填写 `/v1` 跟模型服务商有很大关系,比如 openai 的默认地址是 `api.openai.com/v1`\n 。如果你的代理商转发了 `/v1` 这个接口,那么直接填 `proxy.com` 即可。 但如果模型服务商是直接转发了\n `api.openai.com` 域名,那么你就要自己加上 `/v1` 这个 url。\n</Callout>\n\n相关讨论:\n\n- [Docker 安装,配置好环境变量后,为何返回值是空白?](https://github.com/lobehub/lobehub/discussions/623)\n- [使用第三方接口报错的原因](https://github.com/lobehub/lobehub/discussions/734)\n- [代理服务器地址填了聊天没任何反应](https://github.com/lobehub/lobehub/discussions/1065)\n\n### `OPENAI_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`+qwen-7b-chat,+glm-6b,-gpt-3.5-turbo,gpt-4-0125-preview=gpt-4-turbo`\n\n上面示例表示增加 `qwen-7b-chat` 和 `glm-6b` 到模型列表,而从列表中删除 `gpt-3.5-turbo`,并将 `gpt-4-0125-preview` 模型名字展示为 `gpt-4-turbo`。如果你想先禁用所有模型,再启用指定模型,可以使用 `-all,+gpt-3.5-turbo`,则表示仅启用 `gpt-3.5-turbo`。\n\n你可以在 [modelProviders](https://github.com/lobehub/lobehub/tree/main/src/config/modelProviders) 查找到当前的所有模型名。\n\n## Azure OpenAI\n\n如果你需要使用 Azure OpenAI 来提供模型服务,可以查阅 [使用 Azure OpenAI 部署](/zh/docs/self-hosting/examples/azure-openai) 章节查看详细步骤,这里将列举和 Azure OpenAI 相关的环境变量。\n\n### `AZURE_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Azure OpenAI 账户页面申请的 API 密钥\n- 默认值:-\n- 示例:`c55168be3874490ef0565d9779ecd5a6`\n\n### `AZURE_ENDPOINT`\n\n- 类型:必选\n- 描述:Azure API 地址,从 Azure 门户检查资源时,可在 “密钥和终结点” 部分中找到此值\n- 默认值:`-`\n- 示例:`https://docs-test-001.openai.azure.com`\n\n### `AZURE_API_VERSION`\n\n- 类型:必选\n- 描述:Azure 的 API 版本,遵循 YYYY-MM-DD 格式\n- 默认值:`-`\n- 示例:`2024-02-01`,查阅 [最新版本](https://docs.microsoft.com/zh-cn/azure/developer/javascript/api-reference/es-modules/azure-sdk/ai-translation/translationconfiguration?view=azure-node-latest#api-version)\n\n### `AZURE_MODEL_LIST`\n\n- 类型:必选\n- 描述:用来控制模型列表,使用 `模型名->部署名=展示名` 来自定义模型的展示名,用英文逗号隔开。支持扩展能力,其余语法规则详见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`gpt-35-turbo->my-deploy=GPT 3.5 Turbo` 或 `gpt-4-turbo->my-gpt4=GPT 4 Turbo<128000:vision:fc>`\n\n## Google AI\n\n### `GOOGLE_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Google AI Platform 申请的 API 密钥,用于访问 Google AI 服务\n- 默认值:-\n- 示例:`AIraDyDwcw254kwJaGjI9wwaHcdDCS__Vt3xQE`\n\n### `GOOGLE_PROXY_URL`\n\n- 类型:可选\n- 描述:如果你手动配置了 Google 接口代理,可以使用此配置项来覆盖默认的 Google API 请求基础 URL\n- 默认值:`https://generativelanguage.googleapis.com`\n- 示例:`https://api.genai.gd.edu.kg/google`\n\n### `GOOGLE_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+gemini-1.5-flash-latest,+gemini-1.5-pro-latest`\n\n## Vertex AI\n\n### `VERTEXAI_CREDENTIALS`\n\n- 类型:必选\n- 描述:Google Cloud 服务账号密钥的 JSON 字符串。用于认证和授权访问 Vertex AI 服务,获取方法请参考 [这里](/zh/docs/usage/providers/vertexai)\n- 默认值:-\n- 示例:`{\"type\": \"service_account\", \"project_id\": \"your-gcp-project-id\", ...}`\n\n### `VERTEXAI_PROJECT`\n\n- 类型:可选\n- 描述:你的 Google Cloud 项目 ID。如果未设置,将从 `VERTEXAI_CREDENTIALS` 中的 `project_id` 字段获取。\n- 默认值:-\n- 示例:`your-gcp-project-id`\n\n### `VERTEXAI_LOCATION`\n\n- 类型:可选\n- 描述:你的 Vertex AI 模型所在的区域。\n- 默认值:`global`\n- 示例:`us-central1`\n\n### `VERTEXAI_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+gemini-1.5-flash-latest,+gemini-1.5-pro-latest`\n\n## Anthropic AI\n\n### `ANTHROPIC_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Anthropic AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`sk-ant-apixx-xxxxxxxxx-xxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxx`\n\n### `ANTHROPIC_PROXY_URL`\n\n- 类型:可选\n- 描述:如果你手动配置了 Anthropic 接口代理,可以使用此配置项来覆盖默认的 Anthropic API 请求基础 URL\n- 默认值:`https://api.anthropic.com`\n- 示例:`https://my-anthropic-proxy.com`\n\n## AWS Bedrock\n\n### `ENABLED_AWS_BEDROCK`\n\n- 类型:可选\n- 描述:当设为 1 时启用 AWS Bedrock 服务\n- 默认值:`0`\n- 示例:`1`\n\n### `AWS_ACCESS_KEY_ID`\n\n- 类型:必选\n- 描述:用于 AWS 服务认证的访问键 ID\n- 默认值:-\n- 示例:`AKIA5STVRLFSB4S9HWBR`\n\n### `AWS_SECRET_ACCESS_KEY`\n\n- 类型:必选\n- 描述:用于 AWS 服务认证的密钥\n- 默认值:-\n- 示例:`Th3vXxLYpuKcv2BARktPSTPxx+jbSiFT6/0w7oEC`\n\n### `AWS_REGION`\n\n- 类型:可选\n- 描述:AWS 服务的区域设置\n- 默认值:`us-east-1`\n- 示例:`us-east-1`\n\n## ComfyUI\n\n### `ENABLED_COMFYUI`\n\n- 类型:可选\n- 描述:默认启用 ComfyUI 作为模型供应商,当设为 0 时关闭 ComfyUI 服务\n- 默认值:`1`\n- 示例:`0`\n\n### `COMFYUI_BASE_URL`\n\n- 类型:可选\n- 描述:ComfyUI 服务的基础 URL 地址\n- 默认值:`http://localhost:8000`\n- 示例:`http://192.168.1.100:8000` 或 `https://my-comfyui-server.com`\n\n### `COMFYUI_AUTH_TYPE`\n\n- 类型:可选\n- 描述:ComfyUI 的认证类型,支持 4 种认证方式\n - `none`: 无认证(默认)\n - `basic`: 基础认证(用户名 + 密码)\n - `bearer`: Bearer Token 认证(API 密钥)\n - `custom`: 自定义请求头认证\n- 默认值:`none`\n- 示例:`basic`\n\n### `COMFYUI_API_KEY`\n\n- 类型:可选\n- 描述:当认证类型为 `bearer` 时使用的 API 密钥\n- 默认值:-\n- 示例:`sk-xxxxxx...xxxxxx`\n\n### `COMFYUI_USERNAME`\n\n- 类型:可选\n- 描述:当认证类型为 `basic` 时使用的用户名\n- 默认值:-\n- 示例:`admin`\n\n### `COMFYUI_PASSWORD`\n\n- 类型:可选\n- 描述:当认证类型为 `basic` 时使用的密码\n- 默认值:-\n- 示例:`password123`\n\n### `COMFYUI_CUSTOM_HEADERS`\n\n- 类型:可选\n- 描述:当认证类型为 `custom` 时使用的自定义请求头,需要使用 JSON 格式字符串\n- 默认值:-\n- 示例:`{\"X-Auth-Token\": \"your-token\", \"X-Custom-Header\": \"value\"}`\n\n<Callout type={'info'}>\n ComfyUI 支持多种认证方式,请根据您的 ComfyUI 服务配置选择合适的认证类型和相应的认证参数。如果您的\n ComfyUI 服务没有设置认证,可以不配置认证相关的环境变量。\n</Callout>\n\n## DeepSeek AI\n\n### `DEEPSEEK_PROXY_URL`\n\n- 类型:可选\n- 描述:如果您手动配置了 DeepSeek API 代理,可以使用此配置项覆盖默认的 DeepSeek API 请求基础 URL\n- 默认值:`https://api.deepseek.com`\n- 示例:`https://my-deepseek-proxy.com`\n\n### `DEEPSEEK_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 DeepSeek AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`sk-xxxxxx...xxxxxx`\n\n### `DEEPSEEK_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+deepseek-reasoner`\n\n## XAI\n\n### `XAI_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 XAI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xai-xxxxxx...xxxxxx`\n\n## 文心一言\n\n### `WENXIN_API_KEY`\n\n- 类型:必选\n- 描述:这是你在百度智能云平台申请的文心一言 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n## OpenRouter AI\n\n### `OPENROUTER_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 OpenRouter AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`sk-or-v1-xxxxxx...xxxxxx=`\n\n### `OPENROUTER_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+01-ai/yi-34b-chat,+huggingfaceh4/zephyr-7b-beta`\n\n## PPIO\n\n### `PPIO_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 PPIO 网站申请的 API 密钥\n- 默认值:-\n- 示例:`sk_xxxxxxxxxxxx`\n\n### `PPIO_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+deepseek/deepseek-v3/community,+deepseek/deepseek-r1-distill-llama-70b`\n\n## Github\n\n### `GITHUB_TOKEN`\n\n- 类型:必选\n- 描述:这是你在 Github 申请的 Personal access tokens\n- 默认值:-\n- 示例:`ghp_xxxxxx...xxxxxx=`\n\n### `GITHUB_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+gpt-4o,+gpt-4o-mini`\n\n## TogetherAI\n\n### `TOGETHERAI_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 TogetherAI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n### `TOGETHERAI_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo,+meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo`\n\n## Fireworks AI\n\n### `FIREWORKSAI_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Fireworks AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n### `FIREWORKSAI_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+accounts/fireworks/models/firefunction-v2,+accounts/fireworks/models/firefunction-v1`\n\n## Ollama\n\n### `ENABLED_OLLAMA`\n\n- 类型:可选\n- 描述:默认启用 Ollama 作为模型供应商,当设为 0 时关闭 Ollama 服务\n- 默认值:`1`\n- 示例:`0`\n\n### `OLLAMA_PROXY_URL`\n\n- 类型:必选\n- 描述:用于启用 Ollama 服务,设置后可在语言模型列表内展示可选开源语言模型,也可以指定自定义语言模型\n- 默认值:-\n- 示例:`http://127.0.0.1:11434`\n\n### `OLLAMA_MODEL_LIST`\n\n- 类型:可选\n- 描述:用于指定自定义 Ollama 语言模型。模型定义语法规则见 [模型列表][model-list]\n- 默认值:-\n- 示例:`qwen:32B`\n\n## Moonshot AI\n\n### `MOONSHOT_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Moonshot AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`Y2xpdGhpMzNhZXNoYjVtdnZjMWc6bXNrLWIxQlk3aDNPaXpBWnc0V1RaMDhSRmRFVlpZUWY=`\n\n### `MOONSHOT_PROXY_URL`\n\n- 类型:可选\n- 描述:如果你手动配置了 Moonshot 接口代理,可以使用此配置项来覆盖默认的 Moonshot API 请求基础 URL\n- 默认值:`https://api.moonshot.cn/v1`\n- 示例:`https://my-moonshot-proxy.com/v1`\n\n## Perplexity AI\n\n### `PERPLEXITY_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Perplexity AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`pplx-xxxxxx...xxxxxx`\n\n### `PERPLEXITY_MODEL_LIST`\n\n- 类型:可选\n- 描述:用于指定自定义 Perplexity 语言模型。模型定义语法规则见 [模型列表][model-list]\n- 默认值:-\n- 示例: `-all,+llama-3.1-sonar-small-128k-online,+llama-3.1-sonar-small-128k-chat`\n\n### `PERPLEXITY_PROXY_URL`\n\n- 类型:可选\n- 描述:如果你手动配置了 Perplexity 接口代理,可以使用此配置项来覆盖默认的 Perplexity API 请求基础 URL\n- 默认值:`https://api.Perplexity.ai`\n- 示例:`https://my-Perplexity-proxy.com`\n\n## Minimax AI\n\n### `MINIMAX_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Minimax AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n## Mistral AI\n\n### `MISTRAL_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Mistral AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx=`\n\n## Groq AI\n\n### `GROQ_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Groq AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`gsk_xxxxxx...xxxxxx`\n\n### `GROQ_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+gemma2-9b-it,+llama-3.1-8b-instant`\n\n### `GROQ_PROXY_URL`\n\n- 类型:可选\n- 描述:如果你手动配置了 Groq 接口代理,可以使用此配置项来覆盖默认的 Groq API 请求基础 URL\n- 默认值:`https://api.groq.com/openai/v1`\n- 示例:`https://my-groq-proxy.com/v1`\n\n## 智谱 AI\n\n### `ZHIPU_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 智谱 AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`4582d332441a313f5c2ed9824d1798ca.rC8EcTAhgbOuAuVT`\n\n### `ZHIPU_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+glm-4-alltools,+glm-4-plus`\n\n## 01 AI\n\n### `ZEROONE_API_KEY`\n\n- 类型:必选\n- 描述:这是你在零一万物服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n### `ZEROONE_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+yi-large,+yi-large-rag`\n\n## 七牛云\n\n### `QINIU_API_KEY`\n\n- 类型:必选\n- 描述:这是你在七牛云上获取的 API 密钥\n- 默认值:-\n- 示例:`sk-xxxxx...xxxxx`\n\n### `QINIU_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+deepseek-r1,+deepseek-v3`\n\n### `QINIU_PROXY_URL`\n\n- 类型:可选\n- 描述:如果你手动配置了 Qiniu 接口代理,可以使用此配置项来覆盖默认的 Qiniu API 请求基础 URL\n- 默认值:`https://api.qnaigc.com/v1`\n- 示例:`https://my-qnaigc.com/v1`\n\n## 通义千问\n\n### `QWEN_API_KEY`\n\n- 类型:必选\n- 描述:这是你在阿里云百炼平台上获取的 DashScope API 密钥\n- 默认值:-\n- 示例:`sk-xxxxx...xxxxx`\n\n### `QWEN_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名->部署名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。部署名`->部署名`可以省略,默认为最新版本的模型。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+qwen-turbo,+qwen-plus,+qwen-max->qwen-max-2025-01-25`\n\n### `QWEN_PROXY_URL`\n\n- 类型:可选\n- 描述:如果你手动配置了 Qwen 接口代理,可以使用此配置项来覆盖默认的 Qwen API 请求基础 URL\n- 默认值:`https://dashscope.aliyuncs.com/compatible-mode/v1`\n- 示例:`https://my-qwen-proxy.com/v1`\n\n## Stepfun AI\n\n### `STEPFUN_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Stepfun AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n## Novita AI\n\n### `NOVITA_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Novita AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n### `NOVITA_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+meta-llama/llama-3.1-8b-instruct,+meta-llama/llama-3.1-70b-instruct`\n\n## 百川\n\n### `BAICHUAN_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 百川智能 服务平台申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n## 紫东太初\n\n### `TAICHU_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 紫东太初 服务平台申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n## 360 AI\n\n### `AI360_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 360 智脑 服务平台申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n## Siliconflow\n\n### `SILICONCLOUD_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Siliconflow 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n### `SILICONCLOUD_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+deepseek-ai/DeepSeek-V2.5,+Qwen/Qwen2.5-7B-Instruct`\n\n### `SILICONCLOUD_PROXY_URL`\n\n- 类型:可选\n- 描述:如果你手动配置了 Siliconflow 接口代理,可以使用此配置项来覆盖默认的 Siliconflow API 请求基础 URL\n- 默认值:`https://api.siliconflow.cn/v1`\n- 示例:`https://my-siliconflow-proxy.com/v1`\n\n## Upstage AI\n\n### `UPSTAGE_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Upstage AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n## Spark AI\n\n### `SPARK_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Spark AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n## A21 AI\n\n### `AI21_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 A21 AI 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n## 腾讯混元\n\n### `HUNYUAN_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 腾讯混元 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`xxxxxx...xxxxxx`\n\n### `HUNYUAN_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+hunyuan-lite,+hunyuan-standard`\n\n## 火山引擎\n\n### `VOLCENGINE_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 火山引擎 服务中申请的 API 密钥,可以前往 [这里](https://console.volcengine.com/ark/region:ark+cn-beijing/endpoint) 查看\n- 默认值:-\n- 示例:`ad925b3d-aaaa-bbbb-cccc-51fde2f50547`\n\n### `VOLCENGINE_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名->部署名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。部署名`->部署名`可以省略,默认为最新版本的模型。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+deepseek-r1,+deepseek-v3->deepseek-v3-250324,+doubao-1.5-pro-256k,+doubao-1.5-pro-32k->doubao-1-5-pro-32k-250115,+doubao-1.5-lite-32k`\n\n### `VOLCENGINE_PROXY_URL`\n\n- 类型:可选\n- 描述:如果你手动配置了 Volcengine 接口代理,可以使用此配置项来覆盖默认的 Volcengine API 请求基础 URL\n- 默认值:`https://ark.cn-beijing.volces.com/api/v3`\n- 示例:`https://my-volcengine-proxy.com/v1`\n\n## InfiniAI\n\n### `INFINIAI_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 [Infini-AI](https://cloud.infini-ai.com) 申请的 API 密钥。\n- 默认值:-\n- 示例:`sk-xxxxxx...xxxxxx`\n\n### `INFINIAI_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名<扩展配置>` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则见 [模型列表][model-list]\n- 默认值:`-`\n- 示例:`-all,+qwq-32b,+deepseek-r1`\n\n## FAL\n\n### `ENABLED_FAL`\n\n- 类型:可选\n- 描述:默认启用 FAL 作为模型供应商,当设为 0 时关闭 FAL 服务\n- 默认值:`1`\n- 示例:`0`\n\n### `FAL_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 FAL 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`fal-xxxxxx...xxxxxx`\n\n### `FAL_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制 FAL 模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则与其他 provider 保持一致。\n- 默认值:`-`\n- 示例:`-all,+fal-ai/flux/schnell,+fal-ai/flux-pro/kontext=FLUX.1 Kontext [pro]`\n\n上述示例表示先禁用所有模型,再启用 `fal-ai/flux/schnell` 和 `fal-ai/flux-pro/kontext`(显示名为 `FLUX.1 Kontext [pro]`)。\n\n## BFL\n\n### `BFL_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 BFL 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`12345678-1234-1234-1234-123456789abc`\n\n### `BFL_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制 BFL 模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则与其他 provider 保持一致。\n- 默认值:`-`\n- 示例:`-all,+flux-pro-1.1,+flux-kontext-pro=FLUX.1 Kontext [pro]`\n\n上述示例表示先禁用所有模型,再启用 `flux-pro-1.1` 和 `flux-kontext-pro`(显示名为 `FLUX.1 Kontext [pro]`)。\n\n## NewAPI\n\n### `NEWAPI_API_KEY`\n\n- 类型:可选\n- 描述:这是你的 NewAPI 服务实例的 API 密钥。NewAPI 是一个多供应商模型聚合服务,提供对各种 AI 模型 API 的统一访问。\n- 默认值:-\n- 示例:`sk-xxxxxx...xxxxxx`\n\n### `NEWAPI_PROXY_URL`\n\n- 类型:可选\n- 描述:你的 NewAPI 服务器实例的基础 URL。这应该指向你部署的 NewAPI 服务端点。\n- 默认值:-\n- 示例:`https://your-newapi-server.com`\n\n<Callout type={'info'}>\n NewAPI\n 是一个多供应商模型聚合服务,支持基于供应商检测的自动模型路由。它提供成本管理功能,并为访问包括\n OpenAI、Anthropic、Google 等多个供应商的模型提供单一端点。了解更多关于 NewAPI 的信息请访问\n [https://github.com/Calcium-Ion/new-api](https://github.com/Calcium-Ion/new-api)。\n</Callout>\n\n## Vercel AI Gateway\n\n### `VERCELAIGATEWAY_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Vercel AI Gateway 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`vck_xxxxxx...xxxxxx`\n\n### `VERCELAIGATEWAY_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制 Vercel AI Gateway 模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则与其他 provider 保持一致。\n- 默认值:`-`\n- 示例:`-all,+vercel-model-1,+vercel-model-2=vercel-special`\n\n## Cerebras\n\n### `CEREBRAS_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Cerebras 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`csk-xxxxxx...xxxxxx`\n\n### `CEREBRAS_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制 Cerebras 模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则与其他 provider 保持一致。\n- 默认值:`-`\n- 示例:`-all,+cerebras-model-1,+cerebras-model-2=cerebras-special`\n\n## AiHubMix\n\n### `AIHUBMIX_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 AiHubMix 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`sk-xxxxxx...xxxxxx`\n\n### `AIHUBMIX_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制 AiHubMix 模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则与其他 provider 保持一致。\n- 默认值:`-`\n- 示例:`-all,+claude-opus-4-1-20250805,+claude-opus-4-20250514=claude-opus-4`\n\n## Straico\n\n### `STRAICO_API_KEY`\n\n- 类型:必选\n- 描述:这是你在 Straico 服务中申请的 API 密钥\n- 默认值:-\n- 示例:`sk-xxxxxx...xxxxxx`\n\n### `STRAICO_MODEL_LIST`\n\n- 类型:可选\n- 描述:用来控制 Straico 模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。模型定义语法规则与其他 provider 保持一致。\n- 默认值:`-`\n- 示例:`-all,+straico-model-1,+straico-model-2=straico-special`\n\n[model-list]: /zh/docs/self-hosting/advanced/model-list\n"}}, "lobehub/docs/self-hosting/environment-variables/model-provider.mdx": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785595581.811193, "n": 29039, "h": "d162050b3bc61d15", "c": "---\ntitle: LobeHub Model Service Providers - Environment Variables and Configuration\ndescription: >-\n Learn about the environment variables and configuration settings for various\n model service providers like OpenAI, Google AI, AWS Bedrock, Ollama,\n Perplexity AI, Anthropic AI, Mistral AI, Groq AI, OpenRouter AI, and 01.AI.\ntags:\n - Model Service Providers\n - Environment Variables\n---\n\n# Model Providers\n\nWhen deploying LobeHub, a rich set of environment variables related to model service providers is provided, allowing you to easily define the model service providers to be enabled in LobeHub.\n\n## OpenAI\n\n### `ENABLED_OPENAI`\n\n- Type:Optional\n- Description:Enables OpenAI as a model provider by default, turns off the OpenAI service when set to `0`\n- Default:`1`\n- Example:`0`\n\n### `OPENAI_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for on the OpenAI account page, you can check it out [here](https://platform.openai.com/api-keys)\n- Default: -\n- Example: `sk-xxxxxx...xxxxxx`\n\n### `OPENAI_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the OpenAI interface proxy, you can use this configuration item to override the default OpenAI API request base URL\n- Default: `https://api.openai.com/v1`\n- Example: `https://api.chatanywhere.cn` or `https://aihubmix.com/v1`\n\n<Callout type={'warning'}>\n Please check the request suffix of your proxy service provider. Some proxy service providers may\n add `/v1` to the request suffix, while others may not. If you find that the AI returns an empty\n message during testing, try adding the `/v1` suffix and retry.\n</Callout>\n\n<Callout type={'info'}>\n Whether to fill in `/v1` is closely related to the model service provider. For example, the\n default address of openai is `api.openai.com/v1`. If your proxy forwards the `/v1` interface, you\n can simply fill in `proxy.com`. However, if the model service provider directly forwards the\n `api.openai.com` domain, then you need to add `/v1` to the URL yourself.\n</Callout>\n\nRelated discussions:\n\n- [Why is the return value blank after installing Docker, configuring environment variables?](https://github.com/lobehub/lobehub/discussions/623)\n- [Reasons for errors when using third-party interfaces](https://github.com/lobehub/lobehub/discussions/734)\n- [No response in chat after filling in the proxy server address](https://github.com/lobehub/lobehub/discussions/1065)\n\n### `OPENAI_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `+qwen-7b-chat,+glm-6b,-gpt-3.5-turbo,gpt-4-0125-preview=gpt-4-turbo`\n\nThe above example adds `qwen-7b-chat` and `glm-6b` to the model list, removes `gpt-3.5-turbo` from the list, and displays the name of `gpt-4-0125-preview` as `gpt-4-turbo`. If you want to disable all models first and then enable specific models, you can use `-all,+gpt-3.5-turbo`, which means only `gpt-3.5-turbo` will be enabled.\n\nYou can find all current model names in [modelProviders](https://github.com/lobehub/lobehub/tree/main/src/config/modelProviders).\n\n## Azure OpenAI\n\nIf you need to use Azure OpenAI to provide model services, you can refer to the [Deploying with Azure OpenAI](/docs/self-hosting/examples/azure-openai) section for detailed steps. Here, we will list the environment variables related to Azure OpenAI.\n\n### `AZURE_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for on the Azure OpenAI account page\n- Default: -\n- Example: `c55168be3874490ef0565d9779ecd5a6`\n\n### `AZURE_ENDPOINT`\n\n- Type: Required\n- Description: The endpoint of Azure OpenAI, you can find it in the Azure OpenAI account page\n- Default: `-`\n- Example: `https://docs-test-001.openai.azure.com`\n\n### `AZURE_API_VERSION`\n\n- Type: Required\n- Description: The API version of Azure, following the format YYYY-MM-DD\n- Default: `-`\n- Example: `2023-02-01`, refer to [latest version](https://docs.microsoft.com/zh-cn/azure/developer/javascript/api-reference/es-modules/azure-sdk/ai-translation/translationconfiguration?view=azure-node-latest#api-version)\n\n### `AZURE_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `id->deploymentName=displayName` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `gpt-35-turbo->my-deploy=GPT 3.5 Turbo` 或 `gpt-4-turbo->my-gpt4=GPT 4 Turbo<128000:vision:fc>`\n\n## Google AI\n\n### `GOOGLE_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the Google AI Platform to access Google AI services\n- Default: -\n- Example: `AIraDyDwcw254kwJaGjI9wwaHcdDCS__Vt3xQE`\n\n### `GOOGLE_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the Google API proxy, you can use this configuration item to override the default Google API request base URL\n- Default: `https://generativelanguage.googleapis.com`\n- Example: `https://api.genai.gd.edu.kg/google`\n\n### `GOOGLE_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+gemini-1.5-flash-latest,+gemini-1.5-pro-latest`\n\n## Vertex AI\n\n### `VERTEXAI_CREDENTIALS`\n\n- Type: Required\n- Description: A JSON string of your Google Cloud service account key, you can get the key from [here](/docs/usage/providers/vertexai).\n- Default: -\n- Example: `{\"type\": \"service_account\", \"project_id\": \"your-gcp-project-id\", ...}`\n\n### `VERTEXAI_PROJECT`\n\n- Type: Optional\n- Description: Your Google Cloud project ID. If not set, it will be obtained from the `project_id` field in `VERTEXAI_CREDENTIALS`.\n- Default: -\n- Example: `your-gcp-project-id`\n\n### `VERTEXAI_LOCATION`\n\n- Type: Optional\n- Description: The region where your Vertex AI model is located.\n- Default: `global`\n- Example: `us-central1`\n\n### `VERTEXAI_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+gemini-1.5-flash-latest,+gemini-1.5-pro-latest`\n\n## Anthropic AI\n\n### `ANTHROPIC_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied from Anthropic AI\n- Default: -\n- Example: `sk-ant-apixx-xxxxxxxxx-xxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxx`\n\n### `ANTHROPIC_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the Anthropic API proxy, you can use this configuration item to override the default Anthropic API request base URL\n- Default: `https://api.anthropic.com`\n- Example: `https://my-anthropic-proxy.com`\n\n## AWS Bedrock\n\n### `ENABLED_AWS_BEDROCK`\n\n- Type:Optional\n- Description:Enables AWS Bedrock as a model provider by default, turns on the AWS Bedrock service when set to `1`\n- Default:`0`\n- Example:`1`\n\n### `AWS_ACCESS_KEY_ID`\n\n- Type: Required\n- Description: Access key ID for AWS service authentication\n- Default: -\n- Example: `AKIA5STVRLFSB4S9HWBR`\n\n### `AWS_SECRET_ACCESS_KEY`\n\n- Type: Required\n- Description: Key for AWS service authentication\n- Default: -\n- Example: `Th3vXxLYpuKcv2BARktPSTPxx+jbSiFT6/0w7oEC`\n\n### `AWS_REGION`\n\n- Type: Optional\n- Description: Region setting for AWS services\n- Default: `us-east-1`\n- Example: `us-east-1`\n\n## DeepSeek AI\n\n### `DEEPSEEK_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the DeepSeek API proxy, you can use this configuration item to override the default DeepSeek API request base URL\n- Default: `https://api.deepseek.com`\n- Example: `https://my-deepseek-proxy.com`\n\n### `DEEPSEEK_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the DeepSeek AI service\n- Default: -\n- Example: `sk-xxxxxx...xxxxxx`\n\n### `DEEPSEEK_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=displayName` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+deepseek-reasoner`\n\n## XAI\n\n### `XAI_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the XAI service\n- Default: -\n- Example: `xai-xxxxxx...xxxxxx`\n\n## Wenxin\n\n### `WENXIN_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the Baidu Wenxin service\n- Default: -\n- Example: `xxxxxx...xxxxxx`\n\n## OpenRouter AI\n\n### `OPENROUTER_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the OpenRouter AI service\n- Default: -\n- Example: `sk-or-v1-xxxxxx...xxxxxx=`\n\n### `OPENROUTER_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to specify a custom OpenRouter model list. Model definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+01-ai/yi-34b-chat,+huggingfaceh4/zephyr-7b-beta`\n\n## PPIO\n\n### `PPIO_API_KEY`\n\n- Type: Required\n- Description: This your PPIO API Key.\n- Default: -\n- Example: `sk_xxxxxxxxxx`\n\n### `PPIO_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+deepseek/deepseek-v3/community,+deepseek/deepseek-r1-distill-llama-70b`\n\n## Github\n\n### `GITHUB_TOKEN`\n\n- Type: Required\n- Description: This is your Personal access tokens you got for in the Github\n- Default: `-`\n- Example:`ghp_xxxxxx...xxxxxx=`\n\n### `GITHUB_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+gpt-4o,+gpt-4o-mini`\n\n## TogetherAI\n\n### `TOGETHERAI_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the TogetherAI service\n- Default: -\n- Example: `xxxxxx...xxxxxx`\n\n### `TOGETHERAI_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to specify a custom TogetherAI model list. Model definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo,+meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo`\n\n## Fireworks AI\n\n### `FIREWORKSAI_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the Fireworks AI service\n- Default: `-`\n- Example:`xxxxxx...xxxxxx`\n\n### `FIREWORKSAI_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+accounts/fireworks/models/firefunction-v2,+accounts/fireworks/models/firefunction-v1`\n\n## Ollama\n\n### `ENABLED_OLLAMA`\n\n- Type:Optional\n- Description:Enables Ollama as a model provider by default, turns off the Ollama service when set to `0`\n- Default:`1`\n- Example:`0`\n\n### `OLLAMA_PROXY_URL`\n\n- Type: Required\n- Description: Used to enable the Ollama service, setting this will display optional open-source language models in the language model list and can also specify custom language models\n- Default: -\n- Example: `http://127.0.0.1:11434`\n\n### `OLLAMA_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to specify a custom Ollama language model. Model definition syntax rules see [model-list][model-list]\n- Default: -\n- Example: `llama2:7B`\n\n## Moonshot AI\n\n### `MOONSHOT_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the Moonshot AI service\n- Default: -\n- Example: `Y2xpdGhpMzNhZXNoYjVtdnZjMWc6bXNrLWIxQlk3aDNPaXpBWnc0V1RaMDhSRmRFVlpZUWY=`\n\n### `MOONSHOT_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the Moonshot API proxy, you can use this configuration item to override the default Moonshot API request base URL\n- Default: `https://api.moonshot.cn/v1`\n- Example: `https://my-moonshot-proxy.com/v1`\n\n## Perplexity AI\n\n### `PERPLEXITY_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied from Perplexity AI\n- Default: -\n- Example: `pplx-xxxxxx...xxxxxx`\n\n### `PERPLEXITY_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the Perplexity API proxy, you can use this configuration item to override the default Perplexity API request base URL\n- Default: `https://api.Perplexity.ai`\n- Example: `https://my-Perplexity-proxy.com`\n\n### `PERPLEXITY_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see\n- Default: `-`\n- Example: `-all,+llama-3.1-sonar-small-128k-online,+llama-3.1-sonar-small-128k-chat`\n\n## Minimax AI\n\n### `MINIMAX_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the Minimax AI service\n- Default: -\n- Example: `xxxxxx...xxxxxx`\n\n## Mistral AI\n\n### `MISTRAL_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the Mistral AI service\n- Default: -\n- Example: `xxxxxx...xxxxxx=`\n\n## Groq AI\n\n### `GROQ_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied from Groq AI\n- Default: -\n- Example: `gsk_xxxxxx...xxxxxx`\n\n### `GROQ_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the Groq API proxy, you can use this configuration item to override the default Groq API request base URL\n- Default: `https://api.groq.com/openai/v1`\n- Example: `https://my-groq-proxy.com/v1`\n\n### `GROQ_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+gemma2-9b-it,+llama-3.1-8b-instant`\n\n## ZHIPU AI\n\n### `ZHIPU_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the ZHIPU AI service\n- Default: -\n- Example: `4582d332441a313f5c2ed9824d1798ca.rC8EcTAhgbOuAuVT`\n\n### `ZHIPU_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+glm-4-alltools,+glm-4-plus`\n\n## 01.AI\n\n### `ZEROONE_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the 01.AI service\n- Default: -\n- Example:`xxxxxx...xxxxxx`\n\n### `ZEROONE_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+yi-large,+yi-large-rag`\n\n## Qiniu\n\n### `QINIU_API_KEY`\n\n- Type: Required\n- Description: This is the API key you can obtain from Qiniu AI service\n- Default: -\n- Example:`sk-xxxxx...xxxxx`\n\n### `QINIU_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+deepseek-r1,+deepseek-v3`\n\n### `QINIU_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the Qiniu API proxy, you can use this configuration item to override the default Qiniu API request base URL\n- Default: `https://api.qnaigc.com/v1`\n- Example: `https://my-qnaigc.com/v1`\n\n## Qwen\n\n### `QWEN_API_KEY`\n\n- Type: Required\n- Description: This is the DashScope API key you can obtain from Alibaba Cloud\n- Default: -\n- Example:`sk-xxxxx...xxxxx`\n\n### `QWEN_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name->deploymentName=display_name` to customize the display name of a model, separated by commas. The deploymentName `->deploymentName` can be omitted, and it defaults to the latest model version. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+qwen-turbo,+qwen-plus,+qwen-max->qwen-max-2025-01-25`\n\n### `QWEN_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the Qwen API proxy, you can use this configuration item to override the default Qwen API request base URL\n- Default: `https://dashscope.aliyuncs.com/compatible-mode/v1`\n- Example: `https://my-qwen-proxy.com/v1`\n\n## Stepfun AI\n\n### `STEPFUN_API_KEY`\n\n- Type: Required\n- Description: This is the DashScope API key you can obtain from Stepfun AI service\n- Default: -\n- Example:`sk-xxxxx...xxxxx`\n\n## Novita AI\n\n### `NOVITA_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the Novita AI service\n- Default: -\n- Example:`xxxxxx...xxxxxx`\n\n### `NOVITA_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+meta-llama/llama-3.1-8b-instruct,+meta-llama/llama-3.1-70b-instruct`\n\n## BAICHUAN\n\n### `BAICHUAN_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the BAICHUAN service\n- Default: -\n- Example:`xxxxxx...xxxxxx`\n\n## TAICHU\n\n### `TAICHU_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the TAICHU service\n- Default: -\n- Example:`xxxxxx...xxxxxx`\n\n## 360 AI\n\n### `AI360_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the 360 AI service\n- Default: -\n- Example:`xxxxxx...xxxxxx`\n\n## Siliconflow\n\n### `SILICONCLOUD_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied from Siliconflow service\n- Default: -\n- Example: `xxxxxx...xxxxxx`\n\n### `SILICONCLOUD_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the Siliconflow API proxy, you can use this configuration item to override the default Siliconflow API request base URL\n- Default: `https://api.siliconflow.cn/v1`\n- Example: `https://my-siliconflow-proxy.com/v1`\n\n### `SILICONCLOUD_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+deepseek-ai/DeepSeek-V2.5,+Qwen/Qwen2.5-7B-Instruct`\n\n## Upstage AI\n\n### `UPSTAGE_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied from Upstage AI service\n- Default: -\n- Example: `xxxxxx...xxxxxx`\n\n## Spark AI\n\n### `SPARK_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied from Spark AI service\n- Default: -\n- Example: `xxxxxx...xxxxxx`\n\n## A21 AI\n\n### `AI21_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied from `AI21_API_KEY` service\n- Default: -\n- Example: `xxxxxx...xxxxxx`\n\n## HUNYUAN\n\n### `HUNYUAN_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied from HUNYUAN service\n- Default: -\n- Example: `xxxxxx...xxxxxx`\n\n### `HUNYUAN_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+hunyuan-lite,+hunyuan-standard`\n\n## Volcengine\n\n### `VOLCENGINE_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied from Volcengine service, you can check it out [here](https://console.volcengine.com/ark/region:ark+cn-beijing/endpoint)\n- Default: -\n- Example: `ad925b3d-aaaa-bbbb-cccc-51fde2f50547`\n\n### `VOLCENGINE_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name->deploymentName=display_name` to customize the display name of a model, separated by commas. The deploymentName `->deploymentName` can be omitted, and it defaults to the latest model version. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+deepseek-r1,+deepseek-v3->deepseek-v3-250324,+doubao-1.5-pro-256k,+doubao-1.5-pro-32k->doubao-1-5-pro-32k-250115,+doubao-1.5-lite-32k`\n\n### `VOLCENGINE_PROXY_URL`\n\n- Type: Optional\n- Description: If you manually configure the Volcengine API proxy, you can use this configuration item to override the default Volcengine API request base URL\n- Default: `https://ark.cn-beijing.volces.com/api/v3`\n- Example: `https://my-volcengine-proxy.com/v1`\n\n## InfiniAI\n\n### `INFINIAI_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied from Infini-AI, you can check it out [here](https://cloud.infini-ai.com)\n- Default: -\n- Example: `sk-xxxxxx...xxxxxx`\n\n### `INFINIAI_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the model list, use `+` to add a model, use `-` to hide a model, use `model_name=display_name` to customize the display name of a model, separated by commas. Definition syntax rules see [model-list][model-list]\n- Default: `-`\n- Example: `-all,+qwq-32b,+deepseek-r1`\n\n## FAL\n\n### `ENABLED_FAL`\n\n- Type: Optional\n- Description: Enables FAL as a model provider by default. Set to `0` to disable the FAL service.\n- Default: `1`\n- Example: `0`\n\n### `FAL_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the FAL service.\n- Default: -\n- Example: `fal-xxxxxx...xxxxxx`\n\n### `FAL_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the FAL model list. Use `+` to add a model, `-` to hide a model, and `model_name=display_name` to customize the display name of a model. Separate multiple entries with commas. The definition syntax follows the same rules as other providers' model lists.\n- Default: `-`\n- Example: `-all,+fal-ai/flux/schnell,+fal-ai/flux-pro/kontext=FLUX.1 Kontext [pro]`\n\nThe above example disables all models first, then enables `fal-ai/flux/schnell` and `fal-ai/flux-pro/kontext` (displayed as `FLUX.1 Kontext [pro]`).\n\n## ComfyUI\n\n### `ENABLED_COMFYUI`\n\n- Type: Optional\n- Description: Enables ComfyUI as a model provider by default. Set to `0` to disable the ComfyUI service.\n- Default: `1`\n- Example: `0`\n\n### `COMFYUI_BASE_URL`\n\n- Type: Optional\n- Description: The base URL address of the ComfyUI service\n- Default: `http://localhost:8188`\n- Example: `http://192.168.1.100:8188` or `https://my-comfyui-server.com`\n\n### `COMFYUI_AUTH_TYPE`\n\n- Type: Optional\n- Description: The authentication type for ComfyUI, supporting 4 authentication methods\n - `none`: No authentication (default)\n - `basic`: Basic authentication (username + password)\n - `bearer`: Bearer Token authentication (API key)\n - `custom`: Custom request header authentication\n- Default: `none`\n- Example: `basic`\n\n### `COMFYUI_API_KEY`\n\n- Type: Optional\n- Description: The API key used when the authentication type is `bearer`\n- Default: -\n- Example: `sk-xxxxxx...xxxxxx`\n\n### `COMFYUI_USERNAME`\n\n- Type: Optional\n- Description: The username used when the authentication type is `basic`\n- Default: -\n- Example: `admin`\n\n### `COMFYUI_PASSWORD`\n\n- Type: Optional\n- Description: The password used when the authentication type is `basic`\n- Default: -\n- Example: `password123`\n\n### `COMFYUI_CUSTOM_HEADERS`\n\n- Type: Optional\n- Description: Custom request headers used when the authentication type is `custom`, requires JSON format string\n- Default: -\n- Example: `{\"X-Auth-Token\": \"your-token\", \"X-Custom-Header\": \"value\"}`\n\n<Callout type={'info'}>\n ComfyUI supports multiple authentication methods. Please choose the appropriate authentication\n type and corresponding authentication parameters according to your ComfyUI service configuration.\n If your ComfyUI service has no authentication set up, you can skip configuring\n authentication-related environment variables.\n</Callout>\n\n## BFL\n\n### `BFL_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the BFL service.\n- Default: -\n- Example: `12345678-1234-1234-1234-123456789abc`\n\n### `BFL_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the BFL model list. Use `+` to add a model, `-` to hide a model, and `model_name=display_name` to customize the display name of a model. Separate multiple entries with commas. The definition syntax follows the same rules as other providers' model lists.\n- Default: `-`\n- Example: `-all,+flux-pro-1.1,+flux-kontext-pro=FLUX.1 Kontext [pro]`\n\nThe above example disables all models first, then enables `flux-pro-1.1` and `flux-kontext-pro` (displayed as `FLUX.1 Kontext [pro]`).\n\n## NewAPI\n\n### `NEWAPI_API_KEY`\n\n- Type: Optional\n- Description: This is the API key for your NewAPI service instance. NewAPI is a multi-provider model aggregation service that provides unified access to various AI model APIs.\n- Default: -\n- Example: `sk-xxxxxx...xxxxxx`\n\n### `NEWAPI_PROXY_URL`\n\n- Type: Optional\n- Description: The base URL for your NewAPI server instance. This should point to your deployed NewAPI service endpoint.\n- Default: -\n- Example: `https://your-newapi-server.com/`\n\nNewAPI is a multi-provider model aggregation service that supports automatic model routing based on provider detection. It offers cost management features and provides a single endpoint for accessing models from multiple providers including OpenAI, Anthropic, Google, and more. Learn more about NewAPI at [https://github.com/Calcium-Ion/new-api](https://github.com/Calcium-Ion/new-api).\n\n## Vercel AI Gateway\n\n### `VERCELAIGATEWAY_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the Vercel AI Gateway service.\n- Default: -\n- Example: `vck_xxxxxx...xxxxxx`\n\n### `VERCELAIGATEWAY_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the Vercel AI Gateway model list. Use `+` to add a model, `-` to hide a model, and `model_name=display_name` to customize the display name of a model. Separate multiple entries with commas. The definition syntax follows the same rules as other providers' model lists.\n- Default: `-`\n- Example: `-all,+vercel-model-1,+vercel-model-2=vercel-special`\n\n## Cerebras\n\n### `CEREBRAS_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the Cerebras service.\n- Default: -\n- Example: `csk-xxxxxx...xxxxxx`\n\n### `CEREBRAS_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the Cerebras model list. Use `+` to add a model, `-` to hide a model, and `model_name=display_name` to customize the display name of a model. Separate multiple entries with commas. The definition syntax follows the same rules as other providers' model lists.\n- Default: `-`\n- Example: `-all,+cerebras-model-1,+cerebras-model-2=cerebras-special`\n\n## AiHubMix\n\n### `AIHUBMIX_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the AiHubMix service.\n- Default: -\n- Example: `sk-xxxxxx...xxxxxx`\n\n### `AIHUBMIX_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the AiHubMix model list. Use `+` to add a model, `-` to hide a model, and `model_name=display_name` to customize the display name of a model. Separate multiple entries with commas. The definition syntax follows the same rules as other providers' model lists.\n- Default: `-`\n- Example: `-all,+claude-opus-4-1-20250805,+claude-opus-4-20250514=claude-opus-4`\n\n## Straico\n\n### `STRAICO_API_KEY`\n\n- Type: Required\n- Description: This is the API key you applied for in the Straico service.\n- Default: -\n- Example: `sk-xxxxxx...xxxxxx`\n\n### `STRAICO_MODEL_LIST`\n\n- Type: Optional\n- Description: Used to control the Straico model list. Use `+` to add a model, `-` to hide a model, and `model_name=display_name` to customize the display name of a model. Separate multiple entries with commas. The definition syntax follows the same rules as other providers' model lists.\n- Default: `-`\n- Example: `-all,+straico-model-1,+straico-model-2=straico-special`\n\n[model-list]: /docs/self-hosting/advanced/model-list\n"}}, "lobehub/.env.example": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785595582.0211868, "n": 13105, "h": "80727bb468878cd4", "c": "# Specify your API Key selection method, currently supporting `random` and `turn`.\n# API_KEY_SELECT_MODE=random\n\n# #######################################\n# ########## Security Settings ###########\n# #######################################\n\n# Control Content Security Policy headers\n# Set to '1' to enable X-Frame-Options and Content-Security-Policy headers\n# Default is '0' (enabled)\n# ENABLED_CSP=1\n\n# SSRF Protection Settings\n# Set to '1' to allow connections to private IP addresses (disable SSRF protection)\n# WARNING: Only enable this in trusted environments\n# Default is '0' (SSRF protection enabled)\n# SSRF_ALLOW_PRIVATE_IP_ADDRESS=0\n\n# Whitelist of allowed private IP addresses (comma-separated)\n# Only takes effect when SSRF_ALLOW_PRIVATE_IP_ADDRESS is '0'\n# Example: Allow specific internal servers while keeping SSRF protection\n# SSRF_ALLOW_IP_ADDRESS_LIST=192.168.1.100,10.0.0.50\n\n# #######################################\n# ########### Redis Settings ############\n# #######################################\n\n# Connection string for self-hosted Redis (Docker/K8s/managed). Use container hostname when running via docker-compose.\n# REDIS_URL=redis://localhost:6379\n\n# Optional database index.\n# REDIS_DATABASE=0\n\n# Optional authentication for managed Redis.\n# REDIS_USERNAME=default\n# REDIS_PASSWORD=yourpassword\n\n# Set to '1' to enforce TLS when connecting to managed Redis or rediss:// endpoints.\n# REDIS_TLS=0\n\n# Namespace prefix for cache/queue keys.\n# REDIS_PREFIX=lobechat\n\n# #######################################\n# ######### AI Provider Service #########\n# #######################################\n\n# ## OpenAI ###\n\n# you openai api key\nOPENAI_API_KEY=sk-xxxxxxxxx\n\n# use a proxy to connect to the OpenAI API\n# OPENAI_PROXY_URL=https://api.openai.com/v1\n\n# add your custom model name, multi model separate by comma. for example gpt-3.5-1106,gpt-4-1106\n# OPENAI_MODEL_LIST=gpt-3.5-turbo\n\n\n# ## Azure OpenAI ###\n\n# you can learn azure OpenAI Service on https://learn.microsoft.com/en-us/azure/ai-services/openai/overview\n# use Azure OpenAI Service by uncomment the following line\n\n# The API key you applied for on the Azure OpenAI account page, which can be found in the \"Keys and Endpoints\" section.\n# AZURE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# The endpoint you applied for on the Azure OpenAI account page, which can be found in the \"Keys and Endpoints\" section.\n# AZURE_ENDPOINT=https://docs-test-001.openai.azure.com\n\n# Azure's API version, follows the YYYY-MM-DD format\n# AZURE_API_VERSION=2024-10-21\n\n\n# ## Anthropic Service ####\n\n# ANTHROPIC_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# use a proxy to connect to the Anthropic API\n# ANTHROPIC_PROXY_URL=https://api.anthropic.com\n\n\n# ## Google AI ####\n\n# GOOGLE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n\n# ## AWS Bedrock ###\n\n# AWS_REGION=us-east-1\n# AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxx\n# AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n\n# ## Ollama AI ####\n\n# You can use ollama to get and run LLM locally, learn more about it via https://github.com/ollama/ollama\n\n# The local/remote ollama service url\n# OLLAMA_PROXY_URL=http://127.0.0.1:11434\n\n# OLLAMA_MODEL_LIST=your_ollama_model_names\n\n\n# ## OpenRouter Service ###\n\n# OPENROUTER_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# OPENROUTER_MODEL_LIST=model1,model2,model3\n\n\n# ## Mistral AI ###\n\n# MISTRAL_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## Perplexity Service ###\n\n# PERPLEXITY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## Groq Service ####\n\n# GROQ_API_KEY=gsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ### 01.AI Service ####\n\n# ZEROONE_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## TogetherAI Service ###\n\n# TOGETHERAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## ZhiPu AI ###\n\n# ZHIPU_API_KEY=xxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxx\n\n# ## Moonshot AI ####\n\n# MOONSHOT_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## Minimax AI ####\n\n# MINIMAX_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## DeepSeek AI ####\n\n# DEEPSEEK_PROXY_URL=https://api.deepseek.com/v1\n# DEEPSEEK_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## Qiniu AI ####\n\n# QINIU_PROXY_URL=https://api.qnaigc.com/v1\n# QINIU_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## Qwen AI ####\n\n# QWEN_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## Cloudflare Workers AI ####\n\n# CLOUDFLARE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# CLOUDFLARE_BASE_URL_OR_ACCOUNT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## SiliconCloud AI ####\n\n# SILICONCLOUD_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n\n# ## TencentCloud AI ####\n\n# TENCENT_CLOUD_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## PPIO ####\n\n# PPIO_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## INFINI-AI ###\n\n# INFINIAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n\n# ## 302.AI ###\n\n# AI302_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## ModelScope ###\n\n# MODELSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## AiHubMix ###\n\n# AIHUBMIX_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## BFL ###\n\n# BFL_API_KEY=bfl-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## FAL ###\n\n# FAL_API_KEY=fal-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# #######################################\n# ######## AI Image Settings ############\n# #######################################\n\n# Default image generation count (range: 1-20, default: 4)\n# AI_IMAGE_DEFAULT_IMAGE_NUM=4\n\n# ## Nebius ###\n\n# NEBIUS_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# ## NewAPI Service ###\n\n# NEWAPI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# NEWAPI_PROXY_URL=https://your-newapi-server.com\n\n# ## Vercel AI Gateway ###\n\n# VERCELAIGATEWAY_API_KEY=your_vercel_ai_gateway_api_key\n\n\n# #######################################\n# ########### Market Service ############\n# #######################################\n\n# The LobeChat agents market index url\n# AGENTS_INDEX_URL=https://chat-agents.lobehub.com\n\n# #######################################\n# ########### Plugin Service ############\n# #######################################\n\n# The LobeChat plugins store index url\n# PLUGINS_INDEX_URL=https://chat-plugins.lobehub.com\n\n# set the plugin settings\n# the format is `plugin-identifier:key1=value1;key2=value2`, multiple settings fields are separated by semicolons `;`, multiple plugin settings are separated by commas `,`.\n# PLUGIN_SETTINGS=search-engine:SERPAPI_API_KEY=xxxxx\n\n# #######################################\n# ###### Doc / Changelog Service ########\n# #######################################\n\n# Use in Changelog / Document service cdn url prefix\n# DOC_S3_PUBLIC_DOMAIN=https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# Use in dev cdn workflow\n# DOC_S3_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# DOC_S3_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# #######################################\n# ### Mobile SPA S3 Workflow ############\n# #######################################\n\n# Used by `bun run workflow:mobile-spa` to build mobile SPA, upload assets to S3, and generate template\n# MOBILE_S3_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# MOBILE_S3_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# MOBILE_S3_BUCKET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# MOBILE_S3_ENDPOINT=https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# MOBILE_S3_REGION=auto\n# MOBILE_S3_PUBLIC_DOMAIN=https://cdn.example.com\n# MOBILE_S3_KEY_PREFIX=mobile/latest # optional, S3 key path prefix\n\n# #######################################\n# #### S3 Object Storage Service ########\n# #######################################\n\n# S3 keys\n# S3_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# S3_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# Bucket name\n# S3_BUCKET=lobechat\n\n# Bucket request endpoint\n# S3_ENDPOINT=https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.r2.cloudflarestorage.com\n\n# Bucket region, such as us-west-1, generally not needed to add\n# but some service providers may require configuration\n# S3_REGION=us-west-1\n\n\n# #######################################\n# ########### Auth Service ##############\n# #######################################\n\n# Auth Secret (use `openssl rand -base64 32` to generate)\n# AUTH_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# Require email verification before allowing users to sign in (default: false)\n# Set to '1' to force users to verify their email before signing in\n# AUTH_EMAIL_VERIFICATION=0\n\n# SSO Providers Configuration (for Better-Auth)\n# Comma-separated list of enabled OAuth providers\n# Supported providers: auth0, authelia, authentik, casdoor, cloudflare-zero-trust, cognito, generic-oidc, github, google, keycloak, logto, microsoft, microsoft-entra-id, okta, zitadel\n# Example: AUTH_SSO_PROVIDERS=google,github,auth0,microsoft-entra-id\n# AUTH_SSO_PROVIDERS=\n\n# Email whitelist for registration (comma-separated)\n# Supports full email (user@example.com) or domain (example.com)\n# Leave empty to allow all emails\n# AUTH_ALLOWED_EMAILS=example.com,admin@other.com\n\n# Disable email/password authentication (SSO-only mode)\n# Set to '1' to disable email/password sign-in and registration, only allowing SSO login\n# AUTH_DISABLE_EMAIL_PASSWORD=0\n\n# Google OAuth Configuration (for Better-Auth)\n# Get credentials from: https://console.cloud.google.com/apis/credentials\n# Authorized redirect URIs:\n# - Development: http://localhost:3210/api/auth/callback/google\n# - Production: https://yourdomain.com/api/auth/callback/google\n# GOOGLE_CLIENT_ID=xxxxx.apps.googleusercontent.com\n# GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxxxxxxx\n\n# GitHub OAuth Configuration (for Better-Auth)\n# Get credentials from: https://github.com/settings/developers\n# Create a new OAuth App with:\n# Authorized callback URL:\n# - Development: http://localhost:3210/api/auth/callback/github\n# - Production: https://yourdomain.com/api/auth/callback/github\n# GITHUB_CLIENT_ID=Ov23xxxxxxxxxxxxx\n# GITHUB_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# AWS Cognito OAuth Configuration (for Better-Auth)\n# Get credentials from: https://console.aws.amazon.com/cognito\n# Setup steps:\n# 1. Create a User Pool with App Client\n# 2. Configure Hosted UI domain\n# 3. Enable \"Authorization code grant\" OAuth flow\n# 4. Set OAuth scopes: openid, profile, email\n# Authorized callback URL:\n# - Development: http://localhost:3210/api/auth/callback/cognito\n# - Production: https://yourdomain.com/api/auth/callback/cognito\n# COGNITO_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxx\n# COGNITO_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n# COGNITO_DOMAIN=your-app.auth.us-east-1.amazoncognito.com\n# COGNITO_REGION=us-east-1\n# COGNITO_USERPOOL_ID=us-east-1_xxxxxxxxx\n\n# Microsoft OAuth Configuration (for Better-Auth)\n# Get credentials from: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade\n# Create a new App Registration in Microsoft Entra ID (Azure AD)\n# Authorized redirect URL:\n# - Development: http://localhost:3210/api/auth/callback/microsoft\n# - Production: https://yourdomain.com/api/auth/callback/microsoft\n# MICROSOFT_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n# MICROSOFT_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n# #######################################\n# ########## Email Service ##############\n# #######################################\n\n# SMTP Server Configuration (required for email verification with Better-Auth)\n\n# SMTP server hostname (e.g., smtp.gmail.com, smtp.office365.com)\n# SMTP_HOST=smtp.example.com\n\n# SMTP server port (usually 587 for TLS, or 465 for SSL)\n# SMTP_PORT=587\n\n# Use secure connection (set to 'true' for port 465, 'false' for port 587)\n# SMTP_SECURE=false\n\n# SMTP authentication username (usually your email address)\n# SMTP_USER=your-email@example.com\n\n# SMTP authentication password (use app-specific password for Gmail)\n# SMTP_PASS=your-password-or-app-specific-password\n\n# Sender email address (optional, defaults to SMTP_USER)\n# Required for AWS SES where SMTP_USER is not a valid email address\n# SMTP_FROM=noreply@example.com\n\n# #######################################\n# ######### Server Database #############\n# #######################################\n\n# Postgres database URL\n# DATABASE_URL=postgres://username:password@host:port/database\n\n# use `openssl rand -base64 32` to generate a key for the encryption of the database\n# we use this key to encrypt the user api key and proxy url\n# KEY_VAULTS_SECRET=xxxxx/xxxxxxxxxxxxxx=\n\n# Specify the Embedding model and Reranker model(unImplemented)\n# DEFAULT_FILES_CONFIG=\"embedding_model=openai/embedding-text-3-small,reranker_model=cohere/rerank-english-v3.0,query_mode=full_text\"\n\n# Embedding batch size for processing (default: 50)\n# EMBEDDING_BATCH_SIZE=50\n\n# Embedding concurrency for parallel processing (default: 10)\n# EMBEDDING_CONCURRENCY=10\n\n# #######################################\n# ######### MCP Service Config ##########\n# #######################################\n\n# MCP tool call timeout (milliseconds)\n# MCP_TOOL_TIMEOUT=60000\n\n# #######################################\n# ######### Klavis Service ##############\n# #######################################\n\n# Klavis API Key for accessing Strata hosted MCP servers\n# Get your API key from: https://klavis.io\n# IMPORTANT: This key is stored server-side only and NEVER exposed to the client\n# When this key is set, Klavis integration will be automatically enabled\n# KLAVIS_API_KEY=your_klavis_api_key_here\n"}}, "lobehub/packages/model-runtime/src/providers/ai360/index.test.ts": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785809835.4428651, "n": 37882, "h": "42ae92f0bcba4815", "c": "// @vitest-environment node\nimport { ModelProvider } from 'model-bank';\nimport { beforeEach, describe, expect, it, vi } from 'vitest';\n\nimport { testProvider } from '../../providerTestUtils';\nimport { LobeAi360AI, params } from './index';\n\ntestProvider({\n Runtime: LobeAi360AI,\n provider: ModelProvider.Ai360,\n defaultBaseURL: 'https://api.360.cn/v1',\n chatDebugEnv: 'DEBUG_AI360_CHAT_COMPLETION',\n chatModel: 'deepseek-r1',\n invalidErrorType: 'InvalidProviderAPIKey',\n bizErrorType: 'ProviderBizError',\n test: {\n skipAPICall: true,\n skipErrorHandle: true,\n },\n});\n\ndescribe('LobeAi360AI - custom features', () => {\n let instance: InstanceType<typeof LobeAi360AI>;\n\n beforeEach(() => {\n instance = new LobeAi360AI({ apiKey: 'test_api_key' });\n vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue(\n new ReadableStream() as any,\n );\n });\n\n describe('params.debug', () => {\n it('should disable debug mode by default', () => {\n delete process.env.DEBUG_AI360_CHAT_COMPLETION;\n const result = params.debug.chatCompletion();\n expect(result).toBe(false);\n });\n\n it('should enable debug mode when DEBUG_AI360_CHAT_COMPLETION is set to 1', () => {\n process.env.DEBUG_AI360_CHAT_COMPLETION = '1';\n const result = params.debug.chatCompletion();\n expect(result).toBe(true);\n delete process.env.DEBUG_AI360_CHAT_COMPLETION;\n });\n\n it('should disable debug mode when DEBUG_AI360_CHAT_COMPLETION is not 1', () => {\n process.env.DEBUG_AI360_CHAT_COMPLETION = '0';\n const result = params.debug.chatCompletion();\n expect(result).toBe(false);\n delete process.env.DEBUG_AI360_CHAT_COMPLETION;\n });\n });\n\n describe('params.chatCompletion.handlePayload', () => {\n it('should add web_search tool when enabledSearch is true', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: true,\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.tools).toBeDefined();\n expect(result.tools?.some((tool: any) => tool.type === 'web_search')).toBe(true);\n expect(result.tools?.find((tool: any) => tool.type === 'web_search')).toEqual({\n type: 'web_search',\n web_search: {\n search_mode: 'auto',\n },\n });\n });\n\n it('should correctly set web_search properties', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: true,\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n const webSearchTool = result.tools?.find((tool: any) => tool.type === 'web_search');\n\n expect(webSearchTool).toBeDefined();\n expect(webSearchTool.type).toBe('web_search');\n expect(webSearchTool.web_search).toBeDefined();\n expect(webSearchTool.web_search.search_mode).toBe('auto');\n });\n\n it('should not add web_search tool when enabledSearch is false', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: false,\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.tools).toBeUndefined();\n });\n\n it('should not add web_search tool when enabledSearch is not present', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.tools).toBeUndefined();\n });\n\n it('should disable stream when tools are present', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n tools: [{ type: 'function', function: { name: 'test' } }],\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.stream).toBe(false);\n });\n\n it('should disable stream when enabledSearch is true', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: true,\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.stream).toBe(false);\n });\n\n it('should not set stream to false when no tools', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.stream).not.toBe(false);\n });\n\n it('should merge tools with web_search when enabledSearch is true', () => {\n const existingTool = { type: 'function', function: { name: 'existing_tool' } };\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: true,\n tools: [existingTool],\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.tools).toHaveLength(2);\n expect(result.tools).toContainEqual(existingTool);\n expect(result.tools?.some((tool: any) => tool.type === 'web_search')).toBe(true);\n });\n\n it('should remove enabledSearch from payload', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: true,\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.enabledSearch).toBeUndefined();\n });\n\n it('should preserve other payload properties', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n temperature: 0.7,\n max_tokens: 1024,\n top_p: 0.9,\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.messages).toEqual(payload.messages);\n expect(result.model).toBe(payload.model);\n expect(result.temperature).toBe(payload.temperature);\n expect(result.max_tokens).toBe(payload.max_tokens);\n expect(result.top_p).toBe(payload.top_p);\n });\n\n it('should handle empty tools array when enabledSearch is true', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: true,\n tools: [],\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.tools).toHaveLength(1);\n expect(result.tools?.[0].type).toBe('web_search');\n });\n\n it('should handle multiple existing tools when enabledSearch is true', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: true,\n tools: [\n { type: 'function', function: { name: 'tool1' } },\n { type: 'function', function: { name: 'tool2' } },\n ],\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n\n expect(result.tools).toHaveLength(3);\n expect(result.tools?.[0].function.name).toBe('tool1');\n expect(result.tools?.[1].function.name).toBe('tool2');\n expect(result.tools?.[2].type).toBe('web_search');\n });\n });\n\n describe('params.models', () => {\n it('should fetch and process models successfully', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt-pro',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n {\n id: '360gpt2-o1',\n max_tokens: 8192,\n total_tokens: 16384,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n\n expect(models).toHaveLength(2);\n expect(mockClient.models.list).toHaveBeenCalled();\n });\n\n it('should correctly map model properties', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt-pro',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.id).toBe('360gpt-pro');\n expect(model.contextWindowTokens).toBe(8192);\n expect(model.maxOutput).toBe(4096);\n });\n\n it('should detect 360gpt-pro as function call capable', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt-pro',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.functionCall).toBe(true);\n });\n\n it('should detect reasoning models with 360gpt2-o1 keyword', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt2-o1',\n max_tokens: 8192,\n total_tokens: 16384,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.reasoning).toBe(true);\n });\n\n it('should detect reasoning models with 360zhinao2-o1 keyword', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360zhinao2-o1-preview',\n max_tokens: 8192,\n total_tokens: 16384,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.reasoning).toBe(true);\n });\n\n it('should handle case-insensitive reasoning keyword matching', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360GPT2-O1',\n max_tokens: 8192,\n total_tokens: 16384,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.reasoning).toBe(true);\n });\n\n it('should merge with LOBE_DEFAULT_MODEL_LIST for known models', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt-pro',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n // Known models from LOBE_DEFAULT_MODEL_LIST should have displayName and enabled flag\n expect(model.displayName).toBeDefined();\n expect(model.enabled).toBeDefined();\n });\n\n it('should handle models not in LOBE_DEFAULT_MODEL_LIST', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: 'unknown-model',\n max_tokens: 2048,\n total_tokens: 4096,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.id).toBe('unknown-model');\n expect(model.displayName).toBeUndefined();\n expect(model.enabled).toBe(false);\n });\n\n it('should inherit abilities from LOBE_DEFAULT_MODEL_LIST', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt-pro',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n // Check that abilities are inherited from known model\n expect(typeof model.functionCall).toBe('boolean');\n expect(typeof model.vision).toBe('boolean');\n expect(typeof model.reasoning).toBe('boolean');\n });\n\n it('should handle models with non-number max_tokens', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: 'test-model',\n max_tokens: 'unlimited' as any,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.maxOutput).toBeUndefined();\n });\n\n it('should handle models with null max_tokens', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: 'test-model',\n max_tokens: null as any,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.maxOutput).toBeUndefined();\n });\n\n it('should handle empty model list', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n\n expect(models).toEqual([]);\n });\n\n it('should handle model list with valid models only', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: 'model1',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n {\n id: 'model2',\n max_tokens: 2048,\n total_tokens: 4096,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n\n expect(models).toHaveLength(2);\n expect(models.every((m) => m !== null && m.id)).toBe(true);\n });\n\n it('should handle API errors gracefully', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockRejectedValue(new Error('API Error')),\n },\n };\n\n await expect(params.models!({ client: mockClient as any })).rejects.toThrow('API Error');\n });\n\n it('should set reasoning to false for non-reasoning models', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt-base',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.reasoning).toBe(false);\n });\n\n it('should set functionCall to false for non-360gpt-pro models without functionCall ability', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: 'test-model',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.functionCall).toBe(false);\n });\n\n it('should set vision to false for models without vision ability', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: 'test-model',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.vision).toBe(false);\n });\n\n it('should handle case-insensitive model ID matching with LOBE_DEFAULT_MODEL_LIST', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360GPT-PRO',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n // Should match case-insensitively with LOBE_DEFAULT_MODEL_LIST\n expect(model.id).toBe('360GPT-PRO');\n expect(model.displayName).toBeDefined();\n });\n\n it('should handle models with all properties present', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt-pro',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model).toHaveProperty('id');\n expect(model).toHaveProperty('contextWindowTokens');\n expect(model).toHaveProperty('maxOutput');\n expect(model).toHaveProperty('functionCall');\n expect(model).toHaveProperty('vision');\n expect(model).toHaveProperty('reasoning');\n expect(model).toHaveProperty('enabled');\n });\n\n it('should detect all reasoning model variants correctly', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt2-o1',\n max_tokens: 8192,\n total_tokens: 16384,\n },\n {\n id: '360gpt2-o1-preview',\n max_tokens: 8192,\n total_tokens: 16384,\n },\n {\n id: '360zhinao2-o1',\n max_tokens: 8192,\n total_tokens: 16384,\n },\n {\n id: '360zhinao2-o1-mini',\n max_tokens: 8192,\n total_tokens: 16384,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n\n expect(models).toHaveLength(4);\n expect(models.every((m) => m.reasoning === true)).toBe(true);\n });\n\n it('should handle models with zero context window', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: 'test-model',\n max_tokens: 0,\n total_tokens: 0,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.contextWindowTokens).toBe(0);\n expect(model.maxOutput).toBe(0);\n });\n\n it('should handle very large context window values', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: 'large-context-model',\n max_tokens: 128000,\n total_tokens: 1000000,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.contextWindowTokens).toBe(1000000);\n expect(model.maxOutput).toBe(128000);\n });\n\n it('should handle models with special characters in ID', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt-pro-v2.0-beta',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.id).toBe('360gpt-pro-v2.0-beta');\n });\n\n it('should detect 360gpt-pro as functionCall capable', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt-pro',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.id).toBe('360gpt-pro');\n expect(model.functionCall).toBe(true);\n });\n\n it('should prioritize reasoning from keyword over knownModel', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt2-o1-custom',\n max_tokens: 8192,\n total_tokens: 16384,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n // Should detect reasoning from keyword even if not in LOBE_DEFAULT_MODEL_LIST\n expect(model.reasoning).toBe(true);\n });\n\n it('should prioritize functionCall from model ID check over knownModel', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt-pro',\n max_tokens: 4096,\n total_tokens: 8192,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.functionCall).toBe(true);\n });\n\n it('should merge multiple capabilities correctly', async () => {\n const mockClient = {\n models: {\n list: vi.fn().mockResolvedValue({\n data: [\n {\n id: '360gpt2-o1',\n max_tokens: 8192,\n total_tokens: 16384,\n },\n ],\n }),\n },\n };\n\n const models = await params.models!({ client: mockClient as any });\n const model = models[0];\n\n expect(model.reasoning).toBe(true);\n expect(typeof model.functionCall).toBe('boolean');\n expect(typeof model.vision).toBe('boolean');\n });\n });\n\n describe('LobeAi360AI instance - integration tests', () => {\n it('should add web_search tool when enabledSearch is true', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: true,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.tools).toBeDefined();\n expect(calledPayload.tools?.some((tool: any) => tool.type === 'web_search')).toBe(true);\n });\n\n it('should disable stream when tools are present', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n tools: [{ type: 'function', function: { name: 'test' } }],\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.stream).toBe(false);\n });\n\n it('should enable stream when no tools', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.stream).not.toBe(false);\n });\n\n it('should merge tools with web_search when enabledSearch is true', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: true,\n tools: [{ type: 'function', function: { name: 'existing_tool' } }],\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.tools).toHaveLength(2);\n expect(calledPayload.tools?.some((tool: any) => tool.type === 'function')).toBe(true);\n expect(calledPayload.tools?.some((tool: any) => tool.type === 'web_search')).toBe(true);\n });\n\n it('should preserve temperature without normalization', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n temperature: 0.7,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.temperature).toBe(0.7);\n });\n\n it('should preserve top_p without modification', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n top_p: 0.9,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.top_p).toBe(0.9);\n });\n\n it('should preserve max_tokens without modification', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n max_tokens: 1024,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.max_tokens).toBe(1024);\n });\n\n it('should preserve messages as-is', async () => {\n const messages = [\n { content: 'Hello', role: 'user' as const },\n { content: 'Hi there!', role: 'assistant' as const },\n { content: 'How are you?', role: 'user' as const },\n ];\n\n await instance.chat({\n messages,\n model: '360gpt-pro',\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.messages).toEqual(messages);\n });\n\n it('should preserve model name', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt2-o1',\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.model).toBe('360gpt2-o1');\n });\n\n it('should handle combined parameters correctly', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n temperature: 0.8,\n top_p: 0.85,\n max_tokens: 2048,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.model).toBe('360gpt-pro');\n expect(calledPayload.temperature).toBe(0.8);\n expect(calledPayload.top_p).toBe(0.85);\n expect(calledPayload.max_tokens).toBe(2048);\n });\n\n it('should not include undefined parameters in payload', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n });\n\n const callArgs = vi.mocked(instance['client'].chat.completions.create).mock.calls[0][0];\n expect(callArgs).not.toHaveProperty('temperature');\n expect(callArgs).not.toHaveProperty('top_p');\n expect(callArgs).not.toHaveProperty('max_tokens');\n });\n });\n\n describe('exports', () => {\n it('should export params object', () => {\n expect(params).toBeDefined();\n expect(params.provider).toBe(ModelProvider.Ai360);\n expect(params.baseURL).toBe('https://api.360.cn/v1');\n });\n\n it('should export LobeAi360AI class', () => {\n expect(LobeAi360AI).toBeDefined();\n expect(typeof LobeAi360AI).toBe('function');\n });\n\n it('should export params with all required properties', () => {\n expect(params).toHaveProperty('provider');\n expect(params).toHaveProperty('baseURL');\n expect(params).toHaveProperty('chatCompletion');\n expect(params).toHaveProperty('debug');\n expect(params).toHaveProperty('models');\n });\n\n it('should have chatCompletion.handlePayload function', () => {\n expect(params.chatCompletion).toBeDefined();\n expect(params.chatCompletion.handlePayload).toBeDefined();\n expect(typeof params.chatCompletion.handlePayload).toBe('function');\n });\n\n it('should have debug.chatCompletion function', () => {\n expect(params.debug).toBeDefined();\n expect(params.debug.chatCompletion).toBeDefined();\n expect(typeof params.debug.chatCompletion).toBe('function');\n });\n\n it('should have models function', () => {\n expect(params.models).toBeDefined();\n expect(typeof params.models).toBe('function');\n });\n });\n\n describe('edge cases and comprehensive coverage', () => {\n it('should handle payload with undefined tools', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n tools: undefined,\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n expect(result.tools).toBeUndefined();\n });\n\n it('should handle payload with null tools', () => {\n const payload = {\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n tools: null as any,\n } as any;\n\n const result = params.chatCompletion.handlePayload!(payload);\n expect(result.tools).toBeNull();\n });\n\n it('should handle empty messages array', async () => {\n await instance.chat({\n messages: [],\n model: '360gpt-pro',\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.messages).toEqual([]);\n });\n\n it('should handle very small temperature values', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n temperature: 0.01,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.temperature).toBe(0.01);\n });\n\n it('should handle temperature of 0', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n temperature: 0,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.temperature).toBe(0);\n });\n\n it('should handle temperature of 1', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n temperature: 1,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.temperature).toBe(1);\n });\n\n it('should handle high temperature values', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n temperature: 2,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.temperature).toBe(2);\n });\n\n it('should handle top_p of 0', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n top_p: 0,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.top_p).toBe(0);\n });\n\n it('should handle top_p of 1', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n top_p: 1,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.top_p).toBe(1);\n });\n\n it('should handle very small top_p values', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n top_p: 0.01,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.top_p).toBe(0.01);\n });\n\n it('should handle large max_tokens values', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n max_tokens: 100000,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.max_tokens).toBe(100000);\n });\n\n it('should handle complex message history with multiple roles', async () => {\n const messages = [\n { content: 'You are a helpful assistant', role: 'system' as const },\n { content: 'Hello', role: 'user' as const },\n { content: 'Hi! How can I help?', role: 'assistant' as const },\n { content: 'What is 2+2?', role: 'user' as const },\n { content: '2+2 equals 4', role: 'assistant' as const },\n { content: 'Thanks', role: 'user' as const },\n ];\n\n await instance.chat({\n messages,\n model: '360gpt-pro',\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.messages).toEqual(messages);\n });\n\n it('should handle combined parameters with web search', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n temperature: 0.8,\n top_p: 0.85,\n max_tokens: 2048,\n enabledSearch: true,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.temperature).toBe(0.8);\n expect(calledPayload.top_p).toBe(0.85);\n expect(calledPayload.max_tokens).toBe(2048);\n expect(calledPayload.stream).toBe(false);\n expect(calledPayload.tools?.some((tool: any) => tool.type === 'web_search')).toBe(true);\n });\n\n it('should handle combined parameters with tools and no web search', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n temperature: 0.9,\n top_p: 0.95,\n max_tokens: 4096,\n tools: [{ type: 'function', function: { name: 'test_tool' } }],\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.temperature).toBe(0.9);\n expect(calledPayload.top_p).toBe(0.95);\n expect(calledPayload.max_tokens).toBe(4096);\n expect(calledPayload.stream).toBe(false);\n expect(calledPayload.tools).toHaveLength(1);\n });\n\n it('should preserve all model parameters', async () => {\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360zhinao2-o1-preview',\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.model).toBe('360zhinao2-o1-preview');\n });\n\n it('should handle multiple function tools', async () => {\n const tools = [\n { type: 'function' as const, function: { name: 'tool1', description: 'First tool' } },\n { type: 'function' as const, function: { name: 'tool2', description: 'Second tool' } },\n { type: 'function' as const, function: { name: 'tool3', description: 'Third tool' } },\n ];\n\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n tools,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.tools).toHaveLength(3);\n expect(calledPayload.stream).toBe(false);\n });\n\n it('should handle enabledSearch with multiple function tools', async () => {\n const tools = [\n { type: 'function' as const, function: { name: 'tool1', description: 'First tool' } },\n { type: 'function' as const, function: { name: 'tool2', description: 'Second tool' } },\n ];\n\n await instance.chat({\n messages: [{ content: 'Hello', role: 'user' }],\n model: '360gpt-pro',\n enabledSearch: true,\n tools,\n });\n\n const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];\n expect(calledPayload.tools).toHaveLength(3);\n expect(calledPayload.tools?.filter((t: any) => t.type === 'function')).toHaveLength(2);\n expect(calledPayload.tools?.filter((t: any) => t.type === 'web_search')).toHaveLength(1);\n expect(calledPayload.stream).toBe(false);\n });\n });\n});\n"}}, "lobehub/packages/model-bank/src/modelProviders/sensenova.ts": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785809866.3273811, "n": 816, "h": "e17490466b5d2702", "c": "import type { ModelProviderCard } from '@/types/llm';\n\n// ref https://platform.sensenova.cn/pricing\n// ref https://platform.sensenova.cn/release?path=/release-202409.md\nconst SenseNova: ModelProviderCard = {\n chatModels: [],\n checkModel: 'SenseChat-Turbo',\n description:\n 'SenseNova delivers efficient, easy-to-use full-stack LLM services backed by SenseTime infrastructure.',\n disableBrowserRequest: true,\n id: 'sensenova',\n modelList: { showModelFetcher: true },\n modelsUrl: 'https://platform.sensenova.cn/pricing',\n name: 'SenseNova',\n settings: {\n disableBrowserRequest: true,\n proxyUrl: {\n placeholder: 'https://api.sensenova.cn/compatible-mode/v2',\n },\n sdkType: 'openai',\n showModelFetcher: true,\n },\n url: 'https://platform.sensenova.cn/home',\n};\n\nexport default SenseNova;\n"}}, "lobehub/packages/model-runtime/src/providers/tencentcloud/index.ts": {"c32ae54d58f1c231eb6c6061ffced785bd0c7216": {"t": 1785846964.6006067, "n": 1725, "h": "1f9b36b00e1a6443", "c": "import type { ChatModelCard } from '@lobechat/types';\nimport { ModelProvider } from 'model-bank';\n\nimport type { OpenAICompatibleFactoryOptions } from '../../core/openaiCompatibleFactory';\nimport { createOpenAICompatibleRuntime } from '../../core/openaiCompatibleFactory';\n\nexport interface TencentCloudModelCard {\n id: string;\n}\n\nexport const params = {\n baseURL: 'https://api.lkeap.cloud.tencent.com/v1',\n debug: {\n chatCompletion: () => process.env.DEBUG_TENCENT_CLOUD_CHAT_COMPLETION === '1',\n },\n models: async ({ client }) => {\n const { LOBE_DEFAULT_MODEL_LIST } = await import('model-bank');\n\n const reasoningKeywords = ['deepseek-r1'];\n\n const modelsPage = (await client.models.list()) as any;\n const modelList: TencentCloudModelCard[] = modelsPage.data;\n\n return modelList\n .map((model) => {\n const knownModel = LOBE_DEFAULT_MODEL_LIST.find(\n (m) => model.id.toLowerCase() === m.id.toLowerCase(),\n );\n\n return {\n contextWindowTokens: knownModel?.contextWindowTokens ?? undefined,\n displayName: knownModel?.displayName ?? undefined,\n enabled: knownModel?.enabled || false,\n functionCall: knownModel?.abilities?.functionCall || false,\n id: model.id,\n reasoning:\n reasoningKeywords.some((keyword) => model.id.toLowerCase().includes(keyword)) ||\n knownModel?.abilities?.reasoning ||\n false,\n vision: knownModel?.abilities?.vision || false,\n };\n })\n .filter(Boolean) as ChatModelCard[];\n },\n provider: ModelProvider.TencentCloud,\n} satisfies OpenAICompatibleFactoryOptions;\n\nexport const LobeTencentCloudAI = createOpenAICompatibleRuntime(params);\n"}}}}