From 45115b802f5ce6ca19fec6949e8a7bcdc2b0741b Mon Sep 17 00:00:00 2001 From: foxplaying <166147707+foxplaying@users.noreply.github.com> Date: Mon, 22 Sep 2025 11:59:12 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/llm_models/model_client/gemini_client.py | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/llm_models/model_client/gemini_client.py b/src/llm_models/model_client/gemini_client.py index 67c7475e..1a2e0426 100644 --- a/src/llm_models/model_client/gemini_client.py +++ b/src/llm_models/model_client/gemini_client.py @@ -17,6 +17,7 @@ from google.genai.types import ( EmbedContentResponse, EmbedContentConfig, SafetySetting, + HttpOptions, HarmCategory, HarmBlockThreshold, ) @@ -345,22 +346,21 @@ class GeminiClient(BaseClient): def __init__(self, api_provider: APIProvider): super().__init__(api_provider) + + http_options_kwargs = {"timeout": api_provider.timeout} + # 增加传入参数处理 + if api_provider.base_url: + parts = api_provider.base_url.rsplit("/", 1) + if len(parts) == 2 and parts[1].startswith("v"): + http_options_kwargs["base_url"] = parts[0] + "/" + http_options_kwargs["api_version"] = parts[1] + else: + http_options_kwargs["base_url"] = api_provider.base_url self.client = genai.Client( + http_options=HttpOptions(**http_options_kwargs), api_key=api_provider.api_key, ) # 这里和openai不一样,gemini会自己决定自己是否需要retry - # 尝试传入自定义base_url(实验性,必须为Gemini格式) - if hasattr(api_provider, "base_url") and api_provider.base_url: - base_url = api_provider.base_url.rstrip("/") # 去掉末尾 / - self.client._api_client._http_options.base_url = base_url - - # 如果 base_url 已经带了 /v1 或 /v1beta,就清掉 SDK 的 api_version - if base_url.endswith("/v1") or base_url.endswith("/v1beta"): - self.client._api_client._http_options.api_version = None - - # 让 GeminiClient 内部也能访问底层 api_client - self._api_client = self.client._api_client - @staticmethod def clamp_thinking_budget(tb: int, model_id: str) -> int: """ From be5b1cd1f53c27c18f9420ea5bc430de153492df Mon Sep 17 00:00:00 2001 From: foxplaying <166147707+foxplaying@users.noreply.github.com> Date: Mon, 22 Sep 2025 12:28:06 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/llm_models/model_client/gemini_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llm_models/model_client/gemini_client.py b/src/llm_models/model_client/gemini_client.py index 1a2e0426..c662a687 100644 --- a/src/llm_models/model_client/gemini_client.py +++ b/src/llm_models/model_client/gemini_client.py @@ -350,9 +350,9 @@ class GeminiClient(BaseClient): http_options_kwargs = {"timeout": api_provider.timeout} # 增加传入参数处理 if api_provider.base_url: - parts = api_provider.base_url.rsplit("/", 1) + parts = api_provider.base_url.rstrip("/").rsplit("/", 1) if len(parts) == 2 and parts[1].startswith("v"): - http_options_kwargs["base_url"] = parts[0] + "/" + http_options_kwargs["base_url"] = f"{parts[0]}/" http_options_kwargs["api_version"] = parts[1] else: http_options_kwargs["base_url"] = api_provider.base_url From 3eeb1a84b3c437d9ee70d205988265141268b69b Mon Sep 17 00:00:00 2001 From: foxplaying <166147707+foxplaying@users.noreply.github.com> Date: Mon, 22 Sep 2025 12:43:34 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=97=B6=E9=97=B4=E5=8D=95=E4=BD=8D?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/llm_models/model_client/gemini_client.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/llm_models/model_client/gemini_client.py b/src/llm_models/model_client/gemini_client.py index c662a687..4c3e4305 100644 --- a/src/llm_models/model_client/gemini_client.py +++ b/src/llm_models/model_client/gemini_client.py @@ -346,9 +346,15 @@ class GeminiClient(BaseClient): def __init__(self, api_provider: APIProvider): super().__init__(api_provider) - - http_options_kwargs = {"timeout": api_provider.timeout} + # 增加传入参数处理 + http_options_kwargs = {"timeout": api_provider.timeout} + + # 秒转换为毫秒传入 + if api_provider.timeout is not None: + http_options_kwargs["timeout"] = int(api_provider.timeout * 1000) + + # 传入并处理地址和版本(必须为Gemini格式) if api_provider.base_url: parts = api_provider.base_url.rstrip("/").rsplit("/", 1) if len(parts) == 2 and parts[1].startswith("v"): From fbc84789cb3c9e5350154402461b93c2b2b9956a Mon Sep 17 00:00:00 2001 From: foxplaying <166147707+foxplaying@users.noreply.github.com> Date: Tue, 23 Sep 2025 17:15:21 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=A2=84=E7=AE=97?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/llm_models/model_client/gemini_client.py | 23 ++++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/llm_models/model_client/gemini_client.py b/src/llm_models/model_client/gemini_client.py index 4c3e4305..9e8844e8 100644 --- a/src/llm_models/model_client/gemini_client.py +++ b/src/llm_models/model_client/gemini_client.py @@ -386,20 +386,29 @@ class GeminiClient(BaseClient): limits = THINKING_BUDGET_LIMITS[key] break - # 特殊值处理 + # 预算值处理 if tb == THINKING_BUDGET_AUTO: return THINKING_BUDGET_AUTO if tb == THINKING_BUDGET_DISABLED: if limits and limits.get("can_disable", False): return THINKING_BUDGET_DISABLED - return limits["min"] if limits else THINKING_BUDGET_AUTO + if limits: + logger.warning(f"模型 {model_id} 不支持禁用思考预算,已回退到最小值 {limits['min']}") + return limits["min"] + return THINKING_BUDGET_AUTO - # 已知模型裁剪到范围 + # 已知模型范围裁剪 + 提示 if limits: - return max(limits["min"], min(tb, limits["max"])) + if tb < limits["min"]: + logger.warning(f"模型 {model_id} 的 thinking_budget={tb} 过小,已调整为最小值 {limits['min']}") + return limits["min"] + if tb > limits["max"]: + logger.warning(f"模型 {model_id} 的 thinking_budget={tb} 过大,已调整为最大值 {limits['max']}") + return limits["max"] + return tb - # 未知模型,返回动态模式 - logger.warning(f"模型 {model_id} 未在 THINKING_BUDGET_LIMITS 中定义,将使用动态模式 tb=-1 兼容。") + # 未知模型 → 默认自动模式 + logger.warning(f"模型 {model_id} 未在 THINKING_BUDGET_LIMITS 中定义,已启用模型自动预算兼容") return THINKING_BUDGET_AUTO async def get_response( @@ -454,7 +463,7 @@ class GeminiClient(BaseClient): try: tb = int(extra_params["thinking_budget"]) except (ValueError, TypeError): - logger.warning(f"无效的 thinking_budget 值 {extra_params['thinking_budget']},将使用默认动态模式 {tb}") + logger.warning(f"无效的 thinking_budget 值 {extra_params['thinking_budget']},将使用模型自动预算模式 {tb}") # 裁剪到模型支持的范围 tb = self.clamp_thinking_budget(tb, model_info.model_identifier) From a2916515066676e13a08e905f830b993f4b98088 Mon Sep 17 00:00:00 2001 From: foxplaying <166147707+foxplaying@users.noreply.github.com> Date: Tue, 23 Sep 2025 17:25:48 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/model_configuration_guide.md | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/model_configuration_guide.md b/docs/model_configuration_guide.md index fd1cb018..96ab3a23 100644 --- a/docs/model_configuration_guide.md +++ b/docs/model_configuration_guide.md @@ -28,7 +28,7 @@ version = "1.1.1" ```toml [[api_providers]] name = "DeepSeek" # 服务商名称(自定义) -base_url = "https://api.deepseek.cn/v1" # API服务的基础URL +base_url = "https://api.deepseek.com/v1" # API服务的基础URL api_key = "your-api-key-here" # API密钥 client_type = "openai" # 客户端类型 max_retry = 2 # 最大重试次数 @@ -43,19 +43,19 @@ retry_interval = 10 # 重试间隔(秒) | `name` | ✅ | 服务商名称,需要在模型配置中引用 | - | | `base_url` | ✅ | API服务的基础URL | - | | `api_key` | ✅ | API密钥,请替换为实际密钥 | - | -| `client_type` | ❌ | 客户端类型:`openai`(OpenAI格式)或 `gemini`(Gemini格式,现在支持不良好) | `openai` | +| `client_type` | ❌ | 客户端类型:`openai`(OpenAI格式)或 `gemini`(Gemini格式) | `openai` | | `max_retry` | ❌ | API调用失败时的最大重试次数 | 2 | | `timeout` | ❌ | API请求超时时间(秒) | 30 | | `retry_interval` | ❌ | 重试间隔时间(秒) | 10 | -**请注意,对于`client_type`为`gemini`的模型,`base_url`字段无效。** +**请注意,对于`client_type`为`gemini`的模型,`retry`字段由`gemini`自己决定。** ### 2.3 支持的服务商示例 #### DeepSeek ```toml [[api_providers]] name = "DeepSeek" -base_url = "https://api.deepseek.cn/v1" +base_url = "https://api.deepseek.com/v1" api_key = "your-deepseek-api-key" client_type = "openai" ``` @@ -73,7 +73,7 @@ client_type = "openai" ```toml [[api_providers]] name = "Google" -base_url = "https://api.google.com/v1" +base_url = "https://generativelanguage.googleapis.com/v1beta" api_key = "your-google-api-key" client_type = "gemini" # 注意:Gemini需要使用特殊客户端 ``` @@ -133,7 +133,17 @@ thinking = {type = "disabled"} # 禁用思考 ``` 请注意,`extra_params` 的配置应该构成一个合法的TOML字典结构,具体内容取决于API服务商的要求。 -**请注意,对于`client_type`为`gemini`的模型,此字段无效。** +对于`gemini`需要单独进行配置 +```toml +[[models]] +model_identifier = "gemini-2.5-flash" +name = "gemini-2.5-flash" +api_provider = "google" +[models.extra_params] +thinking_budget = 0 # 禁用思考 +# thinking_budget = -1 由模型自己决定 +``` + ### 3.3 配置参数说明 | 参数 | 必填 | 说明 | From 30ef8dd81a892b3c2336d7e6b540b411e3473ebe Mon Sep 17 00:00:00 2001 From: foxplaying <166147707+foxplaying@users.noreply.github.com> Date: Tue, 23 Sep 2025 17:27:35 +0800 Subject: [PATCH 6/7] Update model_configuration_guide.md --- docs/model_configuration_guide.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/model_configuration_guide.md b/docs/model_configuration_guide.md index 96ab3a23..65fae981 100644 --- a/docs/model_configuration_guide.md +++ b/docs/model_configuration_guide.md @@ -131,9 +131,8 @@ enable_thinking = false # 禁用思考 [models.extra_params] thinking = {type = "disabled"} # 禁用思考 ``` -请注意,`extra_params` 的配置应该构成一个合法的TOML字典结构,具体内容取决于API服务商的要求。 -对于`gemini`需要单独进行配置 +而对于`gemini`需要单独进行配置 ```toml [[models]] model_identifier = "gemini-2.5-flash" @@ -144,6 +143,8 @@ thinking_budget = 0 # 禁用思考 # thinking_budget = -1 由模型自己决定 ``` +请注意,`extra_params` 的配置应该构成一个合法的TOML字典结构,具体内容取决于API服务商的要求。 + ### 3.3 配置参数说明 | 参数 | 必填 | 说明 | From f8844fec4f51346a6fc5131d6386bdcdb4dfa128 Mon Sep 17 00:00:00 2001 From: foxplaying <166147707+foxplaying@users.noreply.github.com> Date: Tue, 23 Sep 2025 17:49:06 +0800 Subject: [PATCH 7/7] Update model_configuration_guide.md --- docs/model_configuration_guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/model_configuration_guide.md b/docs/model_configuration_guide.md index 65fae981..f2da8be1 100644 --- a/docs/model_configuration_guide.md +++ b/docs/model_configuration_guide.md @@ -137,7 +137,7 @@ thinking = {type = "disabled"} # 禁用思考 [[models]] model_identifier = "gemini-2.5-flash" name = "gemini-2.5-flash" -api_provider = "google" +api_provider = "Google" [models.extra_params] thinking_budget = 0 # 禁用思考 # thinking_budget = -1 由模型自己决定