( question: string, imageSource?: string, useVision = false )
| 353 | |
| 354 | // 调用GPT API |
| 355 | async function callGptApi( |
| 356 | question: string, |
| 357 | imageSource?: string, |
| 358 | useVision = false |
| 359 | ): Promise<string> { |
| 360 | const apiKey = ConfigManager.get(CONFIG_KEYS.GPT_KEY); |
| 361 | const apiUrl = ConfigManager.get(CONFIG_KEYS.GPT_API); |
| 362 | const model = useVision |
| 363 | ? ConfigManager.get(CONFIG_KEYS.GPT_VISION_MODEL) |
| 364 | : ConfigManager.get(CONFIG_KEYS.GPT_MODEL); |
| 365 | const webSearch = |
| 366 | ConfigManager.get(CONFIG_KEYS.GPT_WEB_SEARCH).toLowerCase() === "true"; |
| 367 | const maxTokensStr = ConfigManager.get(CONFIG_KEYS.GPT_MAX_TOKENS); |
| 368 | |
| 369 | if (!apiKey) { |
| 370 | throw new Error("未设置 API Key"); |
| 371 | } |
| 372 | if (!apiUrl) { |
| 373 | throw new Error("未设置 API URL"); |
| 374 | } |
| 375 | if (!model) { |
| 376 | throw new Error("未设置模型"); |
| 377 | } |
| 378 | |
| 379 | let maxTokens: number | null = null; |
| 380 | try { |
| 381 | const parsed = parseInt(maxTokensStr); |
| 382 | if (parsed === -1) { |
| 383 | maxTokens = null; |
| 384 | } else { |
| 385 | maxTokens = parsed; |
| 386 | } |
| 387 | } catch { |
| 388 | maxTokens = 888; |
| 389 | } |
| 390 | |
| 391 | const useResponsesApi = webSearch; |
| 392 | const url = useResponsesApi |
| 393 | ? `${apiUrl}/v1/responses` |
| 394 | : `${apiUrl}/v1/chat/completions`; |
| 395 | |
| 396 | let payload: any; |
| 397 | |
| 398 | if (useVision && imageSource) { |
| 399 | if (useResponsesApi) { |
| 400 | // Responses API with vision |
| 401 | payload = { |
| 402 | model, |
| 403 | input: [ |
| 404 | { |
| 405 | role: "user", |
| 406 | content: [ |
| 407 | { type: "input_text", text: question }, |
| 408 | { type: "input_image", image_url: imageSource }, |
| 409 | ], |
| 410 | }, |
| 411 | ], |
| 412 | tools: [{ type: "web_search" }], |
no test coverage detected