章节二十六:智库——导入流程基础架构
一、骨架代码
1. 状态定义
所有导入流程的节点共享同一个状态对象,用来在节点间传递数据。状态中定义了文件路径、文件标题、Markdown内容、切分结果、向量列表、任务ID等字段。
定义方式使用TypedDict,给每个键指定类型,方便IDE提示和类型检查。
2. 节点基类设计
为了避免每个节点都重复写日志、异常捕获等通用代码,设计了一个NodeBase抽象基类:
- 通用逻辑封装:
__call__方法统一处理日志记录、任务追踪、异常捕获。 - 子类约束:强制子类覆盖
name属性,实现核心业务方法process。 - 兼容LangGraph:实例化后可直接作为节点加入工作流。
每个具体节点继承NodeBase,只需实现process方法即可。
3. 节点注册
导入流程共有8个节点:
- node_entry:入口节点,判断文件类型。
- node_pdf_to_md:PDF转Markdown。
- node_md_img:图片处理。
- node_document_split:文档切分。
- node_item_name_recognition:商品名识别。
- node_bge_embedding:向量化嵌入。
- node_import_milvus:写入Milvus。
开发策略采用"自顶向下"模式:先创建所有节点的骨架(只打印日志),再串联主图验证流程通畅,最后逐一填充节点业务逻辑。
4. 主图编排
主图的工作流程:
- 入口节点接收文件后,根据文件类型路由:
- PDF文件走:入口 -> PDF转换 -> 图片处理 -> 文档切分 -> 商品识别 -> 向量化 -> 写入Milvus
- Markdown文件走:入口 -> 图片处理 -> 文档切分 -> 商品识别 -> 向量化 -> 写入Milvus
- 其他格式文件直接在入口节点结束
验证时分别测试PDF、Markdown和其他格式文件,确认路由正确。
5. 工作流类封装
将工作流改造成类的形式,提升可维护性:
- 封装内部逻辑,对外暴露简洁接口。
- 懒加载编译,首次执行时才触发。
- 每个实例拥有独立的节点和工作流对象,支持多实例并发。
二、入口节点
1. 功能说明
入口节点是整个导入流程的第一个节点,负责接收文件并判断类型,决定后续走哪条路线。
核心逻辑:
第一步:从状态中获取local_file_path(文件路径)。
第二步:检查文件后缀是.pdf还是.md。
第三步:根据类型设置对应标记——PDF设置is_pdf_read_enabled和pdf_path,Markdown设置is_md_read_enabled和md_path。
第四步:从文件名中提取file_title,作为后续元数据。
2. 路由分发
主图中通过路由函数读取入口节点设置的标记,决定下一步走哪个节点:
- 如果
is_pdf_read_enabled为True,路由到PDF转换节点。 - 如果
is_md_read_enabled为True,路由到图片处理节点。 - 其他情况直接结束(END)。
这样不同格式的文件会走不同的处理路径,PDF需要先转换再处理,Markdown则跳过转换直接处理图片。
名词解释
NodeBase:节点抽象基类,封装了日志、异常处理等通用逻辑,子类只需实现业务方法。
骨架代码:只有基本结构没有完整业务逻辑的代码,先搭框架再填内容。
入口节点:工作流的第一个节点,接收输入、判断类型、启动整个流程。
路由分发:根据条件决定下一步走哪个节点的机制,类似if-else分支。
自顶向下:先设计整体框架再实现细节的开发方式,先保证流程走通再填功能。
主体识别:从文档中自动找出核心主题或关键实体,比如产品名称。
向量化:把文字转成数字向量的过程,方便计算机做相似度比较。