Files
EPEEAIKit/art-agent/backend/app/config.py

294 lines
9.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
EPEEKit 集中配置。
所有可调参数从环境变量读取,每次调用实时读取(不缓存),确保 load_dotenv() 后生效。
"""
import os
from typing import Any
def get_llm_max_iterations() -> int:
return int(os.getenv("LLM_MAX_ITERATIONS", "5"))
# ─── LLM 模型注册表 ─────────────────────────────────────
#
# 每个模型的配置说明:
# id — 前端/API 使用的短 ID
# name — 显示名称
# provider — API 提供者(对应 _get_client 的分发键)
# model_id — 传给 OpenAI SDK 的 model 参数
# description — 前端下拉列表说明文字
# vision — 是否支持多模态图片输入
LLM_MODELS: dict[str, dict[str, Any]] = {
"gpt-5.4": {
"id": "gpt-5.4",
"name": "GPT-5.4",
"provider": "vectorengine",
"model_id": "gpt-5.4",
"description": "知识工作与计算机操控最强1M 上下文",
"vision": True,
},
"claude-sonnet-4-6": {
"id": "claude-sonnet-4-6",
"name": "Claude Sonnet 4.6",
"provider": "vectorengine",
"model_id": "claude-sonnet-4-6",
"description": "高性价比编码与日常任务",
"vision": True,
},
"claude-opus-4-6": {
"id": "claude-opus-4-6",
"name": "Claude Opus 4.6",
"provider": "vectorengine",
"model_id": "claude-opus-4-6",
"description": "编码与专家级推理最强128K 输出",
"vision": True,
},
"gemini-3.1-pro-preview": {
"id": "gemini-3.1-pro-preview",
"name": "Gemini 3.1 Pro",
"provider": "vectorengine",
"model_id": "gemini-3.1-pro-preview",
"description": "推理最强、价格最低2M 上下文",
"vision": True,
},
"glm-4.7": {
"id": "glm-4.7",
"name": "GLM-4.7",
"provider": "vectorengine",
"model_id": "glm-4.7",
"description": "智谱 AI中文能力突出免费额度",
"vision": False,
},
"gpt-4o-mini": {
"id": "gpt-4o-mini",
"name": "GPT-4o Mini",
"provider": "vectorengine",
"model_id": "gpt-4o-mini",
"description": "轻量快速、高性价比",
"vision": True,
},
"deepseek-chat": {
"id": "deepseek-chat",
"name": "DeepSeek Chat",
"provider": "deepseek",
"model_id": "deepseek-chat",
"description": "中文对话优化(直连)",
"vision": False,
},
}
def get_default_llm_model_id() -> str:
"""返回 .env 中配置的默认 LLM 短 ID不在注册表中则回退到 gpt-5.4。"""
env_model = os.getenv("LLM_MODEL", "gpt-5.4")
if env_model in LLM_MODELS:
return env_model
return "gpt-5.4"
def get_llm_model_config(model_id: str | None = None) -> dict[str, Any]:
"""根据短 ID 获取 LLM 模型配置,未指定或不存在则使用默认模型。"""
if model_id and model_id in LLM_MODELS:
return LLM_MODELS[model_id]
return LLM_MODELS[get_default_llm_model_id()]
def get_llm_models_list() -> list[dict]:
"""返回前端下拉列表所需的 LLM 模型摘要信息。"""
return [
{
"id": cfg["id"],
"name": cfg["name"],
"description": cfg["description"],
"vision": cfg.get("vision", False),
}
for cfg in LLM_MODELS.values()
]
# ─── 图像模型注册表 ─────────────────────────────────────
#
# 每个模型的配置说明:
# id — 前端/API 使用的短 ID
# name — 显示名称
# provider — 生成服务提供者(对应 image_gen.py 中的 Provider
# model_id — Replicate 上的完整模型 ID
# description — 前端下拉列表中的说明文字
# supports_ref_image — 是否原生支持参考图输入IP-Adapter 等)
# ref_image_param — 传给 Replicate 的参考图参数名(模型间可能不同)
# num_images_param — 批量生成参数名Flux 用 num_outputsKolors 用 number_of_images
# default_params — 默认推理参数
IMAGE_MODELS: dict[str, dict[str, Any]] = {
"gpt-image-1.5": {
"id": "gpt-image-1.5",
"name": "GPT Image 1.5",
"provider": "openai",
"model_id": "gpt-image-1.5",
"description": "OpenAI 最强生图,文字渲染与 prompt 理解最佳,支持多图参考",
"supports_ref_image": True,
"max_ref_images": 16,
"default_params": {
"size": "1024x1024",
"quality": "high",
},
},
"gemini-3.1-flash-image": {
"id": "gemini-3.1-flash-image",
"name": "Gemini 3.1 Flash Image",
"provider": "gemini_native",
"model_id": "gemini-3.1-flash-image-preview",
"description": "Google 原生生图,速度快、价格低,支持多图参考(最多 14 张)",
"supports_ref_image": True,
"max_ref_images": 14,
"default_params": {},
},
"flux-schnell": {
"id": "flux-schnell",
"name": "Flux Schnell",
"provider": "replicate",
"model_id": "black-forest-labs/flux-schnell",
"description": "快速生成,适合快速迭代",
"supports_ref_image": False,
"num_images_param": "num_outputs",
"default_params": {
"aspect_ratio": "1:1",
"output_format": "png",
},
},
"flux-dev": {
"id": "flux-dev",
"name": "Flux Dev",
"provider": "replicate",
"model_id": "black-forest-labs/flux-dev",
"description": "高质量生成,细节更好",
"supports_ref_image": False,
"num_images_param": "num_outputs",
"default_params": {
"aspect_ratio": "1:1",
"output_format": "png",
},
},
"sdxl": {
"id": "sdxl",
"name": "Stable Diffusion XL",
"provider": "replicate",
"model_id": "stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
"description": "经典 SDXL支持 negative prompt",
"supports_ref_image": False,
"num_images_param": "num_outputs",
"default_params": {
"width": 1024,
"height": 1024,
"num_inference_steps": 50,
"guidance_scale": 7.5,
},
},
"instant-style": {
"id": "instant-style",
"name": "InstantStyle",
"provider": "replicate",
"model_id": "jyoung105/instant-style:c6f01e12f31cb99f9ee774a78992a71294f630a6f433d9aecfdc33b816fc4baa",
"description": "强风格迁移,画风还原度高(较慢)",
"supports_ref_image": True,
"ref_image_param": "style_image",
"num_images_param": "num_outputs",
"default_params": {
"width": 1024,
"height": 1024,
"num_inference_steps": 30,
"guidance_scale": 5,
"style_strength": 1.0,
"block_mode": "style-only",
"adapter_mode": "original",
},
},
"kolors-ipadapter": {
"id": "kolors-ipadapter",
"name": "Kolors IP-Adapter",
"provider": "replicate",
"model_id": "fofr/kolors-with-ipadapter:5a1a92b2c0f81813225d48ed8e411813da41aa84e7582fb705d1af46eea36eed",
"description": "风格参考生成,上传参考图效果最佳",
"supports_ref_image": True,
"ref_image_param": "image",
"num_images_param": "number_of_images",
"default_params": {
"width": 1024,
"height": 1024,
"steps": 25,
"cfg": 4,
"ip_adapter_weight": 0.8,
"ip_adapter_weight_type": "style transfer precise",
"output_format": "png",
},
},
}
def get_default_image_model_id() -> str:
"""返回 .env 中配置的默认模型短 ID若不在注册表中则回退到 flux-schnell。"""
env_model = os.getenv("IMAGE_MODEL", "flux-schnell")
for mid, cfg in IMAGE_MODELS.items():
if cfg["model_id"] == env_model or mid == env_model:
return mid
return "flux-schnell"
def get_image_model_config(model_id: str | None = None) -> dict[str, Any]:
"""根据短 ID 获取模型配置,未指定或不存在则使用默认模型。"""
if model_id and model_id in IMAGE_MODELS:
return IMAGE_MODELS[model_id]
return IMAGE_MODELS[get_default_image_model_id()]
def get_ref_image_model_id() -> str | None:
"""返回有参考图时推荐使用的模型 ID第一个 supports_ref_image=True 的模型)。"""
for mid, cfg in IMAGE_MODELS.items():
if cfg.get("supports_ref_image"):
return mid
return None
def get_image_models_list() -> list[dict]:
"""返回前端下拉列表所需的模型摘要信息。"""
return [
{
"id": cfg["id"],
"name": cfg["name"],
"description": cfg["description"],
"supports_ref_image": cfg.get("supports_ref_image", False),
}
for cfg in IMAGE_MODELS.values()
]
# ─── 记忆系统配置 ─────────────────────────────────────
def get_deepseek_api_key() -> str:
return os.getenv("DEEPSEEK_API_KEY", "")
def get_ollama_base_url() -> str:
return os.getenv("OLLAMA_BASE_URL", "http://localhost:11434")
def get_mem0_embedding_model() -> str:
return os.getenv("MEM0_EMBEDDING_MODEL", "nomic-embed-text")
def get_max_recent_turns() -> int:
return int(os.getenv("MAX_RECENT_TURNS", "20"))
# ─── 图像输出配置 ─────────────────────────────────────
def get_image_aspect_ratio() -> str:
return os.getenv("IMAGE_ASPECT_RATIO", "1:1")
def get_image_output_format() -> str:
return os.getenv("IMAGE_OUTPUT_FORMAT", "png")