Files
diary-news/backend/alembic/versions/0004_dual_commentary.py
xiaji bc36a1fc38 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
2026-06-12 19:00:00 +08:00

129 lines
3.4 KiB
Python

"""双 provider 评论:加美团评论列 + commentary_engine 标识
- commentary_engine 区分"实际写入的 provider 名称"(angel / meituan / "angel,meituan")
- commentary_meituan{_status,_model,_error,_} 4 列
Revision ID: 0004
Revises: 0003
Create Date: 2026-06-12
"""
from __future__ import annotations
from typing import Sequence, Union
import sqlalchemy as sa
from alembic import op
revision: str = "0004"
down_revision: Union[str, None] = "0003"
branch_labels = None
depends_on = None
def upgrade() -> None:
# === articles:加 5 列(4 个 status/model/error + 1 个 content)===
op.add_column(
"articles",
sa.Column("commentary_engine", sa.String(32), nullable=True),
)
op.add_column(
"articles",
sa.Column(
"commentary_meituan",
sa.Text,
nullable=True,
),
)
op.add_column(
"articles",
sa.Column(
"commentary_meituan_status",
sa.String(16),
nullable=False,
server_default="n/a",
),
)
op.add_column(
"articles",
sa.Column(
"commentary_meituan_model",
sa.String(64),
nullable=True,
),
)
op.add_column(
"articles",
sa.Column(
"commentary_meituan_error",
sa.Text,
nullable=True,
),
)
# 旧存量:commentary_status=ok 的文章 → 标记 commentary_engine=angel
op.execute(
"UPDATE articles SET commentary_engine = 'angel' "
"WHERE commentary_status = 'ok' AND commentary_engine IS NULL"
)
# === llm_settings:加 6 列(美团 provider 配置)===
op.add_column(
"llm_settings",
sa.Column("meituan_api_key", sa.Text, nullable=False, server_default=""),
)
op.add_column(
"llm_settings",
sa.Column(
"meituan_base_url",
sa.String(255),
nullable=False,
server_default="https://api.longcat.chat/openai/v1",
),
)
op.add_column(
"llm_settings",
sa.Column(
"meituan_chat_model",
sa.String(64),
nullable=False,
server_default="LongCat-2.0-Preview",
),
)
op.add_column(
"llm_settings",
sa.Column(
"meituan_interval_sec",
sa.Float,
nullable=False,
server_default="2.0",
),
)
op.add_column(
"llm_settings",
sa.Column(
"meituan_enabled",
sa.Boolean,
nullable=False,
server_default=sa.true(),
),
)
op.add_column(
"llm_settings",
sa.Column("meituan_commentary_prompt", sa.Text, nullable=True),
)
def downgrade() -> None:
# 反向顺序很重要(后加的先删)
op.drop_column("llm_settings", "meituan_commentary_prompt")
op.drop_column("llm_settings", "meituan_enabled")
op.drop_column("llm_settings", "meituan_interval_sec")
op.drop_column("llm_settings", "meituan_chat_model")
op.drop_column("llm_settings", "meituan_base_url")
op.drop_column("llm_settings", "meituan_api_key")
op.drop_column("articles", "commentary_meituan_error")
op.drop_column("articles", "commentary_meituan_model")
op.drop_column("articles", "commentary_meituan_status")
op.drop_column("articles", "commentary_meituan")
op.drop_column("articles", "commentary_engine")