SAkizuki commited on
Commit
6164549
·
verified ·
1 Parent(s): 843fa13

Auto-sync from GitHub Actions

Browse files
Files changed (4) hide show
  1. .gitignore +2 -1
  2. README.md +2 -0
  3. core/engine.py +15 -4
  4. mcp_server.py +9 -4
.gitignore CHANGED
@@ -17,4 +17,5 @@ eval/
17
  legacy_history.json
18
  CLAUDE.md
19
  *.zip
20
- .claude/
 
 
17
  legacy_history.json
18
  CLAUDE.md
19
  *.zip
20
+ .claude/
21
+ docs/
README.md CHANGED
@@ -466,6 +466,8 @@ npm install -g mcp-remote
466
  | `min_cooc` | `3` | 单个 (tag, artist) 对的最小共现次数 |
467
  | `show_nsfw` | `true` | 是否包含 NSFW 数据 |
468
 
 
 
469
  ### 调用示例
470
 
471
  接入后,你可以直接用自然语言告诉 AI 你的需求,AI 会自动选择合适的参数调用工具:
 
466
  | `min_cooc` | `3` | 单个 (tag, artist) 对的最小共现次数 |
467
  | `show_nsfw` | `true` | 是否包含 NSFW 数据 |
468
 
469
+ 返回字段:`artist`(画师名)、`cooc_count`(共现次数)、`post_count`(作品数)、`sources`(命中标签)、`top_tags`(该画师最常画的 10 个标签,含中文名)
470
+
471
  ### 调用示例
472
 
473
  接入后,你可以直接用自然语言告诉 AI 你的需求,AI 会自动选择合适的参数调用工具:
core/engine.py CHANGED
@@ -121,7 +121,7 @@ CAT_MAP: dict[str, str] = {
121
  '0': 'General', '1': 'Artist', '3': 'Copyright', '4': 'Character', '5': 'Meta',
122
  }
123
 
124
- SCHEMA_VERSION = 3 # 升级此值将自动触发全量重建,用于破坏性格式变更
125
 
126
  # 用户显式分隔后,纯 CJK 片段超过此长度仍用 jieba 切分(避免长句被当作原子概念)
127
  _ATOMIC_CJK_MAX_LEN = 7
@@ -690,7 +690,10 @@ class DanbooruTagger:
690
  def _encode_all_and_save(self) -> None:
691
  print('[Engine] 全量编码...')
692
  for _, attr, col in _LAYER_SPEC:
693
- setattr(self, attr, self._encode_texts(self.df[col].tolist()))
 
 
 
694
  self._save_cache()
695
 
696
  # ── 增量更新 ──────────────────────────────────────────────────────────
@@ -734,7 +737,12 @@ class DanbooruTagger:
734
 
735
  if changed_names:
736
  changed_rows = new_df[new_df['name'].isin(set(changed_names))].reset_index(drop=True)
737
- _vecs = {attr: self._encode_texts(changed_rows[col].tolist()) for _, attr, col in _LAYER_SPEC}
 
 
 
 
 
738
  for j, name in enumerate(changed_rows['name']):
739
  ci = cached_idx[name]
740
  for _, attr, _ in _LAYER_SPEC:
@@ -745,7 +753,10 @@ class DanbooruTagger:
745
  if added_names:
746
  added_rows = new_df[new_df['name'].isin(set(added_names))].reset_index(drop=True)
747
  for _, attr, col in _LAYER_SPEC:
748
- vecs = self._encode_texts(added_rows[col].tolist())
 
 
 
749
  setattr(self, attr, torch.cat([getattr(self, attr), vecs], dim=0))
750
  self.df = pd.concat([self.df, added_rows], ignore_index=True)
751
 
 
121
  '0': 'General', '1': 'Artist', '3': 'Copyright', '4': 'Character', '5': 'Meta',
122
  }
123
 
124
+ SCHEMA_VERSION = 4 # 升级此值将自动触发全量重建,用于破坏性格式变更
125
 
126
  # 用户显式分隔后,纯 CJK 片段超过此长度仍用 jieba 切分(避免长句被当作原子概念)
127
  _ATOMIC_CJK_MAX_LEN = 7
 
690
  def _encode_all_and_save(self) -> None:
691
  print('[Engine] 全量编码...')
692
  for _, attr, col in _LAYER_SPEC:
693
+ texts = self.df[col].tolist()
694
+ if col == 'name': # 英文层:编码时将下划线替换为空格
695
+ texts = [t.replace('_', ' ') for t in texts]
696
+ setattr(self, attr, self._encode_texts(texts))
697
  self._save_cache()
698
 
699
  # ── 增量更新 ──────────────────────────────────────────────────────────
 
737
 
738
  if changed_names:
739
  changed_rows = new_df[new_df['name'].isin(set(changed_names))].reset_index(drop=True)
740
+ _vecs = {}
741
+ for _, attr, col in _LAYER_SPEC:
742
+ texts = changed_rows[col].tolist()
743
+ if col == 'name': # 英文层:编码时将下划线替换为空格
744
+ texts = [t.replace('_', ' ') for t in texts]
745
+ _vecs[attr] = self._encode_texts(texts)
746
  for j, name in enumerate(changed_rows['name']):
747
  ci = cached_idx[name]
748
  for _, attr, _ in _LAYER_SPEC:
 
753
  if added_names:
754
  added_rows = new_df[new_df['name'].isin(set(added_names))].reset_index(drop=True)
755
  for _, attr, col in _LAYER_SPEC:
756
+ texts = added_rows[col].tolist()
757
+ if col == 'name': # 英文层:编码时将下划线替换为空格
758
+ texts = [t.replace('_', ' ') for t in texts]
759
+ vecs = self._encode_texts(texts)
760
  setattr(self, attr, torch.cat([getattr(self, attr), vecs], dim=0))
761
  self.df = pd.concat([self.df, added_rows], ignore_index=True)
762
 
mcp_server.py CHANGED
@@ -354,11 +354,10 @@ async def get_artist_recommendations(
354
 
355
  JSON array sorted by NPMI score (descending). Each result:
356
  - artist: Danbooru artist tag name
357
- - score: Aggregated NPMI score (higher = stronger association)
358
  - cooc_count: Total co-occurrence count across all input tags
359
  - post_count: Artist's total post count on Danbooru
360
  - sources: Input tags that matched this artist
361
- - hit_count: Number of input tags that matched
362
  """
363
  tagger = await DanbooruTagger.get_instance()
364
 
@@ -410,15 +409,18 @@ async def get_artist_recommendations(
410
  corrected_tags, limit=limit, min_cooc=min_cooc,
411
  )
412
 
 
 
 
 
413
  output = []
414
  for r in results:
415
  item = {
416
  "artist": r.artist,
417
- "score": round(r.score, 4),
418
  "cooc_count": r.cooc_count,
419
  "post_count": r.post_count,
420
  "sources": r.sources,
421
- "hit_count": r.hit_count,
422
  }
423
  output.append(item)
424
 
@@ -483,6 +485,7 @@ Anima 是一个 2B 参数的文生图模型(CircleStone Labs × Comfy Org)
483
 
484
  - 所有标签小写,下划线 `_` 替换为空格。**唯一例外**:`score_1` 到 `score_9` 保持下划线。
485
  - 标签内括号用反斜杠转义:`momoko (momopoco)` → `momoko \\(momopoco\\)`
 
486
  - 标签间用一个逗号加一个空格连接:`tag a, tag b, tag c`
487
  - 不要编造不存在的标签。若不确定某标签是否存在,将该概念放入自然语言段落。
488
  - Tag Dropout 机制意味着不需要塞入每一个相关标签——只保留最关键和区分性最强的。
@@ -528,6 +531,8 @@ Anima 是一个 2B 参数的文生图模型(CircleStone Labs × Comfy Org)
528
 
529
  格式:`@nnn yryr`, `@big chungus`
530
 
 
 
531
  ### 数据集标签(非动漫风格时的备选)
532
  在提示词最开头另起一行使用,可大幅改变风格倾向:
533
  - `ye-pop`:LAION-POP 数据集风格,偏抽象/油画/概念艺术
 
354
 
355
  JSON array sorted by NPMI score (descending). Each result:
356
  - artist: Danbooru artist tag name
 
357
  - cooc_count: Total co-occurrence count across all input tags
358
  - post_count: Artist's total post count on Danbooru
359
  - sources: Input tags that matched this artist
360
+ - top_tags: Top 10 tags this artist most frequently draws (with Chinese names)
361
  """
362
  tagger = await DanbooruTagger.get_instance()
363
 
 
409
  corrected_tags, limit=limit, min_cooc=min_cooc,
410
  )
411
 
412
+ # 获取每个画师最常画的标签
413
+ artist_names = [r.artist for r in results]
414
+ top_tags_map = tagger.get_artist_top_tags(artist_names, show_nsfw=show_nsfw)
415
+
416
  output = []
417
  for r in results:
418
  item = {
419
  "artist": r.artist,
 
420
  "cooc_count": r.cooc_count,
421
  "post_count": r.post_count,
422
  "sources": r.sources,
423
+ "top_tags": top_tags_map.get(r.artist, []),
424
  }
425
  output.append(item)
426
 
 
485
 
486
  - 所有标签小写,下划线 `_` 替换为空格。**唯一例外**:`score_1` 到 `score_9` 保持下划线。
487
  - 标签内括号用反斜杠转义:`momoko (momopoco)` → `momoko \\(momopoco\\)`
488
+ - 画师标签前面加一个 `@` 符号
489
  - 标签间用一个逗号加一个空格连接:`tag a, tag b, tag c`
490
  - 不要编造不存在的标签。若不确定某标签是否存在,将该概念放入自然语言段落。
491
  - Tag Dropout 机制意味着不需要塞入每一个相关标签——只保留最关键和区分性最强的。
 
531
 
532
  格式:`@nnn yryr`, `@big chungus`
533
 
534
+ 一段提示词中最多包含3个艺术家标签。
535
+
536
  ### 数据集标签(非动漫风格时的备选)
537
  在提示词最开头另起一行使用,可大幅改变风格倾向:
538
  - `ye-pop`:LAION-POP 数据集风格,偏抽象/油画/概念艺术