Files
bwstudio db8cea02f8 feat: 提示词和 AI 参数移至数据库管理
- AiSetting 模型新增 6 个提示词字段 + 3 个阶段温度字段
- main.py 迁移逻辑改为检测 ai_settings 表的新字段并填充默认值
- generate.py 从数据库读取生成提示词,去掉硬编码
- optimizer 从 API 读取各阶段提示词和温度,删除 prompts.py
- crawler 从 API 读取提取/改写提示词和温度,删除 prompts.py
- settings/active 端点去掉 token 认证(供爬虫/优化器使用)
- 后台设置页新增提示词编辑区和温度调节控件
- 新增 _ensure_default_settings 自动创建默认配置
2026-06-13 17:27:09 +08:00

161 lines
6.1 KiB
Python
Raw Permalink 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.
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.config import API_TITLE, API_VERSION
from app.routers import jokes_router, categories_router, auth_router, admin_router, settings_router, links_router, feedback_router, generate_router
from app.routers.submit import router as submit_router
from app.database import Base, engine
from app.models.setting import AiSetting
from app.models.link import Link
from app.models.feedback import Feedback # 注册模型,确保 create_all 能看到
# 创建新表(如果不存在)
Base.metadata.create_all(bind=engine)
# 对已有表新增字段的兼容迁移(SQLite 不支持 ALTER TABLE ADD COLUMN IF NOT EXISTS
# 默认提示词
_GENERATE_PROMPT_DEFAULT = """你是一位幽默大师,专门创作轻松搞笑的短笑话。
{context}
要求:
1. 根据场景和关键词创作一条原创笑话
2. 笑话要有反转或意外结局
3. 语言风格:{style}
4. 字数要求:{length_requirement}
5. 直接输出笑话内容,不需要解释
请严格按照以下 JSON 格式输出,不要加任何额外说明:
{{
"title": "笑话标题",
"content": "笑话正文",
"score": 8,
"reason": "这个笑话巧妙结合了场景和关键词,结尾有反转"
}}
score 是 1-10 的整数评分,reason 是用一句话说明亮点。"""
_OPTIMIZER_QUALITY_DEFAULT = """你是一个幽默内容审核专家。判断以下内容是否是一个合格的笑话/段子。
合格标准(满足任一即可):
1. 有明确的笑点或反转(punchline)
2. 有幽默的语言表达或双关
3. 有意外结局或情理之中意料之外
不合格标准(符合任一即判定不合格):
1. 纯粹的事实陈述,没有任何幽默元素
2. 只是对话片段,没有笑点
3. 普通故事或叙事,没有幽默设计
4. 说教或道理阐述
5. 内容不完整或难以理解
始终返回 JSON 格式:{"has_punchline": true/false, "reason": "简要说明判断理由"}"""
_OPTIMIZER_POLISH_DEFAULT = """你是一个专业的幽默文案编辑。请润色以下笑话,要求:
1. 保持核心笑点不变
2. 优化语言表达,使其更通顺、更精炼
3. 增强节奏感和幽默效果,但不改变原意
4. 字数控制在原内容的 80%-120%
5. 不要添加额外解释或评论
6. 直接输出润色后的内容,不要加任何前缀"""
_OPTIMIZER_EVALUATE_DEFAULT = """你是一个笑话分类和评价专家。对给定的笑话进行分析,返回 JSON 格式的分类和评分结果。
要求:
1. types: 从提供的类型列表中选择所有匹配的类型名称(数组,可以选多个)
2. crowds: 从提供的人群列表中选择所有匹配的人群名称(数组,可以选多个)
3. score: 1-10 分,基于幽默程度、创意和表达效果
4. comment: 简短评语(10字以内)
始终返回 JSON 格式。"""
_CRAWLER_EXTRACT_DEFAULT = """你是一个笑话提取专家。从给定的网页文本中识别并提取所有笑话、幽默段子或有趣内容。
要求:
1. 只返回真正的笑话内容,不要提取普通文章或新闻
2. 每条笑话需要包含:title(简短标题)、content(完整笑话内容)、type(类型)、crowd(人群)
3. 如果网页中没有笑话,返回空数组 []
4. 永远返回合法的 JSON 格式,根节点为数组或包含 jokes 键的对象"""
_CRAWLER_REWRITE_DEFAULT = """你是一个幽默作家,负责润色和改写笑话。
要求:
1. 保持笑话的核心笑点不变
2. 语言更通顺、更幽默
3. 字数控制在原内容的 80%-120% 之间
4. 不要添加任何解释说明"""
def _migrate_db():
from sqlalchemy import inspect, text
inspector = inspect(engine)
columns = [c["name"] for c in inspector.get_columns("ai_settings")]
# 新增提示词字段
prompt_fields = {
"generate_prompt": _GENERATE_PROMPT_DEFAULT,
"optimizer_quality_prompt": _OPTIMIZER_QUALITY_DEFAULT,
"optimizer_polish_prompt": _OPTIMIZER_POLISH_DEFAULT,
"optimizer_evaluate_prompt": _OPTIMIZER_EVALUATE_DEFAULT,
"crawler_extract_prompt": _CRAWLER_EXTRACT_DEFAULT,
"crawler_rewrite_prompt": _CRAWLER_REWRITE_DEFAULT,
}
for field, default_val in prompt_fields.items():
if field not in columns:
from sqlalchemy import Text
col_type = "TEXT"
with engine.connect() as conn:
conn.execute(text(f"ALTER TABLE ai_settings ADD COLUMN {field} {col_type}"))
conn.commit()
# 新增 temperature 字段
temp_fields = [
("optimizer_quality_temperature", "FLOAT", "0.3"),
("optimizer_polish_temperature", "FLOAT", "0.8"),
("optimizer_evaluate_temperature", "FLOAT", "0.3"),
]
for field, col_type, default_val in temp_fields:
if field not in columns:
with engine.connect() as conn:
conn.execute(text(f"ALTER TABLE ai_settings ADD COLUMN {field} {col_type} DEFAULT {default_val}"))
conn.commit()
# 给新增字段填充默认值(已有记录)
with engine.connect() as conn:
for field, default_val in prompt_fields.items():
conn.execute(text(f"UPDATE ai_settings SET {field} = :val WHERE {field} IS NULL"),
{"val": default_val})
conn.commit()
_migrate_db()
# Create FastAPI application
app = FastAPI(title=API_TITLE, version=API_VERSION)
# Configure CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Mount routers
app.include_router(jokes_router, prefix="/api")
app.include_router(categories_router, prefix="/api")
app.include_router(auth_router, prefix="/api")
app.include_router(admin_router, prefix="/api")
app.include_router(settings_router, prefix="/api")
app.include_router(links_router, prefix="/api")
app.include_router(feedback_router, prefix="/api")
app.include_router(generate_router, prefix="/api")
app.include_router(submit_router, prefix="/api/jokes") # 公开提交接口
@app.get("/")
def root():
return {"message": "欢迎使用笑话大全 API"}
@app.get("/health")
def health_check():
return {"status": "healthy"}