公司未注明

面经合集

完整信息

23 条问法 · 14 道题

本篇目录

内容来自个人+收集自互联网公开的佬们分享的个人面经整合~内容持续更新汇总(偏向于口述版)

上下文管理与记忆

1. 如何设计一个高效的Agent上下文维护方案?

参考口述答案:

核心思路是分层管理。我会把上下文分成三层:

  • 最上面是固定信息,比如系统角色、安全规则,一直放在 system prompt 里不变。
  • 中间是近期对话,保持完整原文,保证多轮连贯。
  • 更早的历史则定期让模型自己做摘要,用一两句话替换掉原始大段对话。

除此之外,真正重要的跨对话知识(比如用户偏好)会存到向量数据库,新会话开始时按需检索再注入上下文。这样既省 token,又不丢关键信息,很多框架比如 LangChain 的 ConversationSummaryBufferMemory 就是这个思路。


messages = [
    {"role": "system", "content": "你是专业助手,偏好表格回答。"},
    {"role": "user", "content": "[历史摘要] 前面聊了Python性能优化。"},
    {"role": "user", "content": "那具体怎么用cProfile?"},
    {"role": "assistant", "content": "你可以这样导入..."},
]

# Token 超限时,把旧消息压缩为摘要
if token_count(messages) > 6000:
    old = messages[1:6]  # 跳过system,取旧消息
    summary = llm.summarize(old)
    messages = [messages[0]] + [{"role": "user", "content": f"[历史摘要] {summary}"}] + messages[6:]

2. 主流模型上下文长度

参考口述答案:

目前 GPT-4o、GPT-4 Turbo 一般是 128k token,Claude 3 系列 200k,谷歌 Gemini 1.5 Pro 可以到 100 万甚至 200 万 token。国内 Kimi 主打 200 万字上下文,通义千问有 100 万 token 版本,DeepSeek-V2 是 128k。

虽然窗口越来越大,但有效注意力在中后段会衰减,而且长文本调用又贵又慢,所以上下文管理仍然是工程里的刚需。

3. 讲一下Agent中的“长短期记忆”

参考口述答案:

可以类比人:

  • 短期记忆就是当前对话窗口里的全部交互历史,存在内存或 Redis 里,会话结束就可丢弃。
  • 长期记忆是跨会话持久化的,通常存向量库或关系数据库。下次新对话时,根据当前问题去检索相关记忆,再拼进上下文。

所以短期记忆解决“这次聊得连贯”,长期记忆解决“下次见你还记得你”。


# 存储
memory_store.add(user_id="u1", content="用户喜欢表格回答",
                  embedding=embed("用户喜欢表格回答"))

# 检索
query_emb = embed("怎么展示数据")
results = memory_store.search(user_id="u1", embedding=query_emb, top_k=3)
system_prompt += "\n已知用户偏好:" + results[0].content

4. 什么样的信息应该放在长期记忆,什么样的信息放在短期记忆?

参考口述答案:

  • 短期记忆放当前任务强相关的即时信息:用户刚问的问题、工具返回结果、中间推理步骤、临时状态。
  • 长期记忆放跨对话还有价值的东西:用户画像(喜好、身份)、历史任务总结、经验教训、用户主动告知的事实(如公司名、deadline)。

判断标准很简单:如果下次新对话时你还得知道这些,就应该进长期记忆。

5. 长期记忆与短期记忆的压缩方案

参考口述答案:

短期记忆压缩,常用摘要+滑动窗口:每隔 N 轮让模型把前一段对话总结成简短摘要,替换掉原始长消息;或者只保留最近 K 轮完整消息,更早的用一句话概括。

长期记忆压缩,更多靠结构化和去重:存的时候只保留核心信息和摘要;后台定期聚类去重,合并相似记忆,淘汰低价值信息。

6. 长期记忆需要保存的核心内容

参考口述答案:

我会重点保存这几类:

  1. 用户画像:身份、偏好、习惯、技能栈。
  2. 任务成果:完成过的目标、产出的文件、重要结论。
  3. 反思与教训:从失败中总结的经验。
  4. 用户明确告知的事实:比如服务器地址、项目节点。

存的时候一定会带上时间戳、重要性评分和类型标签,方便后续检索和过期清理。


memory_entry = {
    "id": "mem_001",
    "user_id": "u1",
    "type": "preference",           # preference / fact / lesson
    "content": "用户要求代码示例用Python",
    "importance": 0.9,
    "created_at": "2026-07-17T10:00:00Z"
}
vector_db.upsert(memory_entry)

7. 如果要进行记忆压缩,通常有哪些方法?

参考口述答案:

常见方法有:

  • LLM 摘要法:让模型把长文总结成几句。
  • 关键信息提取法:抽取人物、事件、决策等结构化字段。
  • 滑动窗口法:只保留最近 N 条完整消息,其余用摘要。
  • 聚类去重法:把嵌入相近的记忆归为一类,只保留最有代表性的一条。
  • 遗忘曲线法:按重要性+最近访问时间打分,低分自动淘汰。 实际系统一般组合使用,比如“摘要 + 滑动窗口 + 重要性过滤”。

8. 长期记忆的压缩触发条件是什么?是基于Token阈值还是基于语义重要性?

参考口述答案:

我会采用混合策略:

  • Token 阈值是硬底线:当上下文使用率达到 70%-80% 时,强制压缩短期记忆防止溢出。
  • 语义重要性是质量过滤:存储时就打分,只有重要性超过阈值的才存;记忆库超量时优先淘汰低分记忆。 另外还会设时间触发,比如每天定时整理记忆库,合并重复、清理失效信息。阈值保底,重要性过滤,两者互补。

9. 当对话轮数很多,上下文窗口不足时,有哪些处理策略?

参考口述答案:

我会按优先级用这几招:

  1. 滑动窗口 + 摘要:保留最近几轮完整对话,更早的用摘要替代。
  2. 向量检索召回:把历史存进向量库,每轮只根据当前问题检索最相关的几句,不全量携带。
  3. 阶段性主动总结:任务阶段切换时,生成进度总结,然后重置上下文,只带总结继续。
  4. 分层处理:近期用原文,中期用摘要,远期靠检索。
  5. 小模型压缩:用便宜模型先做摘要,大模型读压缩版。

def compress_context(messages, keep_recent=6):
    if len(messages) <= keep_recent:
        return messages
    to_summarize = messages[:-keep_recent]
    summary = llm.invoke("总结以下对话要点:" + str(to_summarize))
    return [{"role": "system", "content": f"[历史摘要] {summary}"}] + messages[-keep_recent:]

10. 如果用户的 Prompt 特别长,导致上下文窗口溢出,除了截断,你有哪些简化上下文的策略?

参考口述答案:

直接截断太粗糙,我会用这几个方式:

  • 摘要预处理:先用小模型把长 Prompt 压缩成结构化摘要,Agent 基于摘要工作。
  • 分块处理:把长文本切成几块分别提取关键信息,汇总后再放上下文。
  • 外部文件模式:长文本先存成文件,只把摘要和文件 ID 放上下文,需要细节时调“读文件”工具。
  • RAG 式检索:提前给长文本建好向量索引,只把最相关的片段放进上下文。

核心思路就是把长文本变成可检索的外部知识,而不是全塞窗口。

11. 多Agent/多异步任务下,如何防止上下文污染?

参考口述答案:

防止污染关键是隔离。

  • 会话级隔离:每个 Agent 或任务有独立的 messages 列表,绝不共享。
  • 消息总线通信:Agent 之间通过结构化消息传递结果,不直接拼接聊天记录。
  • 记忆库分区:长期记忆按用户 ID 或 Agent ID 做命名空间隔离。
  • 来源标注:引用其他 Agent 信息时,明确标记“据Agent-A反馈…”,避免模型误以为是自己经历。

这样能从根本上避免信息串扰和幻觉扩散。

12. Agent是怎么实现上下文记忆的?

参考口述答案:

大模型本身是无状态的,记忆全靠工程层维护。

简单说就是维护一个 messages 列表,每次请求把整个列表带上,模型就能“记得”之前说过什么。

长期记忆则是另一套:在对话开始时或需要时,从外部数据库检索与该用户相关的历史信息,注入到系统提示或消息列表开头。

本质就是:短期记忆靠“消息历史拼接”,长期记忆靠“外部检索+注入”。

13. 上下文管理是怎么做的,如何进行记忆?

参考口述答案:

我会做一个上下文管理器模块,负责:

  1. 维护当前会话消息列表。
  2. 监听长度,超阈值时生成摘要替换旧消息。
  3. 识别并提取重要信息,异步写入长期记忆库。
  4. 新会话初始化时,根据用户 ID 从长期记忆库检索相关记忆,拼入系统提示。

这样就形成了一个“感知 → 存储 → 检索 → 注入”的完整闭环。

14. 如何构建工具实现memory记忆,让大模型在长期对话中学习用户习惯?

参考口述答案:

我会给 Agent 配置一套记忆管理工具,比如 remember_info、recall_info、forget_info。

在系统提示里明确告诉模型:“当你发现用户说了以后可能需要的信息,请调 remember 存下来;回答前可以先调 recall 查看相关画像。”

这样模型就能在对话中自发学会并记住用户习惯,下次自动应用。


tools = [
    {
        "name": "remember_info",
        "description": "存储一条需要长期记忆的信息",
        "parameters": {
            "content": "string",  # 要记住的内容
            "category": "preference / fact / lesson"
        }
    },
    {
        "name": "recall_info",
        "description": "根据关键词检索相关记忆",
        "parameters": {"query": "string"}
    }
]

15. 对Cursor记忆管理机制的了解

参考口述答案:

Cursor 的记忆管理和聊天 Agent 不太一样,它更偏向项目级静态上下文。

主要通过 .cursorrules 文件存储编码规范、项目约定、常用指令,每次 AI 请求都会带上。同时它会自动索引项目代码,生成向量嵌入,当你提问时检索相关代码片段。

最近版本也加了全局 Memory 设置,能记住一些全局偏好,比如默认语言、代码风格。

核心是“规则 + 代码索引”,而不是动态的长短期对话记忆。

16. Memory上下文记忆功能的处理逻辑

参考口述答案:

整体处理逻辑是一个循环:

  1. 存储:对话中识别到重要信息,生成记忆条目,计算嵌入,存入向量库。
  2. 检索:新会话开始或需要时,用当前意图做查询,搜索相关记忆。
  3. 注入:将检索到的记忆拼接进上下文。
  4. 维护:后台定期清理过时、低价值或矛盾记忆。

这个闭环跑通后,Agent 就能表现出不错的“记性”。

17. 如何进行记忆管理,怎么处理长上下文,怎么进行持久化,后续怎么读取和关联?

参考口述答案:

我会这样设计:

  • 短期上下文用 Redis 存消息列表,带会话 ID 和过期时间,读写极快。
  • 长上下文处理:超长时做摘要,保留近期完整消息,远期用摘要替代,仍放短期存储。
  • 长期记忆持久化:向量库存嵌入,关系库存元数据(用户ID、时间、类型)。
  • 读取和关联:短期直接用会话 ID 取;长期用用户 ID + 问题嵌入做向量检索,按相似度和时间排序取 Top N 注入。

# 持久化长期记忆
def save_long_term(user_id, content, embedding):
    db.insert("memories", {"user_id": user_id, "content": content, "embedding": embedding})

# 读取
def load_relevant_memories(user_id, query_emb, top_k=5):
    all_mems = db.query("SELECT * FROM memories WHERE user_id=?", user_id)
    scored = sorted(all_mems, key=lambda m: cosine_sim(query_emb, m.embedding), reverse=True)
    return scored[:top_k]

18. 你的向量记忆库是如何更新用户画像的?如何区分短期记忆和长期记忆?

参考口述答案:

画像更新我分两条线:

  • 实时小更新:当识别到画像类信息,直接增/改对应的画像记忆条目。
  • 定时大聚合:后台任务定期对同一用户的所有记忆做聚类和总结,提炼成一份精炼的“用户画像文档”。

区分短期和长期记忆很简单:短期记忆就是消息列表里的内容,存在 Redis,不向量化;长期记忆一定进向量库并标记 type: long_term,生命周期完全不同。

19. 记忆更新时能否精准替换指定片段,还是需要全量清空重建?

参考口述答案:

完全可以精准替换,不需要全量重建。

给每条记忆分配唯一 ID,更新时带上 ID 和新内容,后端找到对应记录,修改内容和嵌入向量,向量数据库大多支持 upsert 操作。

全量重建只在极少数情况使用,比如索引结构改变或出现严重逻辑冲突需要重新梳理时。

20. 存储时如果出现前后不一致的情况如何解决?

参考口述答案:

矛盾有两种,处理方式不同:

  • 随时间更新(如“用Python”→“用Go”):以时间戳为准,新覆盖旧,因为用户偏好可能改变。
  • 逻辑直接冲突(如同时存“喜欢详细”和“喜欢简洁”):检索时把矛盾两条都提示给模型,让模型反问用户确认。

每条记忆加版本号和时间,冲突时保留历史版本但标记失效,做到可追溯。

21. 多轮对话的实现方案

参考口述答案:

多轮对话本质就是把历史消息带回去。大模型无状态,所以我们维护一个 messages 数组,按 user/assistant 交替存储,每次请求全量发送。

持久化方面,把数组存到 Redis 或数据库,用户下次回来加载出来就能无缝续聊。

再配合上下文压缩和长期记忆机制,就能支撑超长多轮对话而不会爆窗口或丢失重要信息。


session = load_session(user_id)  # 从Redis/DB恢复
messages = session["messages"]

user_input = "帮我看看这个报错"
messages.append({"role": "user", "content": user_input})

response = llm.chat(messages)
messages.append({"role": "assistant", "content": response})

save_session(user_id, messages)

不定时更新~

本篇目录
  1. 01
  2. 02
  3. 03
  4. 04
  5. 05
  6. 06
  7. 07
  8. 08
  9. 09
  10. 10
    # 10. 如果用户的 Prompt 特别长,导致上下文窗口溢出,除了截断,你有哪些简化上下文的策略?
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
    # 17. 如何进行记忆管理,怎么处理长上下文,怎么进行持久化,后续怎么读取和关联?
  18. 18
  19. 19
    # 18. 你的向量记忆库是如何更新用户画像的?如何区分短期记忆和长期记忆?
  20. 20
  21. 21
    # 19. 记忆更新时能否精准替换指定片段,还是需要全量清空重建?
  22. 22
  23. 23

同作者面经

展开其余 4 篇收起其余 4 篇