15天学会AI应用开发四根据Token长度截断历史对话在构建AI对话应用时管理历史对话长度是一项关键挑战。无论是使用OpenAI的GPT模型、Claude还是其他大语言模型每个模型都有固定的上下文窗口限制如4096 token、8192 token等。如果不加控制地累积历史对话当总token数超过模型限制时请求会被拒绝或截断导致对话质量下降。本文将深入剖析Token截断的原理并提供实用的代码实现方案。## Token与上下文窗口的基本原理### 什么是TokenToken是语言模型处理文本的基本单位。一个token可以是一个单词、子词或字符。例如英文中hello通常是一个token而中文中你好可能是1-2个token。不同模型的tokenizer分词器不同但核心原则一致模型通过token序列理解语义。### 上下文窗口的硬性限制每个模型都有最大上下文窗口比如GPT-3.5-turbo支持4096 tokensGPT-4支持8192 tokens。当输入的总token数包括用户消息、系统提示、历史对话、当前问题超过这个限制时模型会拒绝处理或抛出错误。因此我们需要一种策略来截断历史对话确保总token数在安全范围内。### 截断策略的设计原则1.保留最新消息通常最近的消息包含更相关的上下文。2.丢弃最旧消息早期对话对当前回复贡献较小。3.考虑系统提示系统提示如角色设定通常需要保留。4.动态调整根据当前输入长度动态计算可保留的历史。## 基于Token长度的截断实现### 计算Token长度首先我们需要一个函数来计算文本的token数。使用OpenAI的tiktoken库是最精准的方式因为它与GPT模型的分词器一致。对于其他模型可以使用transformers库或估算方法。pythonimport tiktokendef count_tokens(text: str, model: str gpt-3.5-turbo) - int: 计算给定文本的token数 :param text: 输入文本 :param model: 模型名称默认gpt-3.5-turbo :return: token数量 try: encoding tiktoken.encoding_for_model(model) return len(encoding.encode(text)) except KeyError: # 如果模型不在tiktoken列表中使用cl100k_base编码 encoding tiktoken.get_encoding(cl100k_base) return len(encoding.encode(text))# 示例计算字符串的token数example_text 你好今天天气怎么样token_count count_tokens(example_text)print(f文本: {example_text} 的token数: {token_count})### 核心截断函数接下来我们实现一个智能截断函数它接收历史对话列表、最大token限制和系统提示返回截断后的对话。pythonfrom typing import List, Dict, Tupledef truncate_conversation( messages: List[Dict[str, str]], max_tokens: int 4096, system_prompt: str , model: str gpt-3.5-turbo) - Tuple[List[Dict[str, str]], int]: 根据token限制截断历史对话保留最新消息 :param messages: 对话消息列表格式为[{role: user, content: ...}, ...] :param max_tokens: 最大token限制 :param system_prompt: 系统提示文本可选 :param model: 模型名称 :return: 截断后的消息列表和总token数 # 计算系统提示的token数 system_tokens count_tokens(system_prompt, model) if system_prompt else 0 # 预留空间给当前输入假设当前输入最大为max_tokens的20% input_buffer int(max_tokens * 0.2) available_tokens max_tokens - system_tokens - input_buffer # 从最新消息开始累积直到达到限制 truncated_messages [] total_tokens system_tokens # 反转列表以便从最新消息开始处理 reversed_messages list(reversed(messages)) for msg in reversed_messages: # 计算当前消息的token数 msg_tokens count_tokens(msg[content], model) # 加上角色标识的固定开销如user或assistant role_overhead count_tokens(msg[role], model) msg_total msg_tokens role_overhead if total_tokens msg_total available_tokens: # 可以添加此消息 truncated_messages.append(msg) total_tokens msg_total else: # 超出限制停止添加 break # 恢复原始顺序从旧到新 truncated_messages.reverse() # 如果系统提示存在添加到开头 if system_prompt: truncated_messages.insert(0, {role: system, content: system_prompt}) total_tokens system_tokens return truncated_messages, total_tokens# 示例模拟历史对话history_messages [ {role: user, content: 什么是机器学习}, {role: assistant, content: 机器学习是人工智能的一个分支它使计算机能够从数据中学习...}, {role: user, content: 能举个例子吗}, {role: assistant, content: 当然比如垃圾邮件分类器就是一个例子...}, {role: user, content: 深度学习与机器学习有什么关系}, {role: assistant, content: 深度学习是机器学习的一个子集使用神经网络...},]# 假设模型最大4096 tokens系统提示占用100 tokenssystem_prompt 你是一个友好的AI助手回答用户问题。truncated, total truncate_conversation( messageshistory_messages, max_tokens4096, system_promptsystem_prompt)print(f原始消息数: {len(history_messages)})print(f截断后消息数: {len(truncated)})print(f总token数: {total})for msg in truncated: print(f[{msg[role]}]: {msg[content][:50]}...)## 高级优化策略### 动态保留策略在实际应用中我们可能需要更精细的控制。例如保留系统提示和最后N条消息同时丢弃中间部分。以下是一个增强版本pythondef smart_truncate_conversation( messages: List[Dict[str, str]], max_tokens: int 4096, system_prompt: str , min_recent_messages: int 2, model: str gpt-3.5-turbo) - Tuple[List[Dict[str, str]], int]: 智能截断至少保留最近min_recent_messages条消息 # 计算系统提示和最少消息的token数 system_tokens count_tokens(system_prompt, model) if system_prompt else 0 # 确保至少保留最近的几条消息 recent_messages messages[-min_recent_messages:] if len(messages) min_recent_messages else messages recent_tokens sum(count_tokens(msg[content], model) count_tokens(msg[role], model) for msg in recent_messages) available_tokens max_tokens - system_tokens - int(max_tokens * 0.2) # 保留20%给当前输入 # 如果最近消息已经超出限制只保留最近消息可能部分丢失 if recent_tokens available_tokens: # 从最近消息中截断 reversed_recent list(reversed(recent_messages)) truncated_recent [] token_sum 0 for msg in reversed_recent: msg_tokens count_tokens(msg[content], model) count_tokens(msg[role], model) if token_sum msg_tokens available_tokens: truncated_recent.append(msg) token_sum msg_tokens else: break truncated_recent.reverse() truncated_messages truncated_recent total_tokens token_sum else: # 从历史消息中逐步添加从最新到最旧 truncated_messages recent_messages.copy() total_tokens recent_tokens for msg in reversed(messages[:-min_recent_messages]): msg_tokens count_tokens(msg[content], model) count_tokens(msg[role], model) if total_tokens msg_tokens available_tokens: truncated_messages.insert(0, msg) total_tokens msg_tokens else: break # 添加系统提示 if system_prompt: truncated_messages.insert(0, {role: system, content: system_prompt}) total_tokens system_tokens return truncated_messages, total_tokens# 测试智能截断truncated_smart, total_smart smart_truncate_conversation( messageshistory_messages, max_tokens4096, system_promptsystem_prompt, min_recent_messages3)print(f智能截断 - 保留消息数: {len(truncated_smart)}, 总token数: {total_smart})### 与API调用集成最后将截断函数与OpenAI API调用结合pythonimport openaidef chat_with_truncation( user_input: str, history: List[Dict[str, str]], system_prompt: str 你是一个AI助手, max_tokens: int 4096, model: str gpt-3.5-turbo) - str: 带截断功能的对话API调用 # 将用户输入添加到历史 history.append({role: user, content: user_input}) # 截断历史 truncated_history, total_tokens smart_truncate_conversation( messageshistory, max_tokensmax_tokens, system_promptsystem_prompt, modelmodel ) # 调用API response openai.ChatCompletion.create( modelmodel, messagestruncated_history, max_tokens500 # 生成回复的token限制 ) assistant_response response.choices[0].message.content # 将回复添加到历史全局变量或持久化存储 history.append({role: assistant, content: assistant_response}) return assistant_response## 总结本文深入探讨了AI对话应用中Token截断的核心原理与实现。我们了解到1. Token是模型处理文本的基本单位每个模型有固定的上下文窗口限制。2. 截断策略应优先保留最新消息和系统提示动态计算可用token空间。3. 使用tiktoken库可以精确计算token数避免估算误差。4. 高级策略如智能保留最近消息能提升对话连续性。通过实现truncate_conversation和smart_truncate_conversation函数我们可以有效管理对话历史避免超出模型限制。在实际开发中还需要考虑并发请求、持久化存储和错误处理等细节。掌握Token截断技术是构建稳定、高效的AI应用的基础。
企业数字化 ERP 产品动态
相关推荐
2026国内企业级AI Agent平台TOP10盘点:谁是最佳选择? 如今,企业级AI Agent已从概念验证全面迈入规模化落地阶段。IDC 数据显示,2026 年中国企业级 AI 智能体市场规模预计增至 449 亿元,同比增长超 110% 。企业对 AI 的需求已从对话辅助转向业务落地,AI Agent 平台成为数字化转型的核心… · 2026/9/24 18:42:56
Agent架构如何提升大模型开发效率与业务指标 1. 为什么Agent正在重塑大模型开发范式 去年ChatGPT引爆的Prompt工程热潮,让不少开发者陷入了"调参炼金术"的怪圈。但真正在一线落地过企业级AI应用的工程师都知道,仅靠精心设计的Prompt就像用吸管喝汤——效率低下且难以规模化。最近三个月&a… · 2026/8/9 13:57:00
从2比10到25比23:中国女排用23天完成一场漂亮的翻身仗 2比10落后,还能赢吗?
9月22日晚,2026年爱知名古屋亚运会女排决赛,中国女排在第三局开局落后8分的情况下,将比分追至19平,最终以25比23完成逆转。随着日本队最后一次接发球出界,中国女排以3比0击… · 2026/9/24 18:43:57
TransUnet眼底血管分割实战:拆解Transformer与U-Net缝合细节 简介:本资源是一套基于TransUnet架构实现眼底血管DRIVE数据集分割的完整实战方案,面向医学图像分割初学者与深度学习实践者,解决视网膜血管结构精准分割这一典型生物医学图像分析任务。压缩包共76个文件,含40张标注图像࿰… · 2026/9/24 18:43:57
Java Spring Boot搭建智慧养老平台:从设备接入到告警落地 简介:一套基于SpringBoot的智慧养老平台Java源码,面向计算机、电子信息工程等专业的学习者,可作为毕业设计、课程设计或期末大作业使用。项目采用B/S架构与MVC分层设计,后端整合SpringBoot、Mybatis与MySQL,前端结合Vu… · 2026/9/24 18:43:57
Flutter For OpenHarmony开发:用Liquid模板引擎优雅处理动态文本 做 Flutter For OpenHarmony 开发,我把文本拼接这块硬骨头啃下来了做 Flutter For OpenHarmony 开发有一阵子了,要我说,最容易被低估的坑不在 UI,不在状态管理,反而在"文本处理"这种不起眼的地方。尤其那种&… · 2026/9/24 18:43:57
Flutter for OpenHarmony实战:扫雷游戏数字显示与适配解析 最近在折腾Flutter for OpenHarmony的游戏合集类App,踩了不少坑,也积累了一些可复现的经验。这个项目本身不复杂,就是做一个包含多个小游戏的App,先落地的是扫雷模块,重点难点在棋盘数字的生成与显示。但越是不复杂的项… · 2026/9/24 18:43:57
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44