feat(commentary): 双 provider 评论 — Angel(Agnes) + 美团大模型(LongCat)
- 新增 articles.commentary_meituan{_status,_model,_error} 4 列 + commentary_engine
- LlmSetting 加 meituan_api_key/base_url/chat_model/interval_sec/enabled/commentary_prompt
- 新 app/services/llm/providers.py 工厂,支持多 provider 客户端
- enrichment 流程改为 commentary_angel + commentary_meituan 并行(asyncio.gather),
任一 provider 失败不影响另一个
- enrichment_loop 状态判定:任一 provider 状态不是 ok 都视为待 enrich
- alembic 0004_dual_commentary 迁移
- 前端 Feed 卡片 + ArticleDetail 详情页各加一条'美团评论'卡
- AdminLlmSettings 加美团 provider 配置卡(独立 api_key 编辑器,不回显明文)
- LlmSettingOut.meituan_api_key_set (bool) 替代直接回传 key
- 默认 URL https://api.longcat.chat/openai/v1 / 默认模型 LongCat-2.0-Preview
This commit is contained in:
@@ -34,8 +34,12 @@ class ArticleListItem(BaseModel):
|
||||
fetched_at: datetime
|
||||
image_url: str | None = None
|
||||
# === 列表预览钩子:点击进详情前的"诱导点" ===
|
||||
commentary: str | None = None # LLM 点评(列表里截断显示)
|
||||
# 双 provider 评论:Angel(原字段) + 美团(meituan 字段),前端两条都展示
|
||||
commentary: str | None = None # Angel 评论(列表里截断显示)
|
||||
commentary_status: str | None = None # ok/failed/pending/n/a
|
||||
commentary_meituan: str | None = None # 美团评论
|
||||
commentary_meituan_status: str | None = None
|
||||
commentary_engine: str | None = None # angel / meituan / "angel,meituan"
|
||||
image_ai_url: str | None = None # AI 插图(列表里缩略图)
|
||||
is_starred: bool = False
|
||||
|
||||
@@ -66,8 +70,14 @@ class ArticleDetail(BaseModel):
|
||||
format_status: str | None = None # pending/ok/failed/n/a
|
||||
classify_status: str | None = None
|
||||
image_ai_status: str | None = None
|
||||
# 双 provider 评论
|
||||
commentary_status: str | None = None
|
||||
commentary: str | None = None
|
||||
commentary: str | None = None # Angel
|
||||
commentary_engine: str | None = None
|
||||
commentary_meituan_status: str | None = None
|
||||
commentary_meituan: str | None = None
|
||||
commentary_meituan_model: str | None = None
|
||||
commentary_meituan_error: str | None = None
|
||||
entities: dict | None = None
|
||||
sentiment: float | None = None
|
||||
duplicate_of: int | None = None
|
||||
|
||||
@@ -20,8 +20,39 @@ class LlmSettingOut(BaseModel):
|
||||
enabled: bool = True
|
||||
# 全局屏蔽分类标签;与 sources.blocklist_tags 合并后注入 classify prompt
|
||||
blocklist_tags: list[str] = []
|
||||
# 美团大模型(LongCat,OpenAI 兼容)双 provider 评论
|
||||
# 安全:不回传 api_key 真值,只回传 meituan_api_key_set 表示"是否已配置"
|
||||
meituan_api_key_set: bool = False
|
||||
meituan_base_url: str = "https://api.longcat.chat/openai/v1"
|
||||
meituan_chat_model: str = "LongCat-2.0-Preview"
|
||||
meituan_interval_sec: float = 2.0
|
||||
meituan_enabled: bool = True
|
||||
meituan_commentary_prompt: str | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
@classmethod
|
||||
def from_row(cls, row) -> "LlmSettingOut":
|
||||
"""从 LlmSetting 构造,key 字段转 bool。"""
|
||||
return cls(
|
||||
format_prompt=row.format_prompt,
|
||||
classify_prompt=row.classify_prompt,
|
||||
commentary_prompt=row.commentary_prompt,
|
||||
image_prompt_template=row.image_prompt_template,
|
||||
image_size=row.image_size,
|
||||
chat_model=row.chat_model,
|
||||
image_model=row.image_model,
|
||||
interval_sec=row.interval_sec,
|
||||
enabled=row.enabled,
|
||||
blocklist_tags=row.blocklist_tags or [],
|
||||
meituan_api_key_set=bool(row.meituan_api_key),
|
||||
meituan_base_url=row.meituan_base_url,
|
||||
meituan_chat_model=row.meituan_chat_model,
|
||||
meituan_interval_sec=row.meituan_interval_sec,
|
||||
meituan_enabled=row.meituan_enabled,
|
||||
meituan_commentary_prompt=row.meituan_commentary_prompt,
|
||||
updated_at=row.updated_at,
|
||||
)
|
||||
|
||||
|
||||
class LlmSettingUpdate(BaseModel):
|
||||
"""PATCH — 全部字段 optional,只更新传入的。"""
|
||||
@@ -36,6 +67,13 @@ class LlmSettingUpdate(BaseModel):
|
||||
interval_sec: float | None = Field(default=None, ge=0.0, le=60.0)
|
||||
enabled: bool | None = None
|
||||
blocklist_tags: list[str] | None = None
|
||||
# 美团 provider 字段(api_key 可更新;None/空 = 不修改;显式传空字符串 = 清空)
|
||||
meituan_api_key: str | None = Field(default=None, max_length=512)
|
||||
meituan_base_url: str | None = Field(default=None, max_length=255)
|
||||
meituan_chat_model: str | None = Field(default=None, max_length=64)
|
||||
meituan_interval_sec: float | None = Field(default=None, ge=0.0, le=60.0)
|
||||
meituan_enabled: bool | None = None
|
||||
meituan_commentary_prompt: str | None = None
|
||||
|
||||
|
||||
# === 默认提示词(模板,用户可改)===
|
||||
|
||||
Reference in New Issue
Block a user