news 2026/5/27 21:24:59

Context Engineering与Prompt Engineering实战:构建高效AI应用的关键技术

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Context Engineering与Prompt Engineering实战:构建高效AI应用的关键技术


背景与痛点:为什么“说人话”这么难?

过去一年,我陆续给三款 SaaS 产品接入了大模型能力:客服机器人、数据洞察助手、内部知识问答。上线前都觉得自己 prompt 写得挺“性感”,结果一上真实流量就翻车:

  • 用户多问两句,模型就开始“装失忆”,答非所问;
  • 把整段对话历史都塞进去,一次请求就占掉 6k tokens,账单飙红;
  • 换成长上下文窗口模型,延迟又直接翻倍,用户侧疯狂转圈。

归根结底,问题集中在两条线:

  1. Context 管理:到底该给模型看多少历史?怎样在“记得住”和“传得快”之间做权衡?
  2. Prompt 设计:如何让模型在有限长度内稳定输出期望格式,又不被几句口语带偏?

下面把我趟出来的实战套路拆给大家。

技术对比:窗口、向量、摘要,谁才是最佳配角?

先放一张总览图,方便后面引用:

1. 滑动窗口(Windowing)

  • 原理:只保留最近 N 轮对话,超出的直接丢弃。
  • 优点:实现简单,token 可控。
  • 缺点:一旦关键信息在 N 轮之前,模型就永久失忆。

2. 向量召回 + 动态拼接(RAG 式)

  • 原理:把历史对话或文档切片向量化,按用户问题语义检索 Top-K 最相关片段,再拼进 prompt。
  • 优点:理论上“无限记忆”,且 token 随 K 值线性增长,可预测。
  • 缺点:依赖向量库质量,检索错误会直接带偏模型;每次召回都要一次向量搜索,增加 P99 延迟。

3. 摘要链(Summary Chain)

  • 原理:每当对话轮次达到阈值,先让模型自己总结前文,存成摘要,后续只传摘要+最近 N 轮。
  • 优点:兼顾长记忆与长度控制。
  • 缺点:多一次 LLM 调用,摘要可能丢失细节;摘要本身也要占 token。

4. 混合策略(Hybrid)

线上最常用:最近 3 轮完整对话 + 动态向量召回 2 条历史 + 上一步摘要。
经验值:在 4k 上下文模型里,可把平均输入压到 2k tokens 以内,召回率保持 90%+。

核心实现:给你一套能直接抄的 Python 骨架

下面代码演示“混合策略”在对话系统中的落地,依赖 openai>=1.0 与 chromadb(向量库)。
为了阅读方便,我拆成三步讲:

1. 对话状态机封装

# dialog_session.py import time from typing import List, Dict import openai from chromadb import Client as ChromaClient from chromadb.config import Settings class DialogSession: """ 负责三件事: 1. 维护原始对话历史 2. 生成/更新摘要 3. 向量库存储 & 召回 """ SUMMARY_TRIGGER = 6 # 轮数阈值 WINDOW_SIZE = 3 # 最近保留 RETRIEVAL_TOPK = 2 # 向量召回条数 def __init__(self, openai_key: str, collection_name: str = "chat_history"): openai.api_key = openai_key self.chroma = ChromaClient(Settings(anonymized_telemetry=False)) self.collection = self.chroma.get_or_create_collection(collection_name) self.raw_history: List[Dict[str, str]] = [] # 完整历史 self.summary: str = "" # 摘要 def add_turn(self, role: str, content: str): """记录一轮对话""" self.raw_history.append({"role": role, "content": content}) # 向量化入库,方便后续语义检索 self.collection.add( documents=[content], metadatas=[{"role": role, "ts": time.time()}], ids=[f"{time.time()}"] ) def _generate_summary(self) -> str: """调用 LLM 生成摘要""" prompt = ( "请将以下对话浓缩成 2 句话以内,保留关键事实与上下文:\n" + "\n".join(f"{m['role']}: {m['content']}" for m in self.raw_history) ) rsp = openai.chat.completions.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": prompt}], max_tokens=120 ) return rsp.choices[0].message.content.strip() def _retrieve_related(self, query: str) -> List[str]: """向量召回 Top-K 相关历史""" res = self.collection.query(query_texts=[query], n_results=self.RETRIEVAL_TOPK) return [d for d in res["documents"][0]] def build_prompt(self, user_input: str) -> List[Dict[str, str]]: """组装最终 prompt""" # 1. 触发摘要 if len(self.raw_history) > self.SUMMARY_TRIGGER and not self.summary: self.summary = self._generate_summary() # 2. 向量召回 related = self._retrieve_related(user_input) # 3. 截取最近窗口 recent = self.raw_history[-self.WINDOW_SIZE:] # 4. 拼装 system + context system = ["你是智能客服助手,请根据背景信息回答。"] if self.summary: system.append(f"历史摘要:{self.summary}") if related: system.append("相关背景:\n" + "\n".join(related)) messages = [{"role": "system", "content": "\n".join(system)}] messages.extend(recent) messages.append({"role": "user", "content": user_input}) return messages

2. Prompt Engineering 模板

再给一个“万能填空”版,适合输出结构化 JSON,也方便后续做字段校验。

# prompt_templates.py def json_bot_template(goal: str, required_keys: List[str], context: str = "") -> str: """ 返回一段 system prompt,要求模型必须输出合法 JSON, 并包含指定字段,否则就重试。 """ key_list = ", ".join(required_keys) return f""" {context} 你的目标是:{goal} 回答时请严格遵循以下格式,不要输出任何多余文字: {{ "{required_keys[0]}": <内容>, "{required_keys[1]}": <内容>, ... }} 确保 JSON 可被 Python json.loads 解析。 """

调用示例:

messages = [ {"role": "system", "content": json_bot_template( goal="判断用户意图并抽取参数", required_keys=["intent", "product", "date"], context="你是电商售后助手。")}, {"role": "user", "content": "我想换货,订单里那双鞋尺码小了"} ]

3. 端到端调用

# main.py from dialog_session import DialogSession import openai, os, json session = DialogSession(openai_key=os.getenv("OPENAI_KEY")) def chat(user_input: str) -> str: messages = session.build_prompt(user_input) rsp = openai.chat.completions.create( model="gpt-3.5-turbo", messages=mes, temperature=0.3, max_tokens=400 ) assistant_msg = rsp.choices[0].message.content session.add_turn("user", user_input) session.add_turn("assistant", assistant_msg) return assistant_msg if __name__ == "__main__": while True: user = input("User: ") print("Bot:", chat(user))

跑通后,你可以用tokencount工具观察:一轮真实对话平均 1.2k~1.5k tokens,比直接丢全史节省 60%+,且摘要 + 召回能覆盖 90% 的“跨轮引用”场景。

性能考量:省 token 也要省时间

  1. token 预算公式
    总输入 = system + summary + retrieved + window + user
    上线前用 1000 条真实日志跑一遍分位统计,确保 P95 不超过模型上限的 75%,给网络抖动留余量。

  2. 向量库延迟
    Chroma 本地 Docker 版在 5 万条 768 维向量下,Top-K 查询约 30~50ms;若对延迟敏感,可提前做“批量预召回”放进 Redis,用户请求时直接 O(1) 读取。

  3. 摘要频率
    摘要也是 LLM 调用,建议异步线程做,或在“用户正在输入”间隙触发,避免卡住首 token 时间。

  4. 并行生成
    对结构化输出,可让模型一次返回带字段的 JSON,减少多轮追问;若字段多,可拆成两次并行调用再合并,降低单请求 max_tokens。

避坑指南:生产环境 5 个深坑

  1. token 估算不准
    中文 & 英文混排时,官方tiktoken会多算 5~10%,预算要再留 10% 安全垫。

  2. 摘要雪崩
    摘要本身也会累加 token,记得给摘要长度设硬上限(如 120 tokens),超长就再摘要一次,防止无限套娃。

  3. 向量 ID 冲突
    时间戳当 ID 在并发高时会碰撞,改用uuid.uuid4()

  4. JSON 输出多余解释
    即使 system 里强调“不要废话”,小概率仍会夹带 “Here is the json:” 前缀,解析前务必 strip() 再做json.loads,失败就重试。

  5. 温度双标
    摘要和召回对事实准确性要求高,temperature 设 0.1~0.3;创意型回答可单独调高,但别全局复用同一参数。

开放式思考

  1. 当上下文突破 100 万字时,摘要+向量还能线性扩展吗?是否需要“分层记忆”或“图索引”新架构?
  2. 多模态(图文、音频)场景下,Context Engineering 的 token 概念被重新定义,你会如何量化成本?
  3. Prompt 自动优化(如 DSPy、APE)正在兴起,人工模板还有多大生存空间?还是说“人机共写”才是终局?

把上面的代码和模板搬到你的项目里,跑通日志看看 token 曲线,再回来聊聊你的答案。祝你少踩坑,多拿 A/B 正向指标!


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 20:17:10

Irony Mod Manager从入门到精通:排障指南

Irony Mod Manager从入门到精通&#xff1a;排障指南 【免费下载链接】IronyModManager Mod Manager for Paradox Games. Official Discord: https://discord.gg/t9JmY8KFrV 项目地址: https://gitcode.com/gh_mirrors/ir/IronyModManager 一、前置知识与环境准备 Iron…

作者头像 李华
网站建设 2026/5/25 20:03:04

ChatGPT并发请求优化实战:从队列策略到API限流设计

背景痛点&#xff1a;429 不是“服务器炸锅”&#xff0c;而是“官方限速” 第一次把 ChatGPT 塞进业务链路时&#xff0c;我 5 分钟就把配额打光——前端日志清一色 429 Too Many Requests。 OpenAI 的限流策略分两层&#xff1a; RPM&#xff08;Requests Per Minute&#…

作者头像 李华
网站建设 2026/5/1 5:50:36

零基础高效绘制专业网络拓扑图:easy-topo开源工具全指南

零基础高效绘制专业网络拓扑图&#xff1a;easy-topo开源工具全指南 【免费下载链接】easy-topo vuesvgelement-ui 快捷画出网络拓扑图 项目地址: https://gitcode.com/gh_mirrors/ea/easy-topo 网络拓扑图工具是IT工程师、网络管理员和系统架构师必备的可视化工具&…

作者头像 李华
网站建设 2026/5/16 4:48:31

医疗术语识别失准、上下文断裂、合规性告警频发,Dify问答调试避坑清单全解析

第一章&#xff1a;医疗问答调试的核心挑战与典型故障图谱医疗问答系统在临床辅助决策、患者教育和智能导诊等场景中承担关键角色&#xff0c;其调试过程远超通用问答系统的复杂度。语义歧义、医学术语层级嵌套、上下文强依赖性以及合规性约束共同构成了调试的深层阻力。例如&a…

作者头像 李华
网站建设 2026/5/15 8:52:05

Dify多租户部署全链路解析(从YAML配置到K8s Namespace级隔离)

第一章&#xff1a;Dify多租户部署的核心概念与架构演进Dify 是一个开源的 LLM 应用开发平台&#xff0c;其多租户能力并非简单地复用单实例资源&#xff0c;而是通过逻辑隔离、数据分片与策略驱动的权限控制体系实现租户间的安全边界。在架构演进路径上&#xff0c;Dify 从早期…

作者头像 李华