新闻详情

新闻详情

首页 / 资讯中心 / 详情

拆解 Agent 核心原理|从零动手实现简易 AI 智能体(九)

发布时间:2026/11/13 9:39:43来源:尧图网络
拆解 Agent 核心原理|从零动手实现简易 AI 智能体(九)
本文摘要历史记录无限增长会超出模型上下文窗口闲置会话也持续占用内存。本篇通过引入tiktoken进行精确 token 计量并实现基于消息数量的历史截断与会话超时清理机制。一、环境与前提本篇建立在第八篇完成的会话隔离之上。项目目录为agent-demo/入口文件main.py请确保其中已包含通过session_id和asyncio.Lock实现的sessions会话字典及event_generator函数。前置依赖Python 3.11已安装openai,fastapi,uvicorn本篇新增依赖tiktoken安装命令如下pipinstalltiktoken预期输出执行pip list | grep tiktoken将显示已安装的tiktoken包。实际输出tiktoken 0.5.1以实际安装版本为准。二、关键步骤步骤 1添加 Token 用量统计到ChatResponse目的返回每次请求消耗的 token 数便于成本监控。操作修改ChatResponse模型添加usage字段。在event_generator中流式响应结束后尝试从最后一个 chunk 提取usage信息并发送。# main.py 的相关修改部分frompydanticimportBaseModelfromtypingimportList,Dict,AnyclassChatResponse(BaseModel):reply:strusage:Dict[str,int]|NoneNoneasyncdefevent_generator(session_id:str,user_message:str,):# ... 会话获取、消息追加等前置逻辑 ...response_chunks[]usage_dataNoneasyncforchunkinopenai_stream:# ... 处理流式块追加文本到 response_chunks ...pass# 注意OpenAI 流式接口的 usage 提取方式取决于具体库版本以下为简化示例。# 更可靠的方式是使用非流式调用或确认 openai 库版本支持从流中获取 usage。ifhasattr(chunk,usage)andchunk.usage:usage_datachunk.usage.model_dump()final_reply.join(response_chunks)yieldfdata:{ChatResponse(replyfinal_reply,usageusage_data).json()}\n\n预期输出成功请求后SSE 流末尾的 JSON 数据将包含usage字段。实际输出未实测。步骤 2实现历史长度管理基于消息数量截断目的防止history列表无限增长导致 API 上下文超限。操作在event_generator函数中获取会话历史后、调用模型前对history进行截断。# main.py 的相关修改部分在 event_generator 函数内asyncdefevent_generator(session_id:str,user_message:str):asyncwithsessions_lock:session_datasessions.get(session_id,{history:[],last_active:None})# 更新最后活跃时间session_data[last_active]time.time()# 使用标准库 time# 添加当前用户消息session_data[history].append({role:user,content:user_message})# 截断历史保留最近 20 条消息MAX_HISTORY_MESSAGES20iflen(session_data[history])MAX_HISTORY_MESSAGES:session_data[history]session_data[history][-MAX_HISTORY_MESSAGES:]current_historysession_data[history].copy()# 后续使用 current_history 调用 openai_stream预期输出会话历史长度始终不超过 20 条。实际输出未实测。步骤 3实现会话超时清理目的定期清理长时间不活跃的会话释放内存。操作定义超时时间如 30 分钟。编写异步清理函数。在 FastAPI 的lifespan事件中启动清理任务。# main.py 的相关修改部分importasynciofromcontextlibimportasynccontextmanagerimporttime# 定义会话存储和锁沿用前文sessions:Dict[str,Dict]{}sessions_lockasyncio.Lock()SESSION_TIMEOUT30*60# 30 分钟单位秒asyncdefcleanup_expired_sessions():定期清理过期会话whileTrue:awaitasyncio.sleep(5*60)# 每 5 分钟检查一次current_timetime.time()asyncwithsessions_lock:expired_sessions[sidforsid,datainsessions.items()ifcurrent_time-data.get(last_active,current_time)SESSION_TIMEOUT]forsidinexpired_sessions:delsessions[sid]print(f[Cleanup] Session{sid}expired and removed.)asynccontextmanagerasyncdeflifespan(app:FastAPI):cleanup_taskasyncio.create_task(cleanup_expired_sessions())yieldcleanup_task.cancel()try:awaitcleanup_taskexceptasyncio.CancelledError:passappFastAPI(lifespanlifespan)预期输出服务器运行期间超过 30 分钟无活动的会话将被自动删除控制台有清理日志。实际输出未实测。步骤 4整合并更新run_agent_stream调用可选增强目的通过max_tokens参数限制模型单次回复长度。操作在构建openai.chat.completions.create调用时添加max_tokens参数。# 在 event_generator 函数中openai_streamawaitopenai.chat.completions.create(modelgpt-3.5-turbo,messagescurrent_history,streamTrue,max_tokens1024# 限制单次回复最大 token 数)预期输出模型单次回复长度受max_tokens1024限制。实际输出未实测。三、失败处理常见失败使用tiktoken.encoding_for_model(gpt-3.5-turbo)时可能因模型映射缺失而报错。报错原文KeyError: Could not automatically map gpt-3.5-turbo to a tokeniser. Please use tiktoken.get_encoding to explicitly get the tokeniser you expect.原因tiktoken库版本可能未包含最新模型的分词器映射。修复方法直接指定编码名称。importtiktoken encodingtiktoken.get_encoding(cl100k_base)# 适用于 gpt-3.5-turbo 和 gpt-4token_countlen(encoding.encode(text))四、替代方案与取舍本文演示了基于消息数量的截断但还有其他方案。做法适用条件代价边界不适用场景基于消息数量的截断1. 原型开发快速验证。2. 对话轮数固定且较短。1. 实现简单。2. 无法精确控制总 token 消耗可能浪费额度或意外超限。适用于对话结构稳定、每轮交互 token 消耗差异不大的场景。当用户问题或模型回复长度波动极大时容易导致总 token 数超限。基于 token 总量的截断1. 生产环境需严格控制成本与 API 调用成功率。2. 使用多种模型需精确管理上下文窗口。1. 需引入tiktoken依赖。2. 每次截断前需计算 token 数增加延迟和 CPU 开销。适用于任何需要精确控制 token 的场景是更健壮的方案。对于极简单的演示项目可能略显过度设计。选择建议生产环境中尤其是处理长文档或长对话时建议结合tiktoken实现基于 token 总量的截断。参考资料Background Tasks - FastAPIasyncio.sleep — Python 官方文档OpenAI API 文档 - Chat Completionstiktoken GitHub 仓库下一篇将探讨如何将对话历史与 Agent 状态持久化到数据库实现跨服务器重启的会话恢复。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/13 0:43:49

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/12 23:59:09

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/13 10:09:00

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/13 13:31:48

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/13 16:11:45

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/13 0:02:27

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉