mirror of
https://github.com/xr843/Master-skill.git
synced 2026-05-10 05:16:25 +00:00
feat: add --brief flag to rag_query.py to reduce output verbosity
- New --brief flag for semantic/search subcommands outputs one-line-per-result (title + link + 80-char snippet) instead of full 500-char excerpts - Reduces output from ~60 lines to ~7 lines per query (3 results) - /compare-masters now uses --brief by default (multiple queries no longer flood the terminal with long excerpts) - Full output (default) preserved for single-master /ask and debugging
This commit is contained in:
@@ -118,11 +118,13 @@ PROJECT_ROOT="$(dirname "$(dirname "$(dirname "$SKILL_FILE")")")"
|
|||||||
|
|
||||||
2. **加载法师角色内容**:`$PROJECT_ROOT/prebuilt/{slug}/teaching.md` 和 `voice.md`
|
2. **加载法师角色内容**:`$PROJECT_ROOT/prebuilt/{slug}/teaching.md` 和 `voice.md`
|
||||||
|
|
||||||
3. **执行语义检索**:
|
3. **执行语义检索**(使用 `--brief` 减少输出冗余):
|
||||||
```bash
|
```bash
|
||||||
python3 "$PROJECT_ROOT/tools/rag_query.py" semantic "<问题>" --top_k 3
|
python3 "$PROJECT_ROOT/tools/rag_query.py" semantic "<问题>" --top_k 3 --brief
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`--brief` 模式每条结果只显示 2 行(经名+链接+80字摘要),避免 60+ 行的完整经文内容刷屏。
|
||||||
|
|
||||||
4. **过滤结果**:根据该法师 meta.json 的 `search_scope.primary_cbeta_ids` 过滤检索结果
|
4. **过滤结果**:根据该法师 meta.json 的 `search_scope.primary_cbeta_ids` 过滤检索结果
|
||||||
|
|
||||||
5. **降级处理**:若 `rag_query.py` 不可达(路径解析失败或 FoJin API 不可用),改用 teaching.md 中已验证的 FoJin 链接作为出处,并在回答开头提示"本次检索基于预置内容"
|
5. **降级处理**:若 `rag_query.py` 不可达(路径解析失败或 FoJin API 不可用),改用 teaching.md 中已验证的 FoJin 链接作为出处,并在回答开头提示"本次检索基于预置内容"
|
||||||
|
|||||||
+48
-6
@@ -19,12 +19,26 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|||||||
from fojin_bridge import create_bridge, FojinUnavailableError
|
from fojin_bridge import create_bridge, FojinUnavailableError
|
||||||
|
|
||||||
|
|
||||||
def format_search_results(data: dict) -> str:
|
def format_search_results(data: dict, brief: bool = False) -> str:
|
||||||
"""Format keyword search results for LLM consumption."""
|
"""Format keyword search results for LLM consumption."""
|
||||||
items = data.get("items") or data.get("results") or []
|
items = data.get("items") or data.get("results") or []
|
||||||
if not items:
|
if not items:
|
||||||
return "未找到相关结果。"
|
return "未找到相关结果。"
|
||||||
|
|
||||||
|
if brief:
|
||||||
|
total = data.get("total", len(items))
|
||||||
|
lines = [f"关键词搜索 {total} 条,显示 {len(items)}:"]
|
||||||
|
for i, item in enumerate(items, 1):
|
||||||
|
title = item.get("title", "无标题")
|
||||||
|
text_id = item.get("text_id", item.get("id", ""))
|
||||||
|
link = f"https://fojin.app/texts/{text_id}" if text_id else ""
|
||||||
|
snippet = item.get("highlight", item.get("snippet", item.get("content", "")))
|
||||||
|
snippet_str = str(snippet).strip().replace("\n", " ")[:80]
|
||||||
|
lines.append(f"{i}. {title} — {link}")
|
||||||
|
if snippet_str:
|
||||||
|
lines.append(f" {snippet_str}...")
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
for i, item in enumerate(items, 1):
|
for i, item in enumerate(items, 1):
|
||||||
title = item.get("title", "无标题")
|
title = item.get("title", "无标题")
|
||||||
@@ -42,7 +56,6 @@ def format_search_results(data: dict) -> str:
|
|||||||
if text_id:
|
if text_id:
|
||||||
lines.append(f"FoJin链接: https://fojin.app/texts/{text_id}")
|
lines.append(f"FoJin链接: https://fojin.app/texts/{text_id}")
|
||||||
if snippet:
|
if snippet:
|
||||||
# Truncate long snippets
|
|
||||||
snippet_str = str(snippet)
|
snippet_str = str(snippet)
|
||||||
if len(snippet_str) > 500:
|
if len(snippet_str) > 500:
|
||||||
snippet_str = snippet_str[:500] + "..."
|
snippet_str = snippet_str[:500] + "..."
|
||||||
@@ -54,12 +67,39 @@ def format_search_results(data: dict) -> str:
|
|||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
def format_semantic_results(data: dict) -> str:
|
def format_semantic_results(data: dict, brief: bool = False) -> str:
|
||||||
"""Format semantic search results for LLM consumption."""
|
"""Format semantic search results for LLM consumption.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data: API response dict
|
||||||
|
brief: If True, output one-line-per-result (compact mode for meta-skills
|
||||||
|
like /compare-masters). If False, output full content excerpts.
|
||||||
|
"""
|
||||||
items = data.get("items") or data.get("results") or []
|
items = data.get("items") or data.get("results") or []
|
||||||
if not items:
|
if not items:
|
||||||
return "语义检索未找到相关经文。"
|
return "语义检索未找到相关经文。"
|
||||||
|
|
||||||
|
if brief:
|
||||||
|
lines = [f"语义检索 {len(items)} 条:"]
|
||||||
|
for i, item in enumerate(items, 1):
|
||||||
|
title = item.get("title", "无标题")
|
||||||
|
score = item.get("score", item.get("similarity", ""))
|
||||||
|
content = item.get("content", item.get("snippet", item.get("text", "")))
|
||||||
|
text_id = item.get("text_id", item.get("id", ""))
|
||||||
|
juan = item.get("juan_num", item.get("juan", ""))
|
||||||
|
|
||||||
|
link = f"https://fojin.app/texts/{text_id}" if text_id else ""
|
||||||
|
if text_id and juan:
|
||||||
|
link += f"/juan/{juan}"
|
||||||
|
|
||||||
|
score_str = f" (score={score:.2f})" if isinstance(score, (int, float)) else ""
|
||||||
|
snippet = str(content).strip().replace("\n", " ")[:80]
|
||||||
|
|
||||||
|
lines.append(f"{i}. {title}{score_str} — {link}")
|
||||||
|
if snippet:
|
||||||
|
lines.append(f" {snippet}...")
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
lines = [f"语义检索返回 {len(items)} 条相关经文:\n"]
|
lines = [f"语义检索返回 {len(items)} 条相关经文:\n"]
|
||||||
for i, item in enumerate(items, 1):
|
for i, item in enumerate(items, 1):
|
||||||
title = item.get("title", "无标题")
|
title = item.get("title", "无标题")
|
||||||
@@ -158,13 +198,13 @@ def format_kg_results(data: dict) -> str:
|
|||||||
def cmd_search(args):
|
def cmd_search(args):
|
||||||
bridge = create_bridge()
|
bridge = create_bridge()
|
||||||
result = bridge.search_texts(args.query, sources=args.sources, size=args.top_k)
|
result = bridge.search_texts(args.query, sources=args.sources, size=args.top_k)
|
||||||
print(format_search_results(result))
|
print(format_search_results(result, brief=args.brief))
|
||||||
|
|
||||||
|
|
||||||
def cmd_semantic(args):
|
def cmd_semantic(args):
|
||||||
bridge = create_bridge()
|
bridge = create_bridge()
|
||||||
result = bridge.semantic_search(args.query, top_k=args.top_k)
|
result = bridge.semantic_search(args.query, top_k=args.top_k)
|
||||||
print(format_semantic_results(result))
|
print(format_semantic_results(result, brief=args.brief))
|
||||||
|
|
||||||
|
|
||||||
def cmd_dict(args):
|
def cmd_dict(args):
|
||||||
@@ -192,12 +232,14 @@ def main():
|
|||||||
p_search.add_argument("query", help="搜索关键词")
|
p_search.add_argument("query", help="搜索关键词")
|
||||||
p_search.add_argument("--sources", default=None, help="限定来源,如 cbeta")
|
p_search.add_argument("--sources", default=None, help="限定来源,如 cbeta")
|
||||||
p_search.add_argument("--top_k", type=int, default=5, help="返回条数 (默认 5)")
|
p_search.add_argument("--top_k", type=int, default=5, help="返回条数 (默认 5)")
|
||||||
|
p_search.add_argument("--brief", action="store_true", help="简洁输出(一行一条)")
|
||||||
p_search.set_defaults(func=cmd_search)
|
p_search.set_defaults(func=cmd_search)
|
||||||
|
|
||||||
# semantic
|
# semantic
|
||||||
p_sem = subparsers.add_parser("semantic", help="语义向量检索")
|
p_sem = subparsers.add_parser("semantic", help="语义向量检索")
|
||||||
p_sem.add_argument("query", help="语义查询")
|
p_sem.add_argument("query", help="语义查询")
|
||||||
p_sem.add_argument("--top_k", type=int, default=5, help="返回条数 (默认 5)")
|
p_sem.add_argument("--top_k", type=int, default=5, help="返回条数 (默认 5)")
|
||||||
|
p_sem.add_argument("--brief", action="store_true", help="简洁输出(一行一条)")
|
||||||
p_sem.set_defaults(func=cmd_semantic)
|
p_sem.set_defaults(func=cmd_semantic)
|
||||||
|
|
||||||
# dict
|
# dict
|
||||||
|
|||||||
Reference in New Issue
Block a user