SAkizuki commited on
Commit
aeae670
ยท
1 Parent(s): 2b9340d

Upload cli.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. cli.py +128 -0
cli.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ cli.py
3
+ โ”€โ”€โ”€โ”€โ”€โ”€
4
+ ๅ‘ฝไปค่กŒ้€‚้…ๅฑ‚๏ผˆๅฏ้€‰๏ผ‰ใ€‚
5
+
6
+ ๅญๅ‘ฝไปค๏ผš
7
+ search ่ฏญไน‰ๆœ็ดขๆ ‡็ญพ
8
+ related ๅŸบไบŽๅ…ฑ็Žฐ่กจๆŸฅๅ…ณ่”ๆŽจ่
9
+
10
+ ็”จๆณ•๏ผš
11
+ python cli.py search "็™ฝ่‰ฒๆฐดๆ‰‹ๆœ็š„ๅฅณๅญฉ" --limit 10 --no-nsfw
12
+ python cli.py related "white_serafuku,sailor_collar" --limit 20
13
+ python cli.py related "white_serafuku,sailor_collar" --no-nsfw --show-sources
14
+ """
15
+
16
+ import argparse
17
+ import asyncio
18
+
19
+ from core.engine import DanbooruTagger
20
+ from core.models import SearchRequest
21
+
22
+
23
+ # โ”€โ”€ search โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
24
+
25
+ async def cmd_search(args):
26
+ tagger = await DanbooruTagger.get_instance()
27
+ request = SearchRequest(
28
+ query=args.query,
29
+ top_k=args.top_k,
30
+ limit=args.limit,
31
+ popularity_weight=args.weight,
32
+ show_nsfw=not args.no_nsfw,
33
+ use_segmentation=not args.no_seg,
34
+ )
35
+ resp = await asyncio.to_thread(tagger.search, request)
36
+
37
+ print(f"\n{'='*60}")
38
+ print(f"ๆŸฅ่ฏข๏ผš{args.query} | ๅ…ฑ {len(resp.results)} ๆก็ป“ๆžœ")
39
+ print(f"{'='*60}")
40
+ print(f"ๆŽจ่ Prompt๏ผš\n {resp.tags_sfw if args.no_nsfw else resp.tags_all}\n")
41
+
42
+ for r in resp.results:
43
+ nsfw_mark = "๐Ÿ”ด" if r.nsfw == '1' else "๐ŸŸข"
44
+ print(f" {nsfw_mark} [{r.final_score:.3f}] {r.tag:<30} {r.cn_name[:20]:<20} {r.category}")
45
+
46
+
47
+ # โ”€โ”€ related โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
48
+
49
+ async def cmd_related(args):
50
+ seed_tags = [t.strip() for t in args.tags.split(',') if t.strip()]
51
+ if not seed_tags:
52
+ print("้”™่ฏฏ๏ผš่ฏทๆไพ›่‡ณๅฐ‘ไธ€ไธช็งๅญๆ ‡็ญพ๏ผŒๅคšไธชๆ ‡็ญพไปฅ้€—ๅทๅˆ†้š”ใ€‚")
53
+ return
54
+
55
+ tagger = await DanbooruTagger.get_instance()
56
+ results = await asyncio.to_thread(
57
+ tagger.get_related,
58
+ seed_tags,
59
+ set(seed_tags), # exclude ็งๅญๆ ‡็ญพ่‡ช่บซ
60
+ args.limit,
61
+ not args.no_nsfw,
62
+ )
63
+
64
+ if not results:
65
+ print("ๆœชๆ‰พๅˆฐๅ…ณ่”ๆŽจ่๏ผˆๅ…ฑ็Žฐ่กจๅฏ่ƒฝๆœชๅŠ ่ฝฝ๏ผŒๆˆ–็งๅญๆ ‡็ญพไธๅœจๅบ“ไธญ๏ผ‰ใ€‚")
66
+ return
67
+
68
+ print(f"\n{'='*60}")
69
+ print(f"็งๅญๆ ‡็ญพ๏ผš{', '.join(seed_tags)} | ๅ…ฑ {len(results)} ๆกๆŽจ่")
70
+ print(f"{'='*60}")
71
+
72
+ # ่พ“ๅ‡บ้€—ๅทๅˆ†้š”็š„ๆ ‡็ญพไธฒ๏ผˆๆ–นไพฟ็›ดๆŽฅๅคๅˆถไฝฟ็”จ๏ผ‰
73
+ tag_list = [r.tag for r in results if not (r.nsfw == '1' and args.no_nsfw)]
74
+ print(f"ๆŽจ่ๆ ‡็ญพ๏ผš\n {', '.join(tag_list)}\n")
75
+
76
+ # ๆ˜Ž็ป†่กจ
77
+ for r in results:
78
+ if r.nsfw == '1' and args.no_nsfw:
79
+ continue
80
+ nsfw_mark = "๐Ÿ”ด" if r.nsfw == '1' else "๐ŸŸข"
81
+ sources_str = f" โ† {', '.join(r.sources)}" if args.show_sources else ""
82
+ print(
83
+ f" {nsfw_mark} [{r.cooc_score:.3f}] {r.tag:<30}"
84
+ f" {r.cn_name[:20]:<20} {r.category}"
85
+ f" (ๅ…ฑ็Žฐ:{r.cooc_count:,}){sources_str}"
86
+ )
87
+
88
+
89
+ # โ”€โ”€ ๅ…ฅๅฃ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
90
+
91
+ async def main():
92
+ parser = argparse.ArgumentParser(
93
+ description="Danbooru Tag CLI Searcher",
94
+ formatter_class=argparse.RawDescriptionHelpFormatter,
95
+ epilog="""
96
+ ็คบไพ‹๏ผš
97
+ python cli.py search "็™ฝ่‰ฒๆฐดๆ‰‹ๆœ็š„ๅฅณๅญฉ" --limit 10
98
+ python cli.py related "white_serafuku,sailor_collar"
99
+ python cli.py related "white_serafuku" --limit 30 --no-nsfw --show-sources
100
+ """,
101
+ )
102
+ sub = parser.add_subparsers(dest='cmd', required=True)
103
+
104
+ # โ”€โ”€ search ๅญๅ‘ฝไปค โ”€โ”€
105
+ p_search = sub.add_parser('search', help='่ฏญไน‰ๆœ็ดขๆ ‡็ญพ')
106
+ p_search.add_argument('query', help='ๆœ็ดข่ฏ๏ผˆๆ”ฏๆŒไธญ่‹ฑๆ–‡่‡ช็„ถ่ฏญ่จ€๏ผ‰')
107
+ p_search.add_argument('--top-k', type=int, default=5, help='ๆฏๅฑ‚่ฟ”ๅ›žๆ•ฐ้‡๏ผˆ้ป˜่ฎค 5๏ผ‰')
108
+ p_search.add_argument('--limit', type=int, default=20, help='็ป“ๆžœไธŠ้™๏ผˆ้ป˜่ฎค 20๏ผ‰')
109
+ p_search.add_argument('--weight', type=float, default=0.15, help='็ƒญๅบฆๆƒ้‡๏ผˆ้ป˜่ฎค 0.15๏ผ‰')
110
+ p_search.add_argument('--no-nsfw', action='store_true', help='่ฟ‡ๆปค NSFW ๅ†…ๅฎน')
111
+ p_search.add_argument('--no-seg', action='store_true', help='็ฆ็”จๆ™บ่ƒฝๅˆ†่ฏ')
112
+
113
+ # โ”€โ”€ related ๅญๅ‘ฝไปค โ”€โ”€
114
+ p_related = sub.add_parser('related', help='ๅŸบไบŽๅ…ฑ็Žฐ่กจๆŸฅๅ…ณ่”ๆŽจ่')
115
+ p_related.add_argument('tags', help='็งๅญๆ ‡็ญพ๏ผŒไปฅ่‹ฑๆ–‡้€—ๅทๅˆ†้š”๏ผˆๅฆ‚ white_serafuku,sailor_collar๏ผ‰')
116
+ p_related.add_argument('--limit', type=int, default=50, help='ๆŽจ่็ป“ๆžœไธŠ้™๏ผˆ้ป˜่ฎค 50๏ผ‰')
117
+ p_related.add_argument('--no-nsfw', action='store_true', help='่ฟ‡ๆปค NSFW ๅ†…ๅฎน')
118
+ p_related.add_argument('--show-sources', action='store_true', help='ๆ˜พ็คบๆฏๆกๆŽจ่็”ฑๅ“ชไธช็งๅญ่งฆๅ‘')
119
+
120
+ args = parser.parse_args()
121
+ if args.cmd == 'search':
122
+ await cmd_search(args)
123
+ elif args.cmd == 'related':
124
+ await cmd_related(args)
125
+
126
+
127
+ if __name__ == "__main__":
128
+ asyncio.run(main())