186 lines
6.1 KiB
Python
186 lines
6.1 KiB
Python
import argparse
|
|
import glob as glob_module
|
|
import logging
|
|
import os
|
|
import sys
|
|
|
|
if sys.stdout.encoding and sys.stdout.encoding.lower() == "gbk":
|
|
sys.stdout.reconfigure(encoding="utf-8")
|
|
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
|
datefmt="%H:%M:%S",
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def cmd_process(args):
|
|
from meeting_processor import meeting_processor
|
|
|
|
filepath = args.file
|
|
if not os.path.exists(filepath):
|
|
print(f"错误:文件不存在 {filepath}")
|
|
sys.exit(1)
|
|
|
|
print(f"正在处理会议文件:{filepath}")
|
|
archive_path = meeting_processor.process_meeting_file(filepath, force=getattr(args, "force", False))
|
|
|
|
if archive_path:
|
|
print("\n处理完成")
|
|
print(f"原文归档:{archive_path}")
|
|
else:
|
|
print("\n处理失败或已跳过")
|
|
sys.exit(1)
|
|
|
|
|
|
def cmd_text(args):
|
|
from meeting_processor import meeting_processor
|
|
|
|
print("正在处理会议文本...")
|
|
archive_path = meeting_processor.process_meeting_text(args.text, force=getattr(args, "force", False))
|
|
if archive_path:
|
|
print("\n处理完成")
|
|
print(f"原文归档:{archive_path}")
|
|
else:
|
|
print("\n处理失败或已跳过")
|
|
|
|
|
|
def cmd_query(args):
|
|
from meeting_processor import meeting_processor
|
|
|
|
print(f"查询:{args.question}")
|
|
print("-" * 40)
|
|
result = meeting_processor.query(args.question, top_k=args.top_k)
|
|
print(result if result else "未找到相关信息")
|
|
|
|
|
|
def cmd_stats(args):
|
|
from meeting_processor import meeting_processor
|
|
|
|
stats = meeting_processor.stats()
|
|
print("会议记忆系统统计")
|
|
print("-" * 40)
|
|
print(f"向量节点数:{stats.get('vector_index', {}).get('node_count', 0)}")
|
|
print(f"Neo4j 启用:{stats.get('graph', {}).get('enabled', False)}")
|
|
print(f"图谱会议数:{stats.get('graph', {}).get('meetings', 0)}")
|
|
print(f"图谱实体数:{stats.get('graph', {}).get('entities', 0)}")
|
|
print(f"行动项数:{stats.get('state', {}).get('action_items_tracked', 0)}")
|
|
print(f"指标数:{stats.get('state', {}).get('metrics_tracked', 0)}")
|
|
print(f"会议系列数:{stats.get('state', {}).get('meeting_series', 0)}")
|
|
print(f"原文归档目录:{stats.get('raw_dir', '')}")
|
|
print(f"状态文件:{stats.get('state_path', '')}")
|
|
|
|
|
|
def cmd_batch(args):
|
|
from meeting_processor import meeting_processor
|
|
|
|
files = glob_module.glob(args.pattern, recursive=True)
|
|
if not files:
|
|
print(f"未匹配到任何文件:{args.pattern}")
|
|
sys.exit(1)
|
|
|
|
print(f"找到 {len(files)} 个文件,开始批量处理...")
|
|
success = 0
|
|
for path in files:
|
|
try:
|
|
print(f"\n处理:{path}")
|
|
result = meeting_processor.process_meeting_file(path, force=getattr(args, "force", False))
|
|
if result:
|
|
success += 1
|
|
except Exception as exc:
|
|
logger.error("处理失败: %s - %s", path, exc)
|
|
|
|
print(f"\n批量处理完成:{success}/{len(files)} 成功")
|
|
|
|
|
|
def cmd_interactive():
|
|
from meeting_processor import meeting_processor
|
|
|
|
print("会议纪要长期记忆系统")
|
|
print("=" * 50)
|
|
print("可用命令:")
|
|
print(" query <问题> 语义查询会议记忆")
|
|
print(" process <路径> 处理会议文件")
|
|
print(" stats 查看统计")
|
|
print(" help 显示帮助")
|
|
print(" exit/quit 退出")
|
|
print("=" * 50)
|
|
|
|
while True:
|
|
try:
|
|
line = input("\n> ").strip()
|
|
except (EOFError, KeyboardInterrupt):
|
|
print()
|
|
break
|
|
|
|
if not line:
|
|
continue
|
|
if line in ("exit", "quit", "q"):
|
|
break
|
|
if line == "help":
|
|
print(" query <问题>")
|
|
print(" process <路径>")
|
|
print(" stats")
|
|
print(" exit/quit")
|
|
continue
|
|
if line == "stats":
|
|
cmd_stats(None)
|
|
continue
|
|
if line.startswith("process "):
|
|
filepath = line[8:].strip()
|
|
if not os.path.exists(filepath):
|
|
print(f"文件不存在:{filepath}")
|
|
continue
|
|
result = meeting_processor.process_meeting_file(filepath)
|
|
print(f"完成:{result}" if result else "处理失败或已跳过")
|
|
continue
|
|
|
|
question = line[6:].strip() if line.startswith("query ") else line
|
|
result = meeting_processor.query(question, top_k=3)
|
|
print(result if result else "未找到相关信息")
|
|
|
|
print("bye!")
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="会议纪要长期记忆系统")
|
|
subparsers = parser.add_subparsers(dest="command")
|
|
|
|
p_process = subparsers.add_parser("process", help="处理会议 markdown 文件")
|
|
p_process.add_argument("file", help="会议文件路径")
|
|
p_process.add_argument("-f", "--force", action="store_true", help="发现重复时自动覆盖")
|
|
|
|
p_text = subparsers.add_parser("text", help="直接处理一段会议文本")
|
|
p_text.add_argument("text", help="会议文本内容")
|
|
p_text.add_argument("-f", "--force", action="store_true", help="发现重复时自动覆盖")
|
|
|
|
p_query = subparsers.add_parser("query", help="语义查询会议记忆")
|
|
p_query.add_argument("question", help="查询问题")
|
|
p_query.add_argument("--top-k", type=int, default=3, help="返回结果数量")
|
|
|
|
subparsers.add_parser("stats", help="查看统计")
|
|
|
|
p_batch = subparsers.add_parser("batch", help="批量处理会议文件")
|
|
p_batch.add_argument("pattern", help="glob 模式,如 meetings/*.md")
|
|
p_batch.add_argument("-f", "--force", action="store_true", help="发现重复时自动覆盖")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.command == "process":
|
|
cmd_process(args)
|
|
elif args.command == "text":
|
|
cmd_text(args)
|
|
elif args.command == "query":
|
|
cmd_query(args)
|
|
elif args.command == "stats":
|
|
cmd_stats(args)
|
|
elif args.command == "batch":
|
|
cmd_batch(args)
|
|
else:
|
|
cmd_interactive()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|