Feat/ai tag suggestion#55
Merged
Merged
Conversation
Plan 2,覆盖 spec §特性 2。9 个 TDD 任务:TS 类型 → validator → 特征 提取 → prompt → 编排 → AISuggestModal → 测试 → Tags.vue 集成 → ship。 全前端,无 Rust 改动(schema 已存在)。
- stripJsonFences 改用 regex,容忍 AI 输出前后的散文 / 单行 fence - parseAndValidate 在 root 不是对象(如 null)时给出明确报错 - 补 3 个 MatchRefresh 变体测试(average 缺 metric / streak 大小写) - 补 3 个递归 TagCondition 测试(and 嵌套合法 / and 嵌入非法 / not 包装错值)
orchestrator 串联 get_my_summoner → get_match_history_by_puuid → featureExtract → requestAIContent → parseAndValidate → sessionStorage 缓存; markAdopted 供 AISuggestModal 采用后标灰态; 7 单元测试覆盖 ok / insufficient / aiError / parseError / 缓存命中 / forceRefresh。
There was a problem hiding this comment.
Pull request overview
Adds an “AI 推荐” workflow to the Tags settings page: it fetches the current user’s recent matches, builds an AI prompt to generate tag rules, validates the AI JSON strictly, shows suggestions in a modal, and allows one-click adoption into persisted TagConfigs.
Changes:
- Integrate an
AI 推荐button +AISuggestModalintoTags.vue, refreshing tag list after adoption. - Introduce
tagSuggestservice (feature extraction → prompt → AI request → validation → sessionStorage cache + adopted marker). - Add comprehensive Vitest coverage for validator/prompt/extraction/orchestrator + modal component behavior.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| lol-record-analysis-tauri/src/views/settings/Tags.vue | Adds AI button + mounts AISuggestModal, reloads tags after adopt |
| lol-record-analysis-tauri/src/components/tags/AISuggestModal.vue | Modal UI for loading/empty/error/ok states and “adopt” flow |
| lol-record-analysis-tauri/src/types/tagSuggest.ts | TS schema mirror for TagCondition/TagConfig + AI result types |
| lol-record-analysis-tauri/src/services/ai/tagSuggest/index.ts | Orchestrates fetching matches, calling AI, validating, caching |
| lol-record-analysis-tauri/src/services/ai/tagSuggest/validator.ts | Strict schema validator + JSON fence stripping |
| lol-record-analysis-tauri/src/services/ai/tagSuggest/prompt.ts | System + user prompt construction |
| lol-record-analysis-tauri/src/services/ai/tagSuggest/featureExtract.ts | Extracts compact per-game features for AI input |
| lol-record-analysis-tauri/src/services/ai/tagSuggest/tests/*.spec.ts | Unit tests for tagSuggest pipeline modules |
| lol-record-analysis-tauri/src/components/tags/tests/AISuggestModal.spec.ts | Component tests for modal rendering and actions |
| docs/superpowers/plans/2026-05-02-ai-tag-suggestion.md | Implementation plan/design notes for the feature |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+87
to
+90
| it('generates id (uuid) and sets isDefault=false / enabled=true', () => { | ||
| const raw = JSON.stringify({ good: [suggestion()], bad: [] }) | ||
| const r = parseAndValidate(raw) | ||
| expect(r.good[0].id).toMatch(/[a-f0-9-]+/) |
| import { invoke } from '@tauri-apps/api/core' | ||
| import TagConditionNode from './TagConditionNode.vue' | ||
| import AISuggestModal from '@renderer/components/tags/AISuggestModal.vue' | ||
| import { championOption } from '../../components/type' |
- 编排器把 puuid 暴露在 ok outcome 里 + 模块级缓存,消除 adopt() 里的 第二次 get_my_summoner 调用以及缓存命中时的多余 IPC - rawCacheKey 清理移到 finally,AI throw 时也不留 sessionStorage 垃圾 - 好/坏标签卡片渲染用 v-for sections 去重 ~46 行模板
- validator 测试 stub crypto.randomUUID,断言用确定值代替 lenient 正则 - Tags.vue championOption 改用 canonical 路径 + import type
实测 AI 会输出 filter "gold>=12000" + refresh "average gold>=12000" 这种永远 成立的套套逻辑,且没样本量门槛。 - SYSTEM_PROMPT 加 3 类常见错误示例 + 2 条良好 few-shot 规则(中路稳健 / 暮气沉沉) - validator 增加 hasFilterRefreshTautology,filter.Stat 和 refresh.Average/Sum/Max/Min 同 metric + 同 op 时拒绝(误杀风险低,因为没有合理用例)
…拒绝模式不一致 实测 AI 把娱乐模式数据贴上"排位..."标签,desc 和 filter.queue 完全脱节。 - GameFeature 加 queueName 字段(小队列 id 表覆盖排位+常见娱乐模式),AI 输入直接看到中文模式名 - SYSTEM_PROMPT 加"模式严格分开" + "desc 必须与 filter 一致"两条硬约束 + 反例 + 大乱斗 few-shot - validator 增加 descMatchesQueueScope:含娱乐 queueId 时 desc 不能含"排位",反之亦然
- validator: NAME_MAX 5→7(让 name 能塞下"模式前缀+主题+调侃") - validator: 新增 hasNonSrLaneWord,filter 全是娱乐模式时 name/desc 不能含 上路/中路/下路/打野/辅助/ADC 等 SR 路位词 - prompt: 鼓励"儒雅+调侃"语气,强制非 SR 模式去路位 - few-shot 改成更有梗的"排位刺客 / 乱斗咆哮王 / 暮气连败王"
- QUEUE_NAMES 扩展到 ~20 个常见模式(含 海克斯乱斗、飞升、雪球、AI 等) - 未知 queueId 默认 '娱乐模式'(绝大多数情况下成立),不再返回信息量为 0 的'其他模式' - 新增分类 fallback:未知但属于 ranked/matchmaking 范围的归为对应类别
编排器调用 get_game_modes 拿到 Rust 维护的中文映射并注入 gameToFeature; featureExtract 只保留分类兜底(排位/匹配/娱乐模式)。新模式以后只在 Rust 那边加一行就能流到 AI 输入,不需要改 TS。 - featureExtract: 移除 QUEUE_NAMES 硬编码 map,新增 QueueNameMap 注入参数 - index: 模块级缓存 get_game_modes 结果,requestTagSuggestions 一次性拉取 - prompt: 简化模式参考块(AI 直接用 queueName)
实测 AI 输出: - "海克斯混子" 配高伤害规则归到好标签 → 命名负面 vs 分类褒义 互相打脸 - "乱斗高光" 配 desc "海克斯乱斗" → 不同队列 (450 vs 2400) 用了模糊词 - validator: 好标签 name 含 混子/翻车/水货/咸鱼/废物/掉分/演员/弱鸡/荣鸡/坑货/送人头 → 拒绝 - prompt: 加"好/坏命名情绪一致" + "name 和 desc 模式名必须一致"两条硬约束 + 海克斯乱斗 few-shot
wnzzer
added a commit
that referenced
this pull request
May 3, 2026
- validator 测试 stub crypto.randomUUID,断言用确定值代替 lenient 正则 - Tags.vue championOption 改用 canonical 路径 + import type
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.