返回 VideoClaw
llm_gemini.py
根目录 / video-claw / video-claw / backend / models / llm_gemini.py
1 # -*- coding: utf-8 -*-
2 """
3 Google Gemini LLM 客户端 (OpenAI 兼容格式)
4 支持 gemini-2.5-flash, gemini-2.5-pro 等模型
5
6 可用模型:
7 - gemini-2.5-flash (性价比高)
8 - gemini-2.5-flash-preview
9 - gemini-2.5-pro (效果最好)
10 - gemini-2.5-pro-preview
11 - gemini-2.0-flash
12 """
13
14 import os
15 import sys
16
17 models_dir = os.path.dirname(os.path.abspath(__file__))
18 backend_dir = os.path.dirname(models_dir)
19 if backend_dir not in sys.path:
20 sys.path.insert(0, backend_dir)
21
22 import time
23 import logging
24 import httpx
25 from openai import OpenAI
26 from typing import List
27 from config import Config
28
29 logger = logging.getLogger(__name__)
30
31
32 class Gemini:
33 """
34 Gemini LLM 客户端,使用 OpenAI 兼容格式调用
35 """
36 def __init__(self, base_url: str = "", api_key: str = ""):
37 """
38 初始化 Gemini 客户端
39 :param base_url: OpenAI 兼容的 Base URL
40 :param api_key: Gemini API Key
41 """
42 # 确保 base_url 以 /v1 结尾
43 default_url = "https://generativelanguage.googleapis.com/v1beta"
44 self.base_url = base_url or Config.GOOGLE_GEMINI_BASE_URL or default_url
45 if self.base_url and not self.base_url.endswith("/v1"):
46 self.base_url = self.base_url.rstrip("/") + "/v1"
47 self.api_key = api_key or Config.GEMINI_API_KEY
48 kwargs = {"api_key": self.api_key, "base_url": self.base_url}
49 proxy = Config.provider_proxy("gemini")
50 if proxy:
51 kwargs["http_client"] = httpx.Client(proxy=proxy)
52 self.client = OpenAI(**kwargs)
53 self.max_attempts = 10
54
55 def query(self, prompt: str, image_urls: List[str] = [], model: str = "gemini-2.5-flash") -> str:
56 """
57 调用 Gemini LLM
58 :param prompt: 文本提示
59 :param image_urls: 图片 URL 列表(可选,用于多模态模型)
60 :param model: 模型名
61 :return: 生成的文本
62 """
63 if not model:
64 model = "gemini-2.5-flash"
65
66 # 构建消息格式
67 content: list = [{"type": "text", "text": prompt}]
68
69 # 添加图片 (如果有多模态模型支持)
70 if image_urls:
71 for img_url in image_urls:
72 if img_url.startswith("http"):
73 content.append({
74 "type": "image_url",
75 "image_url": {"url": img_url}
76 })
77
78 messages = [{"role": "user", "content": content}]
79
80 attempts = 0
81 while attempts < self.max_attempts:
82 try:
83 # 直接使用模型名(代理服务会处理格式转换)
84 response = self.client.chat.completions.create(
85 model=model,
86 messages=messages,
87 temperature=0.7
88 )
89
90 # 检查响应类型
91 if isinstance(response, str):
92 logger.error("Gemini returned a string response: %s", response)
93 raise Exception(f"API 返回错误: {response}")
94
95 if response.choices and len(response.choices) > 0:
96 return response.choices[0].message.content
97
98 except Exception as e:
99 logger.warning("Gemini request failed: %s", e)
100 attempts += 1
101 if attempts < self.max_attempts:
102 time.sleep(10)
103
104 raise Exception("Gemini: 达到最大重试次数,仍未获得有效响应。")
105
106
107 if __name__ == "__main__":
108 import sys
109 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
110 from config import Config
111
112 # 支持的模型列表
113 MODELS = ["gemini-2.5-flash", "gemini-2.0-flash"]
114
115 print("=== Gemini LLM 可用性测试 ===")
116 api_key = Config.GEMINI_API_KEY
117 base_url = Config.GOOGLE_GEMINI_BASE_URL
118 if not api_key:
119 print("✗ GEMINI_API_KEY 未设置,跳过")
120 sys.exit(1)
121 print(f" API Key: {api_key[:6]}***")
122 print(f" Base URL: {base_url}")
123 client = Gemini(api_key=api_key, base_url=base_url)
124 prompt = "用一句话介绍你自己。"
125 print(f" Prompt: {prompt}")
126
127 for model in MODELS:
128 print(f"\n--- 测试模型: {model} ---")
129 t0 = time.time()
130 try:
131 resp = client.query(prompt, model=model)
132 elapsed = time.time() - t0
133 print(f"✓ 响应 ({elapsed:.1f}s): {resp.strip()[:200]}")
134 except Exception as e:
135 print(f"✗ 失败: {e}")
136
136 lines PYTHON