From b7b1960209b44ea13d6fa8b8f4eef8d23996caaa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:31:11 +0000 Subject: [PATCH 1/4] Initial plan From de4c36ffa098486ed18dc5f44e9e9cff43b6d278 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:42:51 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=E6=8B=86=E5=88=86VLM=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: BukeLy <19304666+BukeLy@users.noreply.github.com> --- env.example | 3 ++- src/config.py | 16 +++++++++++++++- src/multi_tenant.py | 5 +++-- src/tenant_config.py | 1 + 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/env.example b/env.example index db7a4f2..2270732 100644 --- a/env.example +++ b/env.example @@ -15,6 +15,8 @@ LLM_API_KEY="your_llm_api_key_here" LLM_BASE_URL="https://ark.ap-southeast.bytepluses.com/api/v3" # 使用的模型名称 LLM_MODEL=seed-1-6-250615 +# 用于多模态图片理解的 VLM 模型(与 LLM_MODEL 解耦) +VLM_MODEL=seed-1-6-250615 # LLM 供应商标识(ark/openai/claude) LLM_PROVIDER=ark # VLM 图片理解 API 超时时间(秒,默认 120 秒) @@ -318,4 +320,3 @@ TZ=Asia/Shanghai # --- Python 配置 --- PYTHONUNBUFFERED=1 # 禁用输出缓冲,实时查看日志 - diff --git a/src/config.py b/src/config.py index 0d1f8f5..672384f 100644 --- a/src/config.py +++ b/src/config.py @@ -10,7 +10,7 @@ import os from typing import Optional -from pydantic import Field +from pydantic import Field, field_validator from pydantic_settings import BaseSettings @@ -22,6 +22,7 @@ class LLMConfig(BaseSettings): api_key: str = Field(..., description="LLM API Key") base_url: str = Field(..., description="LLM API Base URL") model: str = Field(default="seed-1-6-250615", description="LLM Model Name") + vlm_model: str = Field(default="seed-1-6-250615", description="VLM Model Name") vlm_timeout: int = Field(default=120, description="VLM Image Understanding Timeout (seconds)") timeout: int = Field(default=60, description="General LLM Timeout (seconds)") @@ -35,6 +36,19 @@ class Config: env_file = ".env" extra = "ignore" + @field_validator("vlm_model", mode="before") + @classmethod + def _load_vlm_model(cls, v): + """ + 优先读取独立的 VLM_MODEL(保持与 LLM 文本模型解耦) + 回退顺序: + 1) 显式传入值 + 2) 环境变量 VLM_MODEL(独立配置) + 3) 环境变量 LLM_VLM_MODEL(前缀形式) + 4) 默认值 + """ + return v or os.getenv("VLM_MODEL") or os.getenv("LLM_VLM_MODEL") or "seed-1-6-250615" + # ==================== Embedding Configuration ==================== diff --git a/src/multi_tenant.py b/src/multi_tenant.py index d4cb0b1..e18c7d4 100644 --- a/src/multi_tenant.py +++ b/src/multi_tenant.py @@ -51,6 +51,7 @@ def __init__( self.ark_api_key = config.llm.api_key self.ark_base_url = config.llm.base_url self.ark_model = config.llm.model + self.ark_vlm_model = config.llm.vlm_model self.sf_api_key = config.embedding.api_key self.sf_base_url = config.embedding.base_url @@ -278,7 +279,7 @@ def _create_vision_model_func(self, llm_config: Dict): import aiohttp # 从配置中提取参数(支持租户覆盖) - model = llm_config.get("model", self.ark_model) + model = llm_config.get("vlm_model", self.ark_vlm_model) api_key = llm_config.get("api_key", self.ark_api_key) base_url = llm_config.get("base_url", self.ark_base_url) vlm_timeout = llm_config.get("vlm_timeout", self.vlm_timeout) @@ -552,4 +553,4 @@ async def get_tenant_lightrag(tenant_id: str) -> LightRAG: LightRAG: 该租户的实例 """ manager = get_multi_tenant_manager() - return await manager.get_instance(tenant_id) \ No newline at end of file + return await manager.get_instance(tenant_id) diff --git a/src/tenant_config.py b/src/tenant_config.py index 23a3f2f..0eb20a2 100644 --- a/src/tenant_config.py +++ b/src/tenant_config.py @@ -301,6 +301,7 @@ def _merge_llm_config(self, tenant_config: Optional[TenantConfigModel]) -> Dict[ """ base = { "model": config.llm.model, + "vlm_model": config.llm.vlm_model, "api_key": config.llm.api_key, "base_url": config.llm.base_url, "timeout": config.llm.timeout, From e5548d2c6aa56955758ec95c98cf5fda8eee687d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:59:53 +0000 Subject: [PATCH 3/4] =?UTF-8?q?=E5=AE=8C=E5=96=84VLM=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E7=8B=AC=E7=AB=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: BukeLy <19304666+BukeLy@users.noreply.github.com> --- env.example | 5 ++++- src/config.py | 20 ++++---------------- src/multi_tenant.py | 22 ++++++++++++---------- src/tenant_config.py | 2 ++ 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/env.example b/env.example index 2270732..4c7a3eb 100644 --- a/env.example +++ b/env.example @@ -15,8 +15,11 @@ LLM_API_KEY="your_llm_api_key_here" LLM_BASE_URL="https://ark.ap-southeast.bytepluses.com/api/v3" # 使用的模型名称 LLM_MODEL=seed-1-6-250615 -# 用于多模态图片理解的 VLM 模型(与 LLM_MODEL 解耦) +# 用于多模态图片理解的 VLM 模型(必填,独立于 LLM_MODEL) VLM_MODEL=seed-1-6-250615 +# 可选:VLM 使用独立的密钥/域名(未设置时复用 LLM 配置) +# VLM_API_KEY="your_vlm_api_key_here" +# VLM_BASE_URL="https://api.example.com/v1" # LLM 供应商标识(ark/openai/claude) LLM_PROVIDER=ark # VLM 图片理解 API 超时时间(秒,默认 120 秒) diff --git a/src/config.py b/src/config.py index 672384f..3fe7f78 100644 --- a/src/config.py +++ b/src/config.py @@ -8,9 +8,8 @@ 重构原因: 统一配置管理,从服务商导向改为功能导向命名 """ -import os from typing import Optional -from pydantic import Field, field_validator +from pydantic import Field from pydantic_settings import BaseSettings @@ -22,7 +21,9 @@ class LLMConfig(BaseSettings): api_key: str = Field(..., description="LLM API Key") base_url: str = Field(..., description="LLM API Base URL") model: str = Field(default="seed-1-6-250615", description="LLM Model Name") - vlm_model: str = Field(default="seed-1-6-250615", description="VLM Model Name") + vlm_model: str = Field(..., description="VLM Model Name", alias="VLM_MODEL") + vlm_api_key: Optional[str] = Field(default=None, description="VLM API Key", alias="VLM_API_KEY") + vlm_base_url: Optional[str] = Field(default=None, description="VLM API Base URL", alias="VLM_BASE_URL") vlm_timeout: int = Field(default=120, description="VLM Image Understanding Timeout (seconds)") timeout: int = Field(default=60, description="General LLM Timeout (seconds)") @@ -36,19 +37,6 @@ class Config: env_file = ".env" extra = "ignore" - @field_validator("vlm_model", mode="before") - @classmethod - def _load_vlm_model(cls, v): - """ - 优先读取独立的 VLM_MODEL(保持与 LLM 文本模型解耦) - 回退顺序: - 1) 显式传入值 - 2) 环境变量 VLM_MODEL(独立配置) - 3) 环境变量 LLM_VLM_MODEL(前缀形式) - 4) 默认值 - """ - return v or os.getenv("VLM_MODEL") or os.getenv("LLM_VLM_MODEL") or "seed-1-6-250615" - # ==================== Embedding Configuration ==================== diff --git a/src/multi_tenant.py b/src/multi_tenant.py index e18c7d4..344218f 100644 --- a/src/multi_tenant.py +++ b/src/multi_tenant.py @@ -48,10 +48,12 @@ def __init__( self._creation_locks: defaultdict = defaultdict(asyncio.Lock) # 共享配置(从集中配置管理读取) - self.ark_api_key = config.llm.api_key - self.ark_base_url = config.llm.base_url - self.ark_model = config.llm.model - self.ark_vlm_model = config.llm.vlm_model + self.llm_api_key = config.llm.api_key + self.llm_base_url = config.llm.base_url + self.llm_model = config.llm.model + self.vlm_model = config.llm.vlm_model + self.vlm_api_key = config.llm.vlm_api_key or config.llm.api_key + self.vlm_base_url = config.llm.vlm_base_url or config.llm.base_url self.sf_api_key = config.embedding.api_key self.sf_base_url = config.embedding.base_url @@ -86,9 +88,9 @@ def _create_llm_func(self, llm_config: Dict): import asyncio # 从配置中提取参数(支持租户覆盖) - model = llm_config.get("model", self.ark_model) - api_key = llm_config.get("api_key", self.ark_api_key) - base_url = llm_config.get("base_url", self.ark_base_url) + model = llm_config.get("model", self.llm_model) + api_key = llm_config.get("api_key", self.llm_api_key) + base_url = llm_config.get("base_url", self.llm_base_url) # 获取 RateLimiter 参数(租户可配置) # 注意:这里的 max_async 是 RateLimiter 的并发控制,不是 LightRAG 的 @@ -279,9 +281,9 @@ def _create_vision_model_func(self, llm_config: Dict): import aiohttp # 从配置中提取参数(支持租户覆盖) - model = llm_config.get("vlm_model", self.ark_vlm_model) - api_key = llm_config.get("api_key", self.ark_api_key) - base_url = llm_config.get("base_url", self.ark_base_url) + model = llm_config.get("vlm_model", self.vlm_model) + api_key = llm_config.get("vlm_api_key") or self.vlm_api_key + base_url = llm_config.get("vlm_base_url") or llm_config.get("base_url") or self.vlm_base_url vlm_timeout = llm_config.get("vlm_timeout", self.vlm_timeout) # 获取速率限制器(VLM 使用 LLM 的限制) diff --git a/src/tenant_config.py b/src/tenant_config.py index 0eb20a2..250ff0d 100644 --- a/src/tenant_config.py +++ b/src/tenant_config.py @@ -302,6 +302,8 @@ def _merge_llm_config(self, tenant_config: Optional[TenantConfigModel]) -> Dict[ base = { "model": config.llm.model, "vlm_model": config.llm.vlm_model, + "vlm_api_key": config.llm.vlm_api_key, + "vlm_base_url": config.llm.vlm_base_url, "api_key": config.llm.api_key, "base_url": config.llm.base_url, "timeout": config.llm.timeout, From bb21225ac58b779afdb4e0cf7a9154c48091b3c2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 10:01:11 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BC=98=E5=8C=96VLM=E5=AF=86=E9=92=A5?= =?UTF-8?q?=E5=9B=9E=E9=80=80=E4=B8=80=E8=87=B4=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: BukeLy <19304666+BukeLy@users.noreply.github.com> --- src/multi_tenant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multi_tenant.py b/src/multi_tenant.py index 344218f..c87dd2e 100644 --- a/src/multi_tenant.py +++ b/src/multi_tenant.py @@ -282,7 +282,7 @@ def _create_vision_model_func(self, llm_config: Dict): # 从配置中提取参数(支持租户覆盖) model = llm_config.get("vlm_model", self.vlm_model) - api_key = llm_config.get("vlm_api_key") or self.vlm_api_key + api_key = llm_config.get("vlm_api_key") or llm_config.get("api_key") or self.vlm_api_key base_url = llm_config.get("vlm_base_url") or llm_config.get("base_url") or self.vlm_base_url vlm_timeout = llm_config.get("vlm_timeout", self.vlm_timeout)