chore: track claude skills, tools, templates, reference code and research-wiki

- Add all claude skills (brainstorming, commit, debugging, TDD, etc.)
- Add claude hooks (pre-commit-guard, post-edit-quality)
- Add research templates (experiment plan, research brief, etc.)
- Add claude tools (arxiv/semantic_scholar/openalex fetch, wiki, exa)
- Add TRM4 reference implementation as algorithm fidelity baseline
- Add research-wiki content (plans, index, graph, query_pack)
- Update .gitignore to exclude .graphify_version runtime state
This commit is contained in:
2026-07-06 20:59:03 -04:00
parent 0616d16956
commit 6bdb802f01
98 changed files with 19321 additions and 0 deletions
+235
View File
@@ -0,0 +1,235 @@
"""
推理/演示入口
=============
从原始文档(文本或视频)构建 TreeIndex,执行问答。
与 ``train.py``(训练入口)配对,是 Video-Tree-TRM 的端到端演示入口。
子命令
------
- ``index``: 仅构建并缓存 TreeIndex,不执行问答。
- ``query``: 构建索引(或复用缓存)后执行问答。
使用示例::
# 仅构建文本索引
python main.py index --source data/doc.txt --modality text
# 单次问答(视频)
python main.py query --source data/video.mp4 --modality video \\
--question "视频的主要内容是什么?"
# 交互式多轮问答(文本)
python main.py query --source data/doc.txt --modality text --interactive
# 自定义配置
python main.py query --source data/doc.txt --modality text \\
--config config/default.yaml --env .env \\
--question "文档结论是什么?"
"""
from __future__ import annotations
import argparse
import sys
from utils.logger_system import log_msg
from video_tree_trm.config import Config
from video_tree_trm.pipeline import Pipeline
# ---------------------------------------------------------------------------
# CLI 解析
# ---------------------------------------------------------------------------
def _parse_args() -> argparse.Namespace:
"""解析 CLI 参数,返回 Namespace。
返回:
包含子命令及所有选项的 Namespace 对象。
"""
parser = argparse.ArgumentParser(
prog="main.py",
description="Video-Tree-TRM 推理/演示入口",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
# 公共参数
common = argparse.ArgumentParser(add_help=False)
common.add_argument(
"--config",
default="config/default.yaml",
metavar="YAML",
help="配置文件路径(默认: config/default.yaml",
)
common.add_argument(
"--env",
default=".env",
metavar="ENV",
help="环境变量文件路径(默认: .env",
)
common.add_argument(
"--source",
required=True,
metavar="PATH",
help="原始文件路径(文本文件或视频文件)",
)
common.add_argument(
"--modality",
required=True,
choices=["text", "video"],
help="文件模态:text 或 video",
)
subparsers = parser.add_subparsers(dest="command", title="子命令")
subparsers.required = True
# ── index 子命令 ──
subparsers.add_parser(
"index",
parents=[common],
help="构建并缓存 TreeIndex(不执行问答)",
description="从原始文件构建三层树索引并保存到缓存目录。",
)
# ── query 子命令 ──
query_parser = subparsers.add_parser(
"query",
parents=[common],
help="构建索引并执行问答",
description="构建索引后执行单次问答或交互式多轮问答。",
)
mode_group = query_parser.add_mutually_exclusive_group(required=True)
mode_group.add_argument(
"--question",
metavar="TEXT",
help="单次问答:问题字符串",
)
mode_group.add_argument(
"--interactive",
action="store_true",
help="交互式多轮问答模式(输入 quit 退出)",
)
return parser.parse_args()
# ---------------------------------------------------------------------------
# 配置加载
# ---------------------------------------------------------------------------
def _load_config(args: argparse.Namespace) -> Config:
"""从 YAML + .env 加载配置。
参数:
args: CLI 解析结果,需含 configYAML 路径)和 env.env 路径)字段。
返回:
完整的 Config 实例。
异常:
FileNotFoundError: 配置文件不存在。
TypeError: YAML 缺少必需字段。
"""
log_msg("INFO", "加载配置", yaml_path=args.config, env_path=args.env)
return Config.load(
yaml_path=args.config,
env_path=args.env,
)
# ---------------------------------------------------------------------------
# 子命令实现
# ---------------------------------------------------------------------------
def cmd_index(args: argparse.Namespace) -> None:
"""index 子命令:构建并缓存 TreeIndex,打印缓存路径。
参数:
args: 含 source、modality、config、env 字段的 Namespace。
"""
config = _load_config(args)
pipeline = Pipeline(config)
log_msg("INFO", "开始构建索引", source=args.source, modality=args.modality)
tree = pipeline.build_index(args.source, args.modality)
print(f"索引构建完成。模态={args.modality},来源={args.source}")
print(f"节点数量: L1={len(tree.roots)}")
log_msg("INFO", "索引构建完成", l1_count=len(tree.roots))
def cmd_query(args: argparse.Namespace) -> None:
"""query 子命令:构建索引 → 单次或交互式问答。
参数:
args: 含 source、modality、question/interactive、config、env 字段的 Namespace。
实现细节:
- 先调用 build_index(缓存命中时直接加载,无额外开销)。
- --question 模式:单次问答后退出。
- --interactive 模式:循环读取用户输入,输入 'quit' 退出。
"""
config = _load_config(args)
pipeline = Pipeline(config)
log_msg("INFO", "构建/加载索引", source=args.source, modality=args.modality)
tree = pipeline.build_index(args.source, args.modality)
if args.question:
# Phase 1: 单次问答
answer = pipeline.query(args.question, tree)
print(f"\n问题: {args.question}")
print(f"答案: {answer}\n")
log_msg("INFO", "问答完成", question=args.question[:50])
else:
# Phase 2: 交互式多轮问答
print("\n已进入交互式问答模式。输入 'quit' 退出。\n")
while True:
try:
question = input("问题 (输入 'quit' 退出): ").strip()
except (EOFError, KeyboardInterrupt):
print("\n再见。")
break
if question.lower() in ("quit", "exit", "q"):
print("再见。")
break
if not question:
continue
answer = pipeline.query(question, tree)
print(f"答案: {answer}\n")
log_msg("INFO", "交互式问答", question=question[:50])
# ---------------------------------------------------------------------------
# 主入口
# ---------------------------------------------------------------------------
def main() -> None:
"""主入口:解析参数 → 分发子命令。
退出码:
0: 正常退出。
1: 参数错误或运行时异常。
"""
args = _parse_args()
try:
if args.command == "index":
cmd_index(args)
elif args.command == "query":
cmd_query(args)
except (FileNotFoundError, TypeError, ValueError) as exc:
print(f"错误: {exc}", file=sys.stderr)
log_msg("ERROR", f"main.py 异常退出: {exc}")
sys.exit(1)
if __name__ == "__main__":
main()