Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Auto-sync from GitHub Actions
Browse files- .gitignore +2 -1
- README.md +2 -0
- core/engine.py +15 -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 =
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
| 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 = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
| 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 |
-
-
|
| 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 |
-
"
|
| 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 数据集风格,偏抽象/油画/概念艺术
|