File size: 6,050 Bytes
c2179b0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | #!/usr/bin/env python3
"""
AgentFrame CLI — 命令行工具
============================
用法:
agentframe serve [--port 8090] [--config config.json]
agentframe ingest "文本" [--tags a,b] [--session <sid>] [--state <path>]
agentframe ask "问题" [--no-chat] [--hands] [--state <path>]
agentframe stats [--state <path>]
agentframe forget [--threshold 0.15] [--state <path>]
agentframe config [--output config.json]
agentframe demo
"""
import argparse
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from agentframe.config import AgentFrameConfig
from agentframe.core.engine import ContextEngine
DEFAULT_STATE = "/var/lib/agentframe/cli.json"
def load_engine(config_path: str = None, state_path: str = None) -> ContextEngine:
config = AgentFrameConfig.from_file(config_path) if config_path else AgentFrameConfig.from_env()
eng = ContextEngine(config)
sp = state_path or DEFAULT_STATE
if os.path.exists(sp):
eng.load(sp)
return eng
def cmd_serve(args):
from agentframe.api.server import AgentFrameAPI
config = AgentFrameConfig.from_file(args.config) if args.config else AgentFrameConfig.from_env()
api = AgentFrameAPI(config)
print(f"🚀 AgentFrame API — http://{config.api.host}:{args.port or config.api.port}")
api.app.run(host=config.api.host, port=args.port or config.api.port,
debug=config.api.debug)
def cmd_ingest(args):
eng = load_engine(args.config, args.state)
tags = args.tags.split(",") if args.tags else []
cid = eng.ingest(args.text, tags)
sp = args.state or DEFAULT_STATE
os.makedirs(os.path.dirname(sp), exist_ok=True)
eng.save(sp)
print(f"✅ 摄入 chunk_{cid}: {args.text[:50]}...")
print(f" 标签: {tags} | 已存: {sp}")
def cmd_ask(args):
eng = load_engine(args.config, args.state)
if args.hands:
result = eng.ask_with_hands(args.query)
else:
result = eng.ask(args.query, chat=not args.no_chat)
print(f"\n🧠 检索到 {len(result.retrieved)} 块:")
for cid, prev in result.retrieved:
print(f" chunk_{cid}: {prev}...")
if result.answer:
print(f"\n💬 回答:\n{result.answer}")
sp = args.state or DEFAULT_STATE
eng.save(sp)
def cmd_stats(args):
eng = load_engine(args.config, args.state)
for k, v in eng.stats().items():
print(f" {k}: {v}")
def cmd_forget(args):
eng = load_engine(args.config, args.state)
victims = eng.forget(args.threshold)
sp = args.state or DEFAULT_STATE
eng.save(sp)
print(f"🧹 遗忘 {len(victims)} 块: {victims}")
print(f" 剩余: {len(eng.agent.chunk_meta)} 块")
def cmd_config(args):
config = AgentFrameConfig.from_env()
out = args.output or "agentframe.config.json"
config.save(out)
print(f"✅ 配置已写入: {out}")
print(f" LLM: {config.llm.provider} / {config.llm.model}")
print(f" Memory: {config.memory.n_layers}层 INT{config.memory.quant_bits} top-k={config.memory.top_k}")
print(f" API: {config.api.host}:{config.api.port}")
def cmd_demo(args):
"""离线演示: 摄入 → 查询 → 遗忘 (无 API key 也可跑)"""
config = AgentFrameConfig.from_env()
config.llm.provider = "mock"
eng = ContextEngine(config)
print("=" * 56)
print("AgentFrame 离线演示 (Mock LLM)")
print("=" * 56)
chunks = [
{"text": "KV 缓存 270KB/token 展开存储", "tags": ["data"]},
{"text": "吸收式 MLA 缓存 576 维潜在向量", "tags": ["method"]},
{"text": "L40S 实测 35.6x 压缩", "tags": ["data", "result"]},
{"text": "注意力分数不等于任务重要性", "tags": ["agent"]},
]
for c in chunks:
cid = eng.ingest(c["text"], c["tags"])
print(f" 📥 摄入 chunk_{cid}: {c['text']}")
print(f"\n [存储] {eng.stats()['layers']}")
print(f" [压缩] {eng.stats()['bytes_per_token']} B/token")
r = eng.ask("KV压缩能到多少倍?", chat=True)
print(f"\n 🧠 检索: {r.retrieved}")
print(f" 💬 回答: {r.answer}")
v = eng.forget(0.3)
print(f"\n 🧹 遗忘: {len(v)} 块 → 剩余 {len(eng.agent.chunk_meta)} 块")
print("\n✅ 演示完成")
def main():
p = argparse.ArgumentParser(prog="agentframe", description="AgentFrame 上下文保持框架")
sub = p.add_subparsers(dest="cmd")
pserve = sub.add_parser("serve", help="启动 API 服务")
pserve.add_argument("--port", type=int, default=None)
pserve.add_argument("--config", default=None)
pi = sub.add_parser("ingest", help="摄入知识")
pi.add_argument("text")
pi.add_argument("--tags", default=None)
pi.add_argument("--config", default=None)
pi.add_argument("--state", default=None)
pa = sub.add_parser("ask", help="查询")
pa.add_argument("query")
pa.add_argument("--no-chat", action="store_true")
pa.add_argument("--hands", action="store_true")
pa.add_argument("--config", default=None)
pa.add_argument("--state", default=None)
pst = sub.add_parser("stats", help="状态")
pst.add_argument("--config", default=None)
pst.add_argument("--state", default=None)
pf = sub.add_parser("forget", help="遗忘")
pf.add_argument("--threshold", type=float, default=0.15)
pf.add_argument("--config", default=None)
pf.add_argument("--state", default=None)
pc = sub.add_parser("config", help="生成配置")
pc.add_argument("--output", default=None)
sub.add_parser("demo", help="离线演示")
args = p.parse_args()
if args.cmd == "serve":
cmd_serve(args)
elif args.cmd == "ingest":
cmd_ingest(args)
elif args.cmd == "ask":
cmd_ask(args)
elif args.cmd == "stats":
cmd_stats(args)
elif args.cmd == "forget":
cmd_forget(args)
elif args.cmd == "config":
cmd_config(args)
elif args.cmd == "demo":
cmd_demo(args)
else:
p.print_help()
if __name__ == "__main__":
main()
|