ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于API代理的LLM Token优化:用AST裁剪冗余代码

基于API代理的LLM Token优化:用AST裁剪冗余代码 在 LLM 应用的成本账里token 几乎是一切开销的最小单位。API proxy 之所以值得做是因为它可以替调用方统一处理请求内容在进入上游之前完成一次可控的裁剪。一次代码评审请求可能把几十个文件粘进上下文一次 RAG 问答可能把整段文档重复带入历史而提示词里的注释、空行、未使用的 import 和从未被调用的函数都在按 token 计费。更麻烦的是冗余内容会稀释注意力、拉低响应一致性即便模型本身没有报错。针对这类问题一种比较自然的工程方案是在请求链路上加一层 API 代理代理拦截发往 LLM 上游的请求识别其中的代码内容用 AST 完成抽象语法树级别的 pruning再把清理后的请求转发给模型。下面实现的其实是一个最小可复用的原型它基于 FastAPI 搭建兼容主流 chat/completions 接口核心剪枝逻辑可以独立复用。读者可以把它改造成内部网关、CI 代码审查服务或私有 LLM 平台上的一层中间件。1. 理解清楚 token 冗余是如何进入 LLM 上下文的1.1 一次 chat 请求里的 token 开销由哪几部分构成OpenAI 兼容接口的请求体是messages数组每个消息包含role和content。模型真正处理时会把 system prompt、历史对话、工具定义、用户输入拼接到同一个上下文窗口再按模型分词器切分成 token。因此一次请求里的 token 开销不只是“用户最后输入的那句话”而是整段上下文。常见冗余来源如下表所示。冗余类型典型例子简单处理方式是否属于 AST pruning 范畴系统提示重复每轮都发送同一大段 system 指令在代理层做对话级缓存不算属于会话管理多轮历史重复把整段文档或工具返回反复带入做历史摘要或 sliding window不算属于上下文管理代码注释和空行文件顶部大量注释、空行删除注释和空行算是未使用导入import os但全程没用到AST 分析删除算是未使用的函数和类粘贴整个文件但只用其中一小块按引用分析裁剪算是但安全风险较高JSON/YAML 冗余字段配置文件里大量默认值和空值结构化字段裁剪可以借鉴 AST 思路这些冗余会带来两个直接后果一是计费增加输入 token 越多单次调用成本越高二是模型注意力被无关内容分散代码审查、错误修复、接口解释等任务更容易答偏。代理层的价值就是把“该不该删”的判断从用户手里收上来统一执行。1.2 代码类内容为什么是冗余重灾区代码类内容在 prompt 里非常常见但也很容易被忽视。很多用户做代码解释、代码评审、单元测试生成时会直接粘贴完整文件甚至粘贴整个项目目录下的关键文件。下面这段代码比较典型。import os import json # TODO: remove this debug function later def _internal_debug(data): print(data) def main(): cfg json.load(open(config.json)) print(cfg) if __name__ __main__: main()对模型理解main流程来说import os、注释行、_internal_debug都不是必要内容。但它们都会进入分词器变成输入 token。更隐蔽的是很多用户会粘贴带有大量logging日志、调试分支、被注释掉的历史代码的文件这些内容对模型理解真正业务逻辑的贡献非常小却会占用上下文窗口。所以代码类的 token 冗余不是偶发现象而是普遍现象。只要用户通过代码块把文件粘进 prompt就值得在代理层做一次结构化清理。1.3 AST 裁剪不是简单的删注释最容易想到的做法是写正则删注释。比如用#.*$删除注释用\n\s*\n压缩空行。但这种做法的致命问题是正则不理解语法。看下面的 Python 代码。text # 这不是注释这是一个字符串内容 # 它只是恰好以井号开头 url http://example.com/api#fragment如果直接用正则删除“以#开头的内容
返回列表