技术碎碎念01
2026/9/24 17:54:45 网站建设 项目流程

一、多智能体系统

1.1 受控多智能体 vs 开放式多智能体

  • 开放式的多智能体稳定性太难控制,操作不可预期。

  • 受控多智能体是一种很好的解决方案,虽然会丢失一些灵活性,但从企业场景的稳定性来看,很值得考虑。

  • 先固定再谈论自由,自由可以慢慢赋予、一点点摸索;一上来全让智能体干就无法控制变量来进行后续的优化。

1.2 多智能体通信

  • 多智能体的通信可以使用消息队列,通过事件发布、接收事件来进行各个智能体的隔离。

  • 这样后续添加智能体的时候,比较好扩展。

1.3 子智能体结果控制

  • 受控多智能体的子智能体要进行数据结果的控制。

  • 子智能体 A、子智能体 B 的结果都要产出三类结果:1. 开始、2. 过程、3. 结束

  • 这样主智能体可以进行横向对比,适合需要多维度对比的场景。

1.4 多智能体框架

  • CrewAIDeepAgent都是自主式的多智能体,开放性高。


二、LangGraph

2.1 检查点(Checkpoint)与 StateSnapshot

  • 检查点在用户层面是以StateSnapshot对象存在的,底层是 checkpoint。

  • StateSnapshot 有parent_config字段,字段内部有:

    • thread_id:不是线程 id,强调的是一种会话的隔离,记录不同会话的检查点。跨不跨会话是区分 checkpoint 和 store 很重要的一点。

    • checkpoint_id:checkpoint 的唯一性标识。

    • checkpoint_ns:检查点的命名空间,可以区分子图或者图。

  • StateSnapshot 中有values字段,用来存储当前状态字典的属性及其属性值。

2.2 Store

  • Store 中也有 namespace,Store 的 namespace 是由字符串构成的元组,都是用来进行区分的。

  • Store 可以跨会话,checkpoint 是针对单个会话而言。

  • 两者都可以进行持久化。

2.3 节点定义

  • 定义节点可以用函数,也可以使用对象。

  • 使用对象可以在初始化的时候扩展属性。

  • 使用对象来定义节点需要重写对象的__call__魔术方法,使用对象()来调用。

2.4 条件边

LangGraph 的条件边组成:

  1. 节点

  2. 路由函数

  3. 映射字典(可选)

  • 路由函数返回的值可以是节点的名称(没有映射字典的情况下)。

  • 有映射字典的情况下,返回的值会在映射字典中进行映射,转换成图中的节点名称。

2.5 中断机制

  • 中断机制需要提前把数据存放到 checkpoint 中,并且要保存thread_id

  • 保存thread_id是为了找到哪个会话进行保存,需要先通过thread_id来找到对应的 checkpoint,这样才能恢复。

  • 恢复的时候使用Command(resume=...),传入的值是调用interrupt函数时的返回值。

  • 恢复的时候,需要重新执行那个节点,但是会识别出传入了恢复信息,所以不会再次执行interrupt()函数。

  • 但是interrupt()的前面部分的代码还是会再次执行,尽量保持幂等性,这个地方会造成重复操作需要注意。


三、记忆管理

  • 可以使用 LangGraph 中的Storecheckpoint进行记忆管理。

    • Store 可以跨会话。

    • checkpoint 是针对单个会话而言。

  • 较快的获取任务状态可以使用Redis

  • 保留任务执行的状态,要让模型在完成任务的过程中,知道自己完成了什么,还有什么没有完成。


四、Agent 工作模式

4.1 ReAct 模式

  • ReAct 是思考 → 行动 → 观察的一个循环。

  • 问题:随着上下文增长,会出现上下文漂移的情况。

    • 目标、决策会被淹没在很长的文本中,注意力会被稀释。

    • 会因为当前任务获取的新文本而夺走注意力,很容易发生漂移。

4.2 Plan and Executor 模式

  • 问题:怎么保证规划就是对的?一开始就错了,后面很大概率会导致错误。

  • 可以边执行,边去查看自己的进度和要完成的目标,进行方向的纠正。

  • 但纠正的一定是正确的吗?还是不确定。


五、JSON 约束

5.1 JSON Schema

  • 使用 JSON Schema 来约束生成 JSON,有部分厂商支持。

  • 这种 Schema 对于类型、枚举等等进行约束,控制模型的幻觉。

  • 是目前约束性很好的一种方法。

5.2 JSON Mode

  • 虽然支持很广,但只能保证是个 JSON 格式。

  • 对于生成的字段是否正确、是否契合业务等等效果并不好。

5.3 提示词约束

  • 可以在提示词中举几个 JSON 的 case,来强化约束。


六、RAG(检索增强生成)

6.1 表格与图片处理

  • 对表格和图片进行语义的提取,在进行检索的时候进行匹配。

  • 表格和图片可以作为一种元数据进行绑定。

过程:

  1. 对表格和图片提取语义。

  2. 语义进行向量化存储到 chunk。

  3. 表格和图片作为一种元数据,在匹配 chunk 的时候,查看是否有对应的元数据,有的话可以进行展示。

  4. 图片可以使用MinIO存放,然后展示 URL 在前端。

  5. 表格可以在存放的时候用JSON 格式存放,然后放到数据库,前后端协商好定义和展示的形式。

6.2 知识图谱

  • 知识图谱是通过保存实体-关系来打通一些深层关系,可以跨越分片。

  • 比如一个问题和 A、C 都有关系,但语义检索得到 A,A 和 C 是一种深层次的关系,不好获取,使用知识图谱来进行跨分片的查询。

  • 知识图谱的维护、成本也是要考量的关键因素。

流程:

  1. 获取用户问题,提取关键实体。

  2. 和向量数据库里面的实体数据库进行相似度匹配。

  3. 获取到相关的实体。

  4. 根据实体去检索图数据库,获取到相关的实体-关系。

6.3 文本处理

  • 使用正则表达式或者大模型识别电话、姓名、关键信息。

  • 对敏感信息进行脱敏。

6.4 RAG 评测

RAG 评测看四个维度:query、检索到的证据、生成的答案、目标答案

指标说明
Answer Relevancy答案的相关性,看 query 和生成的答案的匹配度,生成的答案是否很好地回答了 query
Faithness忠实性,看生成的答案是否基于检索到的证据,防止大模型幻觉
Recall@K召回率,top-k 返回的相关性文档块的个数 / 总的相关的文档块个数
Precision@K前 K 个位置中相关文档块的个数 / K(当前位置)
Context Precision@K先计算相关性(相关是 1,不相关是 0),然后和自己的 Precision@K 相乘,最后除以 top-k 中相关的文档总个数
Answer Similarity答案的相似度,看生成的答案和目标答案的语义相似程度

七、Agent 测试

  • 对于要上线的 Agent 要进行TTFT(首字延迟)测试,测试性能。

  • 测试一组模拟的数据,可以让业务人员进行编写,输入和目标答案来批量测试效果。


八、Skill 体系

  • 以前的 skill 是一种经验的提取总结。

  • 现在的 skill 有脚本、指导、附件等等,慢慢演变成了一种综合的解决方案。

  • 可以使用关键词唤醒skill,或者对 skill 进行语义提取,然后进行语义匹配。


九、Python 相关

9.1 协程(Coroutine)

  • 协程是一种轻量化的线程,但是是被用户所控制的。

  • 在 Python 中,如果像运行正常函数那样A()运行协程的话,是运行不了的,因为这只是返回一些协程对象,需要创建事件循环放进去。

  • 首先要创建事件循环,asyncio.run()其实默认是创建的,然后create_task()就可以了。

  • 但是单纯create_task()是不行的,因为没有创建事件循环。

  • 出现await就需要把控制权交给事件循环了,等到操作系统通知事件循环它的 IO 完成了,事件循环会把那个协程设置为就绪,等待时机再运行。

9.2 asyncio.to_thread

  • asyncio.to_thread是把操作放到一个独立的线程,返回一个等待的事件,不会阻塞当前事件循环。

  • 因为协程很害怕同步阻塞,一旦出现同步阻塞,整个协程都会停滞,因为这个阻塞不会把控制权交给事件循环,只能硬等。

9.3 闭包

  • 闭包是内部函数访问外部函数的变量,然后外部函数返回内部函数。

  • 这个变量不是全局变量。

  • 内部函数的调用会捆绑外部函数的变量,使得它不会因为外部函数的结束而销毁,可以保持和内部函数一样的生命周期。

9.4 字典的 setdefault

  • setdefault返回 key 所对应的值。

  • 如果没有 key,设置 key 为默认值,返回默认值。

9.5 @lru_cache

  • @lru_cache会丢弃掉最近最少被使用的对象。

  • 可以使用max_size来控制缓存的最大个数。

  • 保存的是参数 → 返回值的映射。

9.6 ContextVar

  • 不同线程之间可以使用 thread 来进行区分。

  • 同一线程的协程可以使用ContextVar来区分。

  • 不同的协程之间 ContextVar 是相互隔离的,可以用来保存请求 id。


十、FastAPI

10.1 Lifespan

  • lifespan中使用@contextmanager

    • yield之前是应用启动之前做的。

    • yield之后是结束之后做的。

    • finally一般来进行最后资源的释放。

    • yield是进入应用中执行。

@contextmanager def A(): ... yield 1 ... ​ with A() as num: ...
  • @contextmanager配合with使用,with中的asyield的返回值。

  • 执行顺序:先执行 A() 内部代码到 yield → 进入 with 代码内部 → 执行完 with 内部代码 → 再执行 A() 中 yield 后面的部分。

10.2 中间件(Middleware)

middleware: 代码执行前的执行动作 call_next() 代码执行后的执行动作
  • 中间件是每次的请求都会执行一次。

  • lifespan是在应用启动的时候执行一次初始化,结束的时候进行一次清洗。

10.3 异步路由

  • FastAPI 对于不加async的路由是创建新的线程。

  • 对于加async的路由是在主线程中的事件循环中运行。


十一、HTTP

11.1 Headers

headers = { "Content-Type": "application/json", "Authorization": "", }
  • Content-Type强调的是请求体的类型是 JSON 格式。


十二、数据结构与算法

12.1 最大堆

  • 每个节点的值都大于等于其子节点的值。

12.2 完全二叉树

  • 完全二叉树的最后一层后面可以空着,但是从左到右必须是没有空隙的。

12.3 B 树 vs B+ 树

  • B 树:非叶子节点存储着数据和键值。

  • B+ 树:非叶子节点只存储键值,所以可以存放更多的节点,树的高度要更低,可以减少磁盘 IO。

  • InnoDB 存储引擎使用 B+ 树,叶子节点使用双向链表,方便范围查询。

  • B+ 树的节点的键值超过了阈值进行分裂:

    • 左侧数据会在原始的节点。

    • 中间的键值会向上传递。

    • 右侧的键值会放到新创建的节点中。

    • 如果父节点阈值也超了,就会递归分裂。

12.4 LFU

  • LFU 是淘汰最近使用频率最低的数据。

12.5 K-means

  • K-means 是一种无监督的聚类算法。

  • 有无监督要看你是否有人工标注的数据。

  • K-means 是没有人工参与的情况下,进行的一种数据的分类。


十三、数据库

13.1 主键与索引

  • 数据库的主键是一种逻辑的约束,物理层面是以主键索引的形式存在。

  • 主键索引:唯一且非空。

  • 唯一索引:唯一但是可以为空。

13.2 联合索引

  • 联合索引是多个字段组合来进行唯一标识一条记录。

13.3 最左前缀原则

  • 最左前缀原则说的是联合索引,从左往右进行依赖匹配。

  • 比如(A,B,C)的话,就可以匹配 A、AB、ABC 这三种索引类型。

  • 如果是 AC 的话,就会出现中断的问题:A 可以匹配,C 因为中间缺少 B,出现了中断,后面就无法使用索引了。

13.4 覆盖索引

  • 覆盖索引一般是不包括主键索引,因为主键索引根本不需要回表,它的叶子节点本身就有行数据。

  • 覆盖索引一般指的是非主键索引(二级索引),查询这个索引不需要回表到主键索引进行查询,提升查询效率。

  • 比如给 name、age 建立联合索引,然后根据 name 查询 age,联合索引都覆盖了信息,这样就不需要回表查询了。

13.5 选择性

  • 数据库的选择性 = 不同值的记录 / 总的记录。

  • 比如性别:男、女,选择性很低,就不适合作为索引。

13.6 索引使用场景

  • 返回的数据量过大也不会使用索引。

  • 前缀'%ABC'是无法使用索引的,因为前缀是未知的。

  • 'ABC%'可以使用索引,这个前缀是确定性的。


十四、消息队列

14.1 消息堆积

  • 生产者生产的过快或者消费者消费的太慢,导致消息会堆积在消息队列中。

14.2 消息确认机制

  • 消费者消费完消息之后通知消息队列它已经消费成功了。

  • 以防发生重复消费、丢失等情况。

14.3 顺序消费

  • 对于消息队列中很看重顺序的情况,可以使用单消费者的情况。

  • 但是要注意生产者的产生速度,不要太快,不然还是会发生消息堆积的问题。


十五、网络通信

15.1 WebSocket vs SSE

  • WebSocket:双向通信(全双工)。

  • SSE:一个长连接的单向通信,服务器会持续向客户端发送数据,但是长连接会比较耗费资源。

15.2 通信模式

  • 全双工:双向通信,可以同时传递消息。

  • 半双工:不能同时传递消息。

  • 单工:单向传递消息。

15.3 SSE 消息格式

data: 内容\n\n

十六、大模型相关

16.1 基础模型 vs Instruct 模型

  • 基础模型:对文本的无脑续写,指令的听从性差。

  • Instruct 模型:进行了很多指令的微调,去训练模型去听从指令,服从性会更好。

16.2 LoRA

  • LoRA 更新的时候只会更新低秩矩阵 A、B。

  • 到最后再和参数矩阵相加。

16.3 残差连接

  • 残差连接通过+X,来使得层数变大的时候,梯度很小了。

  • 直接乘的话,会不断接近于 0,所以使用+X来保持特性。

16.4 SFT(监督微调)

  • SFT 适合学习好的范式回答和行为。

  • 因为在训练的时候关注的是 output 的 loss。

16.5 RLHF

  • RLHF 会学习人类更喜欢哪种回答。

  • 之前会训练一个 Reward Model。

  • Reward Model 是基于 SFT 监督微调的时候生成了很多答案,然后人类进行答案的偏好打分,最后训练出来的。

16.6 DPO

  • DPO 的 β 越大,会使得 sigmoid 越容易接近上限,容易饱和。

  • 饱和之后就会平缓,loss 越小,越学不到东西,就会很接近原始的模型。

  • 反之亦然,一般选择的参数在 0.1。

16.7 强化学习

  • State:智能体在环境中做动作所需要的全部信息。

  • 价值函数:未来所有的路线、发生的概率、对应的奖励,全部考虑,然后最后得出的结果。


十七、ClaudeCode 压缩

  • 压缩之前要说清楚自己要压缩的目标,保留关键的决策。

  • 压缩工具输出,只保留工具输出的结论。

  • 有些工具的调用是为了某项子任务,丢弃中间重复的、无用的思考。

  • 没有空间的时候是无法进行压缩的,因为压缩的结果是大模型基于上下文窗口产生的,输入的文本超过了这个窗口,大模型是无法接受的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询