Gliding Horse 的Token经济学:用 IRI 指针替代文本,让 Token 花在刀刃上
摘要:Gliding Horse(流马)作为 AI Agent 操作系统,提出了一套以"IRI 指针 + 摘要"为核心的上下文优化体系。通过将大段工具结果和历史对话转化为可寻址的 IRI 指针,Token 消耗从随数据量线性增长变为近恒定,单次任务平均节省约 47% 的 Token,同时关键信息可 100% 追溯。本文深入解析其核心思想、架构设计、Token 优化工具箱及实测收益,为构建长周期、多步骤的自主 Agent 提供可落地的 Token 经济学方案。
关键词:Gliding Horse;流马;Token 经济学;上下文管理;IRI 指针;AI Agent;摘要链;JSON‑LD;Token 优化;大模型
对于 AI Agent 来说,上下文窗口就是金钱。每次调用大模型,Prompt 的 Token 消耗直接决定了成本和响应延迟。而多轮对话中,如果不加控制地把历史对话、工具返回的大段 JSON、文件内容全塞进去,Token 会以 O(n) 的速度爆炸,瞬间耗光珍贵的窗口,导致模型"失忆"或拒绝服务。
Gliding Horse(流马)作为 AI Agent 操作系统,把上下文管理 和Token 经济学 视为内核级能力。我们设计了一套以 "IRI 指针 + 摘要" 为核心的上下文优化体系,彻底摆脱了"保留原文 → 截断丢弃"的死循环。下面就把这套系统的设计思路、关键机制和落地效果完整展开。
一、核心思想:从"保留全部"到"按需引用"
传统 Agent 处理长上下文的套路很粗暴:尽量保留,超出窗口就截断或让 LLM 自己总结。这导致:
- 截断丢弃了可能关键的信息;
- LLM 总结可能遗漏细节甚至产生幻觉;
- 大工具结果(如
grep返回几万字符)直接把上下文撑爆。
Gliding Horse 的做法截然不同:完整内容存入图数据库(L0/L2),上下文中只保留简短的摘要和一个全球唯一的 IRI(类似 URL) 。当 LLM 真正需要细节时,可以像点击链接一样,通过内置工具沿着 IRI 精确查询。这套机制的基石就是全系统统一的 JSON‑LD 语义总线 ,任何一个数据块都有 @id,天然可寻址。
传统:上下文 = 全部历史 + 全部工具结果 → Token 爆炸 → 截断丢失
流马:上下文 = 摘要链 + IRI 指针 → Token 恒定 → 按需检索
二、上下文管理引擎架构
上下文引擎位于应用层,与记忆系统、工具系统、投影引擎深度集成。每次 LLM 调用前,它按以下流水线组装最终 Prompt:
#mermaid-svg-9lpVZmaW7ygLmCqA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9lpVZmaW7ygLmCqA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9lpVZmaW7ygLmCqA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9lpVZmaW7ygLmCqA .error-icon{fill:#552222;}#mermaid-svg-9lpVZmaW7ygLmCqA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9lpVZmaW7ygLmCqA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9lpVZmaW7ygLmCqA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9lpVZmaW7ygLmCqA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9lpVZmaW7ygLmCqA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9lpVZmaW7ygLmCqA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9lpVZmaW7ygLmCqA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9lpVZmaW7ygLmCqA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9lpVZmaW7ygLmCqA .marker.cross{stroke:#333333;}#mermaid-svg-9lpVZmaW7ygLmCqA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9lpVZmaW7ygLmCqA p{margin:0;}#mermaid-svg-9lpVZmaW7ygLmCqA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-9lpVZmaW7ygLmCqA .cluster-label text{fill:#333;}#mermaid-svg-9lpVZmaW7ygLmCqA .cluster-label span{color:#333;}#mermaid-svg-9lpVZmaW7ygLmCqA .cluster-label span p{background-color:transparent;}#mermaid-svg-9lpVZmaW7ygLmCqA .label text,#mermaid-svg-9lpVZmaW7ygLmCqA span{fill:#333;color:#333;}#mermaid-svg-9lpVZmaW7ygLmCqA .node rect,#mermaid-svg-9lpVZmaW7ygLmCqA .node circle,#mermaid-svg-9lpVZmaW7ygLmCqA .node ellipse,#mermaid-svg-9lpVZmaW7ygLmCqA .node polygon,#mermaid-svg-9lpVZmaW7ygLmCqA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9lpVZmaW7ygLmCqA .rough-node .label text,#mermaid-svg-9lpVZmaW7ygLmCqA .node .label text,#mermaid-svg-9lpVZmaW7ygLmCqA .image-shape .label,#mermaid-svg-9lpVZmaW7ygLmCqA .icon-shape .label{text-anchor:middle;}#mermaid-svg-9lpVZmaW7ygLmCqA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-9lpVZmaW7ygLmCqA .rough-node .label,#mermaid-svg-9lpVZmaW7ygLmCqA .node .label,#mermaid-svg-9lpVZmaW7ygLmCqA .image-shape .label,#mermaid-svg-9lpVZmaW7ygLmCqA .icon-shape .label{text-align:center;}#mermaid-svg-9lpVZmaW7ygLmCqA .node.clickable{cursor:pointer;}#mermaid-svg-9lpVZmaW7ygLmCqA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-9lpVZmaW7ygLmCqA .arrowheadPath{fill:#333333;}#mermaid-svg-9lpVZmaW7ygLmCqA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9lpVZmaW7ygLmCqA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9lpVZmaW7ygLmCqA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9lpVZmaW7ygLmCqA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-9lpVZmaW7ygLmCqA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9lpVZmaW7ygLmCqA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-9lpVZmaW7ygLmCqA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9lpVZmaW7ygLmCqA .cluster text{fill:#333;}#mermaid-svg-9lpVZmaW7ygLmCqA .cluster span{color:#333;}#mermaid-svg-9lpVZmaW7ygLmCqA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9lpVZmaW7ygLmCqA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-9lpVZmaW7ygLmCqA rect.text{fill:none;stroke-width:0;}#mermaid-svg-9lpVZmaW7ygLmCqA .icon-shape,#mermaid-svg-9lpVZmaW7ygLmCqA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9lpVZmaW7ygLmCqA .icon-shape p,#mermaid-svg-9lpVZmaW7ygLmCqA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-9lpVZmaW7ygLmCqA .icon-shape .label rect,#mermaid-svg-9lpVZmaW7ygLmCqA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9lpVZmaW7ygLmCqA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-9lpVZmaW7ygLmCqA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-9lpVZmaW7ygLmCqA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户输入 / 上一轮结果
SystemPromptBuilder
L3 投影引擎
按需从图库提取相关子图
模板引擎
注入角色专属提示词
组装上下文
结果路由器
工具结果→摘要+IRI
L1 会话摘要链
累积历史
最终 Prompt
Token 预算内
LLM 调用
- SystemPromptBuilder:构建结构化的系统消息,注入当前 Agent 角色(PA/DA/CA/AA)的宪法准则、激活的方法论以及可用工具清单。
- L3 投影引擎:利用 SPARQL 查询从 L0 持久化图中提取当前任务最相关的知识(例如相关技能、历史决策),以 JSON‑LD 子图形式注入,避免冗余。
- 结果路由器:工具返回的大结果被统一处理,生成摘要和 IRI,原始数据存档。
- L1 会话摘要链 :每一轮对话的
summary自动追加到 L1,形成高度压缩的"记忆流";当超过 Token 预算时,较久远的摘要被淘汰到 L0,但保留 IRI 供回溯。
三、工具结果 IRI 化:把 15KB 变成 200 字节
Agent 执行工具调用时,返回的数据往往非常庞大------grep 搜索结果可能有 15KB,curl 的网页响应甚至上百 KB。如果直接注入上下文,几次调用就能耗光所有 Token。
流马的设计是:所有 ≥2KB 的工具结果,自动触发"IRI 化"处理 ,由 ResultRouter 统一完成:
-
内容存储 :原始结果写入 L0 持久化图,分配唯一 IRI(如
iri://tool-result/call_abc)。 -
生成微工具 :同时注册一个专用的读取工具(如
read_full_result_call_abc),供 Agent 后续按需调用。 -
消息替换:将原本的大段结果替换为一条简洁的摘要消息,包含工具名、数据量级和 IRI。
优化前消息(grep 搜索结果,15KB):
[tool] content: "找到 47 处匹配,位于 12 个文件:\n
src/auth.rs:42: let token = ... (后续数千行匹配详情)"优化后消息(约 200 字节):
[grep_search] [已存档] 47 matches in 12 files | iri://tool-result/call_abc
如果 LLM 需要查看具体匹配内容,可以随时调用微工具 read_full_result_call_abc,系统会从图库中取出完整数据返回。Token 消耗从随结果线性增长变成近恒定,关键信息还不会丢失。
四、跨轮摘要引用化:历史对话永不丢失
多轮对话是 Agent 工作的常态。流马采用分层摘要链管理对话历史:
- L1 工作记忆 :每轮 LLM 回复中强制要求输出
summary字段,由系统追加到 L1 的摘要缓冲区。这些摘要极短(几十字),累积起来也只占极少 Token。 - L0 归档 :完整的
thought推理过程和content回答内容被存档到 L0,并返回 IRI(如iri://archive/task/xxx/turn_5)。 - 淘汰保留 IRI:当 L1 摘要过多触发淘汰时,被淘汰的摘要不会消失,而是将其对应的 IRI 移入"弱引用"列表,仍然可以在需要时找回。
当发生消息截断(当前硬顶为 30 条消息)时,我们不再插入一句模糊的"之前已执行 5 轮操作",而是生成结构化历史引用:
[历史摘要]
[轮1/PA] 制定分析计划 → iri://archive/task/xxx/turn_1
[轮2/DA] 搜索认证接口 (grep×3) → iri://archive/task/xxx/turn_2
[轮3/DA] 分析JWT流程 → iri://archive/task/xxx/turn_3
如需详细信息,请使用 kg_search / knowledge_query 查询 IRI。
这样,LLM 即便在长对话中也能清晰知道之前做过什么,且可以主动检索任何一轮的完整细节。关键决策链得以完整保留,不再被截断抹除。
五、Token 优化工具箱
除了 IRI 化与摘要链,流马还配备了一套完整的 Token 优化组件,全部实装并集成到主循环中:
| 组件 | 功能 | 收益 |
|---|---|---|
| ToolGroupManager | 按 Agent 角色(PA/DA/CA/AA)只暴露允许的工具列表 | 减少 Prompt 中工具定义的 Token |
| ContextWindowManager | 智能压缩历史消息,优先保留近期和关键信息 | 将有效轮次从 ~15 轮提升至 50+ 轮 |
| ToolResultCompressor | 对工具结果做摘要压缩,保留核心字段 | 避免大 JSON 直接撑爆窗口 |
| 微工具系统 | 为每个大结果自动注册专用查询工具 | LLM 无需保留原始数据,需要时再查 |
| L1 语义淘汰策略 | 根据时间、语义相关度和 Token 成本计算淘汰分数,精准丢弃最不重要的摘要 | 保证重要信息长期驻留 |
六、配置化与性能收益
整个上下文优化系统通过 config.yaml 集中控制,开发者可以根据自己的模型窗口和成本敏感度灵活调整:
yaml
context_optimization:
enabled: true
tool_result_iri:
threshold: 2048 # ≥2KB 的结果自动 IRI 化
preview_size: 500 # 消息中保留的摘要长度
cross_turn_summary:
max_summary_turns: 10 # 截断时保留的最近轮数
summary_length: 100 # 每轮摘要最大字符
tool_result_compressor:
enabled: true
max_full_results: 2 # 最多保留完整结果数
max_summary_length: 200
context_window:
enabled: true
max_messages: 30
max_tokens: 16000
compression_ratio: 0.3
经过完整实现后,我们实测获得了显著的 Token 节省效果:
| 典型工具调用 | 优化前消息体 | 优化后消息体 | 缩减比例 |
|---|---|---|---|
grep_search(15KB 结果) |
15KB JSON | ~200 字节摘要+IRI | 98.7% |
file_read(5KB 文件) |
5KB | ~500 字节 | 90% |
web_fetch(30KB 网页) |
~2KB 摘要 | ~500 字节 | 75% |
bash 命令输出(20KB) |
~2KB 摘要 | ~500 字节 | 75% |
总体来看,单次任务的平均上下文 Token 消耗降低了约 47%,同时关键信息的可追溯率达到 100%(只要 IRI 存在,数据就永不丢失)。
八、实战代码示例
下面通过一个完整的 Python 示例,展示如何在 Agent 工作流中调用 Gliding Horse 的上下文优化功能。该示例模拟了一个执行 grep 搜索的 Agent,演示 IRI 指针和微工具系统如何避免大结果撑爆上下文。
python
import json
import hashlib
from typing import Optional, Dict, Any
from dataclasses import dataclass, field
# ============================================================
# 模拟 Gliding Horse 上下文优化核心组件
# ============================================================
@dataclass
class ToolResult:
"""工具执行结果"""
tool_name: str
raw_content: str
content_size: int
iri: Optional[str] = None
summary: Optional[str] = None
micro_tool_name: Optional[str] = None
class L0GraphStore:
"""模拟 L0 持久化图存储(实际为图数据库)"""
def __init__(self):
self._store: Dict[str, str] = {}
def store(self, iri: str, content: str) -> None:
self._store[iri] = content
def retrieve(self, iri: str) -> Optional[str]:
return self._store.get(iri)
class ResultRouter:
"""
结果路由器:将大工具结果 IRI 化
- 内容 ≥2KB 自动触发 IRI 化
- 生成摘要 + 注册微工具
"""
def __init__(self, graph_store: L0GraphStore, threshold: int = 2048):
self.graph = graph_store
self.threshold = threshold
self._call_counter = 0
def process(self, tool_name: str, raw_content: str) -> ToolResult:
result = ToolResult(
tool_name=tool_name,
raw_content=raw_content,
content_size=len(raw_content.encode("utf-8"))
)
if result.content_size >= self.threshold:
# 1. 生成唯一 IRI
self._call_counter += 1
content_hash = hashlib.sha256(raw_content.encode()).hexdigest()[:12]
iri = f"iri://tool-result/{tool_name}_{self._call_counter}_{content_hash}"
# 2. 存储完整内容到 L0
self.graph.store(iri, raw_content)
# 3. 注册微工具名称
micro_tool = f"read_full_{tool_name}_{self._call_counter}"
# 4. 生成摘要(取前 200 字符 + 统计信息)
lines = raw_content.split("\n")
match_count = len([l for l in lines if l.strip()])
summary = (
f"[{tool_name}] 共 {match_count} 行结果,"
f"大小 {result.content_size} 字节 | {iri}"
)
result.iri = iri
result.summary = summary
result.micro_tool_name = micro_tool
else:
# 小结果直接保留原文
result.summary = raw_content
return result
class ContextManager:
"""
上下文管理器:组装最终 Prompt
- 工具结果用摘要 + IRI 替代
- 历史对话用摘要链管理
"""
def __init__(self, router: ResultRouter, max_messages: int = 30):
self.router = router
self.max_messages = max_messages
self.history: list = []
def add_tool_call(self, tool_name: str, raw_content: str) -> ToolResult:
"""添加工具调用结果,自动 IRI 化"""
result = self.router.process(tool_name, raw_content)
self.history.append({
"type": "tool_result",
"summary": result.summary,
"iri": result.iri,
"micro_tool": result.micro_tool_name
})
return result
def build_prompt(self, user_query: str) -> str:
"""组装最终 Prompt(仅含摘要 + IRI,不含原始大结果)"""
# 截断历史到最大消息数
recent_history = self.history[-self.max_messages:] if len(self.history) > self.max_messages else self.history
prompt_parts = [
"## 系统指令",
"你是一个 AI Agent,可以使用工具执行任务。",
"工具结果已优化:大结果以摘要+IRI形式呈现,",
"如需查看完整内容,请调用对应的微工具。",
"",
"## 用户查询",
user_query,
"",
"## 历史工具调用摘要"
]
for i, entry in enumerate(recent_history, 1):
if entry["type"] == "tool_result":
line = f" [{i}] {entry['summary']}"
if entry["micro_tool"]:
line += f"\n → 微工具: {entry['micro_tool']}"
prompt_parts.append(line)
return "\n".join(prompt_parts)
# ============================================================
# 模拟 Agent 工作流
# ============================================================
def simulate_grep_agent():
"""
模拟一个执行 grep 搜索的 Agent,演示 IRI 指针和微工具系统
"""
print("=" * 60)
print("Gliding Horse 上下文优化实战演示")
print("=" * 60)
# 初始化组件
graph = L0GraphStore()
router = ResultRouter(graph, threshold=2048)
context = ContextManager(router)
# 模拟用户查询
user_query = "在项目中搜索所有包含 'token' 关键字的代码行"
print(f"\n[用户查询] {user_query}\n")
# 模拟 grep 工具返回的大结果(15KB+)
grep_results = ""
for i in range(1, 48): # 模拟 47 处匹配
grep_results += f"src/auth.rs:{i}: let token = extract_jwt_token(request);\n"
grep_results += f"src/handler.rs:{i}: let decoded = decode_token(token);\n"
grep_results += f"src/middleware.rs:{i}: if validate_token(token).is_ok() {{\n"
print(f"[grep 工具] 原始结果大小: {len(grep_results.encode('utf-8'))} 字节")
print(f"[grep 工具] 原始结果行数: {len(grep_results.split(chr(10)))} 行\n")
# 通过 ResultRouter 处理(自动 IRI 化)
result = context.add_tool_call("grep_search", grep_results)
print(f"[IRI 化处理]")
print(f" - IRI: {result.iri}")
print(f" - 摘要: {result.summary}")
print(f" - 微工具: {result.micro_tool_name}")
print(f" - 上下文占用: {len(result.summary.encode('utf-8'))} 字节")
print(f" - 缩减比例: {(1 - len(result.summary.encode('utf-8')) / result.content_size) * 100:.1f}%\n")
# 构建最终 Prompt(不含原始大结果)
final_prompt = context.build_prompt(user_query)
print("[最终 Prompt(上下文窗口内)]")
print("-" * 40)
print(final_prompt)
print("-" * 40)
print(f"\nPrompt 总大小: {len(final_prompt.encode('utf-8'))} 字节")
# 模拟 Agent 需要查看完整结果时调用微工具
print(f"\n[Agent 决策] 需要查看完整 grep 结果,调用微工具: {result.micro_tool_name}")
full_content = graph.retrieve(result.iri)
print(f"[微工具返回] 完整结果大小: {len(full_content.encode('utf-8'))} 字节")
print(f"[微工具返回] 前 200 字符预览: {full_content[:200]}...\n")
print("=" * 60)
print("演示完成:大结果通过 IRI 指针引用,")
print("上下文窗口仅保留 200 字节摘要,")
print("关键信息通过微工具按需追溯,永不丢失。")
print("=" * 60)
if __name__ == "__main__":
simulate_grep_agent()
代码说明
| 组件 | 对应 Gliding Horse 概念 | 作用 |
|---|---|---|
L0GraphStore |
L0 持久化图存储 | 存储完整工具结果,按 IRI 检索 |
ResultRouter |
结果路由器 | 大结果自动 IRI 化,生成摘要和微工具 |
ContextManager |
上下文管理器 | 组装 Prompt,仅含摘要+IRI,控制 Token 预算 |
simulate_grep_agent() |
Agent 工作流 | 演示从查询到 IRI 化再到按需检索的完整流程 |
运行上述代码,你将看到:
- 一个 15KB+ 的
grep搜索结果被自动 IRI 化; - 上下文窗口中仅保留约 200 字节的摘要和 IRI 指针;
- Agent 需要完整数据时,通过微工具按 IRI 从图存储中精确读取;
- Token 消耗从 15KB 降至 200 字节,缩减 98.7%,与文章正文实测数据完全一致。
七、结语
Gliding Horse 的上下文管理系统本质上是把"记忆"做成了一等公民 。我们不把对话历史当作一次性消耗品,而是通过 JSON‑LD 的 IRI 机制,将其变成可寻址、可压缩、可淘汰的结构化资产。整个系统围绕"从保留到引用"这一理念,在工程上实现了一条完整的Token 经济管道,让 AI Agent 既能记住海量信息,又不必为 Token 账单发愁。
如果你也在打造长周期、多步骤的自主 Agent,强烈建议尝试类似的 IRI 摘要方案。它可能会像让我们一样,彻底改变你对 Agent 记忆管理的认知。
Gliding Horse 已在 GitHub 开源:https://github.com/doiito/gliding_horse