{"repo": "anbeime/ai-trend-publish", "files": {"src/providers/llm/xunfei-llm.ts": {"446fe1f04703c94c556469893a7ab362570f4639": {"t": 1785768232.832607, "n": 4225, "h": "0433f25f5070abf3", "c": "import { ConfigManager } from \"@src/utils/config/config-manager.ts\";\nimport { HttpClient } from \"@src/utils/http/http-client.ts\";\nimport {\n ChatCompletionOptions,\n ChatMessage,\n LLMProvider,\n} from \"@src/providers/interfaces/llm.interface.ts\";\n\ninterface XunfeiMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\ninterface XunfeiResponse {\n code: number;\n message: string;\n sid: string;\n choices: {\n message: {\n role: \"assistant\" | \"user\";\n content: string;\n };\n index: number;\n }[];\n usage: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\n/**\n * 讯飞星火大模型API适配器\n */\nexport class XunfeiLLM implements LLMProvider {\n private baseURL = \"https://spark-api-open.xf-yun.com/v1/chat/completions\";\n private token!: string;\n private defaultModel = \"4.0Ultra\";\n private httpClient: HttpClient;\n\n constructor(\n private configManager: ConfigManager = ConfigManager.getInstance(),\n ) {\n this.httpClient = HttpClient.getInstance();\n }\n\n async initialize(): Promise {\n await this.refresh();\n }\n\n async setModel(model: string): Promise {\n this.defaultModel = model\n }\n\n async refresh(): Promise {\n this.token = await this.configManager.get(\"XUNFEI_API_KEY\");\n if (!this.token) {\n throw new Error(\"讯飞API密钥未设置\");\n }\n\n // 检查API服务是否可用\n const isHealthy = await this.httpClient.healthCheck(\n \"https://spark-api-open.xf-yun.com\",\n );\n if (!isHealthy) {\n console.warn(\"警告: 讯飞API服务健康检查失败,可能无法正常访问\");\n }\n }\n\n /**\n * 创建聊天完成\n * @param messages 消息数组\n * @param options 可选参数\n * @returns 聊天完成响应\n */\n async createChatCompletion(\n messages: ChatMessage[],\n options: ChatCompletionOptions = {},\n ): Promise {\n try {\n const xunfeiMessages: XunfeiMessage[] = messages.map((msg) => ({\n role: msg.role,\n content: msg.content,\n }));\n\n const enableWebSearch = options.stream === undefined\n ? false\n : options.stream;\n\n const response = await this.httpClient.request(\n this.baseURL,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${this.token}`,\n },\n body: JSON.stringify({\n model: this.defaultModel,\n messages: xunfeiMessages,\n stream: false,\n ...(enableWebSearch && {\n tools: [\n {\n type: \"web_search\",\n web_search: {\n enable: true,\n },\n },\n ],\n }),\n }),\n timeout: 60000, // 60秒超时\n retries: 3, // 最多重试3次\n retryDelay: 1000, // 重试间隔1秒\n },\n );\n\n if (response.code !== 0) {\n throw new Error(`API错误: ${response.message}`);\n }\n\n if (!response.choices || response.choices.length === 0) {\n throw new Error(\"没有可用的响应选项\");\n }\n\n // 转换为标准格式返回\n return {\n id: response.sid,\n object: \"chat.completion\",\n created: Date.now(),\n model: this.defaultModel,\n choices: response.choices.map((choice) => ({\n index: choice.index,\n message: {\n role: choice.message.role,\n content: choice.message.content,\n },\n finish_reason: \"stop\",\n })),\n usage: response.usage,\n };\n } catch (error) {\n throw new Error(`创建聊天完成失败: ${(error as Error).message}`);\n }\n }\n\n /**\n * 发送单条消息并获取响应(便捷方法)\n * @param content 消息内容\n * @param systemPrompt 可选的系统提示\n * @param enableWebSearch 是否启用网络搜索\n * @returns 助手的响应文本\n */\n async sendMessage(\n content: string,\n systemPrompt?: string,\n enableWebSearch?: boolean,\n ): Promise {\n const messages: ChatMessage[] = [];\n\n if (systemPrompt) {\n messages.push({\n role: \"system\",\n content: systemPrompt,\n });\n }\n\n messages.push({\n role: \"user\",\n content,\n });\n\n const response = await this.createChatCompletion(messages, {\n stream: enableWebSearch,\n });\n\n return response.choices[0].message.content;\n }\n}\n"}, "62c1db331bf09bb7fe2d1a30be9e95313a80d4c2": {"t": 1785846970.1463294, "n": 4225, "h": "0433f25f5070abf3", "c": "import { ConfigManager } from \"@src/utils/config/config-manager.ts\";\nimport { HttpClient } from \"@src/utils/http/http-client.ts\";\nimport {\n ChatCompletionOptions,\n ChatMessage,\n LLMProvider,\n} from \"@src/providers/interfaces/llm.interface.ts\";\n\ninterface XunfeiMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\ninterface XunfeiResponse {\n code: number;\n message: string;\n sid: string;\n choices: {\n message: {\n role: \"assistant\" | \"user\";\n content: string;\n };\n index: number;\n }[];\n usage: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\n/**\n * 讯飞星火大模型API适配器\n */\nexport class XunfeiLLM implements LLMProvider {\n private baseURL = \"https://spark-api-open.xf-yun.com/v1/chat/completions\";\n private token!: string;\n private defaultModel = \"4.0Ultra\";\n private httpClient: HttpClient;\n\n constructor(\n private configManager: ConfigManager = ConfigManager.getInstance(),\n ) {\n this.httpClient = HttpClient.getInstance();\n }\n\n async initialize(): Promise {\n await this.refresh();\n }\n\n async setModel(model: string): Promise {\n this.defaultModel = model\n }\n\n async refresh(): Promise {\n this.token = await this.configManager.get(\"XUNFEI_API_KEY\");\n if (!this.token) {\n throw new Error(\"讯飞API密钥未设置\");\n }\n\n // 检查API服务是否可用\n const isHealthy = await this.httpClient.healthCheck(\n \"https://spark-api-open.xf-yun.com\",\n );\n if (!isHealthy) {\n console.warn(\"警告: 讯飞API服务健康检查失败,可能无法正常访问\");\n }\n }\n\n /**\n * 创建聊天完成\n * @param messages 消息数组\n * @param options 可选参数\n * @returns 聊天完成响应\n */\n async createChatCompletion(\n messages: ChatMessage[],\n options: ChatCompletionOptions = {},\n ): Promise {\n try {\n const xunfeiMessages: XunfeiMessage[] = messages.map((msg) => ({\n role: msg.role,\n content: msg.content,\n }));\n\n const enableWebSearch = options.stream === undefined\n ? false\n : options.stream;\n\n const response = await this.httpClient.request(\n this.baseURL,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${this.token}`,\n },\n body: JSON.stringify({\n model: this.defaultModel,\n messages: xunfeiMessages,\n stream: false,\n ...(enableWebSearch && {\n tools: [\n {\n type: \"web_search\",\n web_search: {\n enable: true,\n },\n },\n ],\n }),\n }),\n timeout: 60000, // 60秒超时\n retries: 3, // 最多重试3次\n retryDelay: 1000, // 重试间隔1秒\n },\n );\n\n if (response.code !== 0) {\n throw new Error(`API错误: ${response.message}`);\n }\n\n if (!response.choices || response.choices.length === 0) {\n throw new Error(\"没有可用的响应选项\");\n }\n\n // 转换为标准格式返回\n return {\n id: response.sid,\n object: \"chat.completion\",\n created: Date.now(),\n model: this.defaultModel,\n choices: response.choices.map((choice) => ({\n index: choice.index,\n message: {\n role: choice.message.role,\n content: choice.message.content,\n },\n finish_reason: \"stop\",\n })),\n usage: response.usage,\n };\n } catch (error) {\n throw new Error(`创建聊天完成失败: ${(error as Error).message}`);\n }\n }\n\n /**\n * 发送单条消息并获取响应(便捷方法)\n * @param content 消息内容\n * @param systemPrompt 可选的系统提示\n * @param enableWebSearch 是否启用网络搜索\n * @returns 助手的响应文本\n */\n async sendMessage(\n content: string,\n systemPrompt?: string,\n enableWebSearch?: boolean,\n ): Promise {\n const messages: ChatMessage[] = [];\n\n if (systemPrompt) {\n messages.push({\n role: \"system\",\n content: systemPrompt,\n });\n }\n\n messages.push({\n role: \"user\",\n content,\n });\n\n const response = await this.createChatCompletion(messages, {\n stream: enableWebSearch,\n });\n\n return response.choices[0].message.content;\n }\n}\n"}}}}