🧠 项目背景
在文旅数字化服务场景中,无论是博物馆、美术馆、非遗展陈,还是城市旅游导览,用户真正需要的往往不是静态页面上的一段介绍,而是一个能够围绕当前场景持续理解、持续回应的智能助手。比如在展馆里拍下一件展品后,用户希望立即了解它的历史背景、艺术特色和相关故事;又或者在出行前后,希望快速获得路线、开放时间、参观建议和文化内容推荐。传统的图文介绍页、固定问答入口和人工检索式服务,在面对这类动态、多轮、上下文相关的需求时,体验并不理想。
如果继续往下拆,会发现问题的核心并不只是"生成一句回答",而在于文旅知识本身天然分散、表达形式复杂、服务链路又强依赖上下文。展品介绍、景区资料、导览文案、活动信息、FAQ 往往散落在 Markdown、PDF、DOCX 等不同载体中,缺少统一的知识组织与检索方式;而用户的问题又常常带有模糊描述、口语化表达和临时偏好,单纯依赖关键词检索或静态页面,很难给出准确、流畅且有针对性的回应。
因此,这类场景通常会集中暴露出几个典型问题:
- 知识来源分散:文旅内容分布在多种文档和系统中,缺少统一的知识组织与检索入口
- 交互体验不连续:传统检索更适合回答单点问题,难以处理追问、澄清和上下文延续
- 个性化服务能力弱:不同用户在兴趣、时间、路线和内容偏好上差异明显,固定模板难以满足真实需求
- 内容复用与传播效率低:高质量文化内容难以结构化沉淀,更新、维护和复用成本都偏高
我之所以开始做这个项目,也和自己在 Agent、RAG 与知识库方向的实践直接相关。结合"识物探趣"项目中的实际经验,我已经验证了文旅知识库构建、RAG 检索链路、多轮对话和规划型 Agent 在文化展品场景中的可行性,也更清楚工程落地时会遇到的检索效果、上下文保持和系统稳定性问题。文旅 Agent 正是在这样的背景下启动的:希望把知识库、对话交互和任务规划能力整合起来,做一个既能理解文旅内容、又能提供个性化讲解、旅行咨询与文化推荐服务的智能系统,进一步提升文旅内容的数字化服务能力与传播效率。
🎯 目标功能
系统设计围绕三个核心功能展开:
- 文件上传知识库(知识库管理):这个功能支持团队将各种文旅内容文档上传到系统,比如展品图录、场馆资料、导览文案、活动说明等。它为大模型提供了可靠的知识来源,实现了文化内容资产的持续沉淀和高效复用。
- 对话讲解支持(Chatbot):用户可以通过自然语言与系统进行交互,围绕展品、展厅、活动和文旅内容进行连续提问。例如,你可以直接问:“这件展品的历史背景是什么?“系统会结合知识库返回更贴合上下文的讲解内容。
- 智能导览与内容推荐(旅游服务Agent):系统会根据用户的兴趣、时间和当前场景,生成更个性化的导览建议与内容推荐。它既可以围绕单个展品做延伸讲解,也可以根据用户偏好推荐适合重点参观的展厅、活动或文化路线。
🏗️ 技术选型
基于项目的需求和目标,我们进行了以下技术选型:
🛠️ 前后端开发框架
- 前端:Vue3 + ElementPlus
- 后端:Kitex + Hertz + Eino
- 数据库:MySQL
- 缓存:Redis
- 消息队列:Kafka
- 向量数据库:Milvus
💡 Eino框架 vs LangChain
Eino框架是字节跳动开源的一个大模型应用开发框架,核心思想是用图 Graph 来定义 Agent 的工作流。在我的理解里,图中的每个节点代表一个原子能力,比如大模型节点、召回使用的 Retriever 节点等。边则代表了这些节点之间的执行顺序和数据流向。
在项目中,我用 Eino 来构建不同的 Agent。比如 ChatAgent,把召回、Prompt 构建、ReAct 定义成节点,然后用边把它们连起来。这样,整个 Agent 的执行过程就变得非常清晰和可配置。选择 Eino 主要是看中它这种直观的图编排能力和对工作流状态的维护,让我们能相对容易地构建和调试复杂的 Agent。
为什么不选择 LangChain?其实要从它们适合的场景来分析:
选择 Eino 的场景:
- 高性能生产环境:需要处理高并发请求
- 强类型要求:需要编译时类型安全
- Go 技术栈:团队主要使用 Go 语言
选择 LangChain 的场景:
- 快速原型开发:需要快速验证想法
- 社区资源:需要大量的示例和教程
- Python 生态:团队熟悉 Python 和相关库
在实际项目中,技术选型应该基于团队的技术栈、项目需求、性能要求和长期维护考虑。对于追求性能和稳定性的生产环境,Eino 提供了优秀的 Go 原生解决方案。而对于快速迭代和研究型项目,LangChain 的灵活性和生态优势更加明显。Eino 虽在生态覆盖度上略逊于 LangChain,但其强类型带来的稳定性、Graph 编排的开发效率、字节实践的可靠性,更适合企业级生产落地。
📊 向量数据库为什么选择 Milvus?
目前市面上有四种类型的向量数据库:
- 集成了向量搜索插件的现有关系型或列型数据库,比如
PGVector - 支持密集向量索引的传统倒排索引的
ElasticSearch - 基于向量搜索库构建的轻量级向量数据库,
Chroma - 专用向量数据库:专门为向量搜索而设计的数据库
MilvusFaissHNSW
Milvus 是一个基于向量数据库的系统,它支持高维度向量的存储和检索。在智能文旅服务 Agent 中,向量数据库主要用于存储展品资料、场馆信息和活动文档的向量表示,以便后续的语义检索与上下文召回。
选择 Milvus 通常不是因为"它能存向量"这么简单,而是因为你需要一个把向量检索当成核心能力来设计的系统:既能做高性能 ANN,又能做过滤、混合检索、全文检索和更大规模的扩展。Milvus 官方把自己定位为开源、云原生的向量数据库,面向从本地原型到大规模分布式部署的场景。
主要优势:
- Milvus 不只支持 dense vector,还支持 sparse vector、BM25 全文检索、multi-vector hybrid search,并且可以把这些能力放在同一个 collection 里组合使用。对很多知识库检索来说,这意味着你可以把"语义召回"和"关键词命中"放到同一套检索链路里,而不是自己拼很多外部组件。
- Milvus 对工程化检索支持比较完整。Milvus 支持在 ANN 搜索前先做 metadata filtering,把检索范围限制在满足条件的数据子集里,这对带租户、时间、类别、权限等条件的业务很重要。它还支持 rerankers、多种搜索类型,以及把搜索和结构化字段一起组织在 collection 中。
🤖 模型集成
项目会围绕文化展品导览与文旅内容服务集成大语言模型能力,主要用于:
- 展品讲解生成:结合识物结果、知识库内容和当前上下文,自动生成更自然、更连贯的展品讲解内容
- 文旅问答与多轮对话:理解用户关于展品、场馆、活动和路线的提问,并在连续追问中保持上下文一致性
- 导览推荐与任务规划:在需要多步处理的场景下,帮助系统完成内容推荐、导览建议和任务拆解
模型选型方面:
- 基座模型:本地
Ollama部署的Qwen2.5-VL-7B-Instruct模型,尽量减少对外部 API 的依赖,兼顾数据安全与本地调试便利性。 - 嵌入模型:选择
BGE-M3,维度为1024,用于将展品资料、场馆信息和活动文档转成适合检索的语义向量。 - 重排模型:选择
bge-reranker-v2-m3这类Cross-Encoder重排模型,对召回结果做相关性精排,进一步提升文旅问答与讲解场景下的检索准确性。
🧪 核心功能设计
🧭 识物导览服务流程
结合"识物探趣"项目中的实际设计,文旅 Agent 的核心业务流程更接近下面这条链路:
- 用户请求接入:用户可以通过拍照识物、文本提问等方式发起请求。系统首先接收展品图片、问题文本以及当前会话上下文,作为后续理解与检索的输入。
- 意图识别与任务判断:系统会先判断用户当前需求属于展品讲解、场馆信息查询、活动检索,还是路线推荐与内容推荐。如果是拍照场景,还需要先把视觉输入转成可检索、可推理的文本语义。
- 知识检索与上下文构建:在明确意图之后,系统会从文旅知识库中召回相关资料,并结合多轮对话记忆补齐上下文。这里底层依赖 RAG 检索链路,把展品图录、导览文案、活动说明等内容组织成适合注入大模型的上下文。
- Agent 规划与工具调用:对于简单问题,系统可以直接基于检索结果生成回答;对于需要多步处理的场景,则由 Agent 进一步做任务拆解、步骤规划和动态调整。这个过程中会结合
Plan-Execute-Replan与ReAct,把知识检索、工具调用和结果生成串起来执行。 - 结果生成与持续交互:最后由大模型生成个性化讲解、旅行咨询或文化推荐结果,并通过
SSE实时返回给用户。同时系统会维护会话状态,方便用户继续追问,让整个交互保持连续性而不是"一问一答"式的割裂体验。
🧩 系统架构
系统架构如果按照职责来拆,可以分成四个部分:接入层、知识与检索层、Agent 编排层,以及存储与异步支撑层。这样设计的原因很直接:文旅场景既要处理用户实时提问,也要处理知识入库、检索优化、多轮对话状态维护和复杂任务规划,如果把所有能力都堆在一个 Agent 里,后续无论是扩展能力还是排查问题都会变得很困难。
- 接入层:系统对外提供拍照识物、文本提问、知识库文档上传等入口,负责承接用户请求并返回实时结果。前端侧用
Vue3 + ElementPlus承载交互,服务侧通过Hertz + Kitex提供接口能力,并结合SSE将回答生成过程和中间结果实时回传给用户,保证交互的连续性。 - 知识与检索层:这一层负责把
Markdown、PDF、DOCX等文旅资料解析入库,完成文档切分、向量化、索引构建和检索链路编排。检索上采用"粗召回 + 精排"的两阶段架构,在粗召回阶段结合BM25与向量检索,在融合阶段使用RRF进行排序,最后用Cross-Encoder做ReRank,尽量兼顾召回范围和答案准确性。 - Agent 编排层:核心由对话 Agent 和旅游服务 Agent 组成,底层基于
Eino进行工作流编排。对于复杂任务,系统采用Plan-Execute-Replan构建规划能力,并在执行过程中结合ReAct根据中间结果动态调整步骤,把知识检索、工具调用和结果生成串成一条可执行链路。 - 存储与异步支撑层:结构化数据存放在
MySQL,会话态、临时缓存和热点数据交给Redis,向量检索依赖Milvus,异步任务和链路解耦由Kafka承担。实际落地时,我把Redis + MySQL + Milvus组合成 Agent 的异构存储体系,再结合Kafka驱动异步更新,并配合会话状态优先和版本号机制做一致性兜底,以提升多轮对话场景下的上下文保持能力与系统稳定性。
从用户视角看,这套架构最终沉淀为三个核心模块:
- 知识库管理模块:当系统需要回答特定领域问题时,如果直接把长文本交给大模型,会受到上下文窗口、响应速度和成本的限制。知识库管理模块负责把原始文档转成可检索、可复用的知识资产,为后续的 RAG 链路提供稳定的数据底座。
- 对话Agent:这是系统的核心交互入口,它能够理解用户问题、结合知识库与相关工具能力完成多轮对话,并给出更贴合上下文的回答。它解决的不只是"能回答”,更是"能连续地回答”。
- 旅游服务Agent:这一模块更偏向复杂任务处理,它会在理解用户目标后进行任务拆解、步骤规划和动态调整,把个性化讲解、内容推荐、旅行咨询等需求组织成一条更完整的执行链路。
📋 项目预期
✅ 基础预期与达成情况
项目在启动阶段,我给它设定的基础预期主要有三个:先把文旅知识资产沉淀成可检索的数据底座,再把对话与导览链路真正跑通,最后让系统具备持续扩展和工程落地的基础。目前来看,这三个方向的核心能力都已经完成了初步落地:
- 知识底座预期:系统能够支持
Markdown、PDF、DOCX等多格式文旅资料解析入库,完成文档切分、向量化和索引构建,为后续问答、讲解和推荐场景提供统一、可复用的知识来源。 - 检索与交互预期:系统能够围绕文化展品与文旅咨询场景完成"用户提问/识物 -> 检索召回 -> 排序筛选 -> 生成回答"的完整链路。当前 RAG 检索采用"粗召回 + 精排"的两阶段架构,结合
BM25、向量检索、RRF和Cross-Encoder ReRank,在实验评估中做到Recall@5 = 85%、MRR = 0.86。 - 工程可扩展预期:系统不只是一个停留在演示层的 Demo,而是具备继续演进的工程原型。当前已经基于
Redis + MySQL + Milvus构建异构存储体系,并结合Kafka驱动异步更新,配合会话状态优先和版本号机制,为多轮对话场景下的上下文保持和系统稳定性提供支撑。
🚩 最终预期与当前短板
这个 Agent 的最终预期,并不是只做一个"能回答问题的导览机器人",而是打造一个面向文旅场景的智能服务入口:它既能理解文化内容,也能围绕用户的当前位置、兴趣偏好和上下文需求,持续提供讲解、咨询、推荐和任务规划能力。不过从目前阶段来看,离这个目标还有几个比较明确的短板,这些也是我后续优化的重点:
- 复杂任务规划能力仍需增强:虽然已经引入
Plan-Execute-Replan和ReAct来提升任务拆解与动态调整能力,但在开放式、多约束的复杂文旅咨询场景下,规划链路的稳定性还不够强,尤其是在跨多个目标和条件的场景中更容易出现偏移。 - 个性化服务仍以会话级能力为主:当前系统已经具备多轮对话状态维护和异构记忆存储能力,但对用户长期偏好、历史行为和反馈结果的利用还不够深入,距离真正意义上的持续学习和个性化推荐闭环还有一段距离。
- 多模态理解链路还不完整:项目场景天然包含拍照识物、图文联合理解等需求,但当前能力重点仍放在知识检索与文本推理上,后续还需要继续增强视觉理解、图文对齐和多模态知识检索能力,让"识物"真正和"懂内容、会讲解、能推荐"形成统一闭环。