Skip to content

feat(character): 创建角色时用 LLM 从描述补名称 - #329

Open
xiaocheny214 wants to merge 3 commits into
1024XEngineer:mainfrom
xiaocheny214:feat/character-name-from-description
Open

feat(character): 创建角色时用 LLM 从描述补名称#329
xiaocheny214 wants to merge 3 commits into
1024XEngineer:mainfrom
xiaocheny214:feat/character-name-from-description

Conversation

@xiaocheny214

@xiaocheny214 xiaocheny214 commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • POST /charactersname 为空或纯空白时,用 description 经 ai_engine 的 LangChain 起名器生成不超过 20 字的名称再入库。
  • 用户填写的名称优先。LLM 失败或超时则截断 description;两者都空则用「未命名角色」。创建不因起名失败而 500。
  • 起名器在 bootstrap 注入,避免 web → character.service 碰到 ai_engine

Refs #188
Close #188

本次只做后端。Quick Start / Workflow Editor 的选填名称留给后续 PR。

变更

  • CharacterNamerPort + LangChainCharacterNamercreate_chat_model(),不是 Agent)
  • resolve_character_namecreate_character 落库前解析最终名称

Test plan

  • 用户名称优先,不调用 LLM
  • 空名称走假 namer / 失败兜底 / 「未命名角色」
  • LangChain 起名器注入假 chat model,清洗引号并截断 20 字
  • POST /characters 不带 name 时写入生成名
  • import-linter 两条契约 KEPT
  • 接真实 AI_* 配置后,用一段角色描述创建角色,确认名称非空且 ≤20 字

POST /characters 在 name 为空时,经 ai_engine 的 LangChain 起名器从 description 生成不超过 20 字的名称。用户填写的名称优先;LLM 失败则截断描述,都空则用「未命名角色」。

Refs 1024XEngineer#188

Co-authored-by: Cursor <[email protected]>
@vercel

vercel Bot commented Aug 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
windup Ignored Ignored Preview Aug 15, 2026 10:54am

@codecov

codecov Bot commented Aug 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.10145% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ngine/src/windup_ai_engine/impl/character_namer.py 90.47% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查结论

自动命名的分层与请求级失败兜底方向合理,但当前装配和配置会使默认环境无法启动,或让 LLM 起名路径持续退化为描述截断;现有 workflow_run_id 幂等重试还会新增无效的付费调用。已按固定 base/head SHA 核对完整 diff 与 #188 契约。仓库环境没有可执行的 uv,因此未运行 pytest;使用 langchain-openai==1.4.0 单独复现了无凭据构造异常以及空模型名被保留的行为。

View job run

# 起名器在 composition root 注入,避免 web→character.service 碰到 ai_engine。
# 测试若已注入假 namer,不要覆盖。
if character_service._namer is None:
character_service._namer = LangChainCharacterNamer()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 避免在应用启动时强制创建 ChatOpenAI

create_app() 现在无条件构造 LangChainCharacterNamer,其构造函数会立即调用 ChatOpenAI;当本地、测试或仅使用非聊天 AI 能力的部署没有设置 AI_API_KEY 时,langchain-openai==1.4.0 会在这里直接抛出 OpenAIError: Missing credentials。这样应用连健康检查都无法启动,请求内 resolve_character_name 的异常兜底也没有机会执行。请延迟到实际起名调用时再创建模型(让该异常落入现有兜底),或在 bootstrap 中容忍未配置聊天 provider。

"""``CharacterNamerPort`` 的 LangChain 实现。"""

def __init__(self, chat_model: Any | None = None) -> None:
self._model = chat_model if chat_model is not None else create_chat_model()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 为起名调用配置非空的聊天模型

这里使用通用 create_chat_model(),它读取 AIProviderSettings.model;该字段默认值是空字符串,而仓库 .env.example 只配置了 AI_IMAGE_MODELAI_VIDEO_MODEL,没有 AI_MODEL。因此按仓库示例部署时会得到 ChatOpenAI(model=""),每次空名称请求都会因无效模型失败并静默退化为描述截断,PR 宣称的 LLM 起名路径实际上不会工作。请为起名器提供明确的非空模型配置/默认值,并把对应环境变量加入部署契约。

fields = dict(fields)
name = fields.get("name")
namer = None if (name or "").strip() else self._namer
fields["name"] = resolve_character_name(name, fields.get("description"), namer)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 在付费起名前先处理 workflow_run 幂等

POST /characters 的幂等语义是先插入,再在唯一约束冲突时返回已有角色;但这行现在会在 session.flush() 之前调用起名器。于是同一个 workflow_run_id 的正常重试只要 name 为空,就会先执行一次最长 120 秒且可能付费的 LLM 调用,随后才触发 IntegrityError 并丢弃生成结果。请在通常的重试路径上先查询已有角色/建立唯一性,再解析名称;并保留唯一约束处理并发竞态。

xiaocheny214 and others added 2 commits August 15, 2026 18:45
CI 没有 AI_API_KEY 时,装配期创建 ChatOpenAI 会让所有走 create_app 的测试在 setup 失败。LangChain 客户端推迟到第一次起名再构建。

Co-authored-by: Cursor <[email protected]>
create_chat_model 在空 key/空型号时先拒绝,避免 ChatOpenAI(model="")。
同 workflow_run_id 先查已有角色再起名。装配期仍不创建 ChatOpenAI。

Co-authored-by: Cursor <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 支持角色名称填写与自动提取

1 participant