ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

用RAG打造家居装修AI咨询助手:从知识库到问答系统实战

用RAG打造家居装修AI咨询助手:从知识库到问答系统实战

装修咨询这件事,做过的人都懂。手机里存了一堆"避坑指南""预算表""验收清单",真到要问点什么的时候——比如"卫生间防水到底刷几遍?""半包和全包的费用为什么差出一辆小车?"——你翻遍收藏夹也找不到一个能直接给出准确答案的入口。这就是我做"家居装修 AI 智能咨询助手"的起因:把散落在各个装修论坛、知识平台、经验贴里的信息重新组织起来,做成一个能用大白话直接提问、几秒就能给出有依据答案的问答系统,让装修咨询从"大海捞针"变成"一问即答"。

这个项目并不算多高深,本质上是用当下成熟的 RAG(检索增强生成)技术,针对家居装修这个垂直领域做了一次务实的落地。它要解决的是三个很具体的问题:第一,装修知识碎片化严重,用户不知道该信谁;第二,通用大模型虽然懂很多常识,但遇到需要精确到工艺标准、材料参数、验收细节的问题时容易含糊甚至编造;第三,现有的装修平台咨询入口大多对接的是人工客服或销售,问专业问题容易被绕到推销上。这篇文章我会从需求拆解、方案选型、核心实现到排错经验,把整个搭建过程完整讲清楚。想给自己的场景做垂直问答应用的开发者,或者单纯想搞明白这种 AI 助手靠不靠谱的普通用户,都能从中拿到点实在的东西。

1. 先看清问题:装修咨询场景里的真实需求

1.1 用户到底想问什么

做这个项目之前,我先花了一段时间整理装修咨询的真实问题。有条件的话可以直接扒某装修平台公开展示的问答记录,或者用问卷调查的方式收集身边正在装修的朋友的疑问。整理下来发现,装修咨询的问题远没有想象中那么发散,集中在六类:

  1. 流程类:"装修第一步该做什么?""先装门还是先铺地板?"
  2. 材料类:"实木地板和复合地板怎么选?""乳胶漆和墙纸哪个环保?"
  3. 工艺类:"防水刷几遍?""瓷砖铺完多久能踩?""水电改造要不要全屋换线?"
  4. 预算类:"100平米半包大概多少钱?""全屋定制和木工打柜子哪个划算?"
  5. 验收类:"交房验房要看哪些项目?""卫生间闭水试验做多久?"
  6. 风格类:"小户型适合什么风格?""原木风和北欧风有什么区别?"

这些问题有一个共性是:答案不是一句话能说清的,它跟户型情况、所在城市、材料档次、施工队伍的水平都有关系。比如同样是"刷几遍防水",卫生间墙面和地面的要求不一样,厨房和阳台的要求又不一样,规范上还有具体的数值。这就决定了,任何一个懂行的老装修师傅在回答问题的时候,都要先补充很多背景条件,而传统搜索把这些细节全都摊在几十个网页里,让用户自己去找,体验自然很差。

这些问题的另一个特点是,"标准答案"其实就藏在一些相对权威的资料里,比如施工规范、品牌官方施工说明、资深从业者写的经验总结。我的目标不是让 AI 凭空回答问题,而是把这类材料收集起来,做成一个可检索的知识底座,让 AI 在回答时先翻资料再说话。

1.2 为什么通用大模型解决不了这个问题

很多人第一反应是:现在的大模型不是什么都懂吗?直接拿通用模型做咨询不就行了?我实测过几款主流通用模型,对装修话题确实能聊,但离"可用"差得远。举几个实际测试暴露的问题:

  • 回答过于笼统:问"卫生间防水做几遍",通用模型会答"一般刷两到三遍",但不会说清楚"墙面和地面是否一致""丙纶布和涂料施工有什么本质区别""闭水试验要在什么节点做"。这种回答没有错,但也没有用。
  • 数据陈旧:装修材料和工艺更新很快,比如近几年流行的"薄贴法"瓷砖工艺,大模型训练数据里可能覆盖不足,回答容易还停留在传统厚贴法的思路上。
  • 没有地区差异意识:同一个全包报价,一线城市和三四线城市能差出每平米几百块,通用模型的回答往往是全行业平均水平的含糊数据。
  • 容易编造细节:当用户追问得更细,比如"墙固和地固到底是不是必需品""水管走顶好还是走地好",模型偶尔会自信地给出一个听起来很专业、实际经不起推敲的说法。

这些问题的根源不在于模型能力不行,而在于模型是基于通用语料训练的,对垂直领域的精确信息掌握不足,也无法针对用户的具体情况做检索和引用。所以必须用 RAG 的思路,把外部可信知识库作为回答的底座,让模型"先查后答"。

2. 方案设计:决定"好不好用"的几个关键选择

2.1 整体架构:RAG是当下最务实的选择

做垂直问答应用,摆在面前的有两条路:微调大模型,或者 RAG。我的选型结论是 RAG,理由很现实:

  • 微调的成本和收益不成正比。微调需要准备大量高质量的问答对数据,装修领域的公开数据很多,但整理成结构化问答对的成本很高,而且一旦知识需要更新(比如某品牌推出了新工艺),微调模型要重新训练一遍,迭代太慢。
  • RAG天然带证据链。RAG 可以把回答对应的原文片段拎出来展示给用户,这是装修咨询场景里特别重要的信任基础。用户问"防水做几遍",AI 回答完了再补一句"依据来自施工规范,详见知识库第X节",用户的接受度会高很多。
  • RAG可以做增量更新。知识库里加几篇文档、重新跑一遍向量化,新知识就生效了。实测从加文档到生效,半小时以内就能搞定。

架构上我采用了最经典的一条链路:用户问题 → 向量检索 → 候选内容聚合 → 提示词组装 → 大模型生成 → 答案附带引用来源。装修领域的问题相对封闭,不需要复杂的工作流和多轮工具调用,简单链路维护成本低、出问题容易排查,这很重要。

2.2 知识库建设:质量优先于数量

知识库是整个系统的地基,这一步偷懒后面会成倍还债。我在构造知识库时定了几条原则:

  • 来源可信度分级。第一优先级是国家和行业施工规范、标准图集;第二优先级是主流品牌的官方施工指南和产品说明书;第三优先级是资深从业者的系统经验总结;第四优先级才是论坛帖子和个人分享。低优先级内容必须经过人工审核才能进入知识库,宁可少放,也不要滥放。
  • 去广告化处理。网上大量装修文章是整装公司、建材品牌的软文,表面讲知识,结尾一定绕到"找某某公司""买某某品牌"。这类内容不管写得多么详实,我都直接排除。
  • 统一格式与术语。装修行业里同一个东西叫法很多,比如"地板压条"有人叫"扣条","阴阳角"有人叫"阳角条"。知识库里如果术语不统一,检索阶段很容易出问题。我在录入资料时会把常见同义词整理成表,在文本里手动标注规范叫法,同时构建一个小的同义词典供检索层使用。
  • 按场景组织文档。我按"空间 + 工序 + 材料 + 风格"四个维度给文档打标签,比如"厨房/防水/涂料/验收",这一步是为了给分块和索引提供依据。

整个知识库我大概维护了二十多篇长文加一百多篇短问答,覆盖了开头整理的六类高频问题。说实话,量不大,但每个问题都能在库里找到对应的、经过验证的答案。

2.3 Embedding选型与向量存储

知识库里的文本要让机器能"找得到",就需要转成向量做相似度检索。这里有一个容易犯的错误——不要一上来就追求高精度的商用 Embedding 接口,先看看开源的通用中文模型够不够用。我用了一套开源的通用中文 Embedding 模型作为主力,实测在装修垂直语料上的召回效果已经能满足需求;后续如果发现检索精度不够,再考虑商用服务做替换也不迟。

向量存储我选了开源方案。原因很简单:项目体量不大,单机部署完全够用,开源方案不需要额外支付服务费用,数据也能保留在本机,更可控。索引构建时选用余弦相似度作为距离度量,比默认的 L2 距离在文本语义匹配上的表现更稳。

2.4 检索不是"把问题扔进去就完了"

RAG 项目的实际效果,一半取决于检索质量,另一半才取决于生成。很多人跑通 demo 之后觉得效果一般,问题往往不在大模型,而在检索到的资料不对。我针对装修领域做了几项针对性优化:

  • 混合检索:只依赖向量的语义检索,会出现一个问题——用户问"防水做几遍",向量相似度可能把"涂料刷几遍""油漆涂刷次数"这类文章也捞出来,因为语义上太接近了。我加了 BM25 关键词检索,把两种方式的召回结果做融合,取并集后再统一排名。这样"防水"这个关键词就能稳住在结果里。
  • 查询改写:用户提问很口语化,比如"墙皮要不要铲掉",知识库里写的是"原墙面基层处理"。直接检索很难命中。我的做法是,在检索前先用大模型做一次轻量的改写和同义扩展,把口语问题映射到知识库里更规范的表述。
  • 重排:混合检索召回的数量可以放宽到 10~15 条,然后用一个轻量级的重排模型或简单规则,把与问题真正对口的片段排到前面。这一步对最终效果提升非常明显。

3. 核心实现:把知识"喂"给 AI 的完整流程

3.1 数据准备与清洗过程

我从确定选题到落地,花费时间最长的不是写代码,而是准备数据。原始资料要么是网页格式,要么是 PDF 文档,转换出来全是混乱的换行符和广告区块。清洗流程大致有三步:

第一步,转纯文本,把所有内容统一转成 Markdown 格式。对网页内容,用通用抽取工具把正文提取出来,丢掉导航、侧栏、评论区;第二步,人工逐篇审阅,标记可信度级别、删除广告软文、修正错别字和明显过时的内容;第三步,统一格式,每篇文档都用多级标题组织,重要工艺参数用加粗和表格突出,方便后续分块时保持语义完整。

这一步我有一个要特别提醒的坑:不要高估自动化清洗的效果。装修行业的网页内容质量参差不齐,正则抽出来的正文经常夹着无关的行业新闻和推荐位。我最后是由人工按一篇一篇的粒度审核的,虽然累了点,但建模之后再返工的代价高得多。

清洗完成后的数据结构大致是:

source: 某施工规范/某经验总结 category: 卫生间防水 title: 卫生间防水施工要点 content: | ### 基层处理 ### 防水涂料施工 ### 闭水试验

3.2 分块策略:切分可不是"按字数截断"

直接把一篇长文章塞给模型不现实,上下文长度有限,而且检索时整篇文章作为一坨向量,粒度太粗,定位不到具体答案句。分块是 RAG 效果的关键变量,我的做法是:

  • 优先按结构切分。Markdown 的一级、二级标题就是天然的切分边界,先把文档按标题拆成多个小节,避免一个片段跨两个主题。
  • 控制块大小。每个分块控制在 300~500 字之间。太短则信息不全,模型可能拿不到完整上下文;太长则引入噪声,且占用大模型的输入窗口。这个数字不是拍脑袋定的,我对比过 200 字、400 字、800 字三档,400 字左右在命中率和回答完整度上最平衡。
  • 设置重叠。相邻分块之间保留 50~100 字的重叠。原因很朴素:很多句子跨段落才说完整,比如某节末尾说"一般推荐两遍",下一节开头才说"第一遍和第二遍的间隔时间",硬切会把语义截断。
  • 关键表格转成文字。装修文档里常有参数表,比如"防水层厚度要求""不同房间的用水要求",直接保留 Markdown 表格会让检索和模型理解都变困难。我在预处理时把表格逐行转成"指标:数值"的自然语言,放到对应分块里。

3.3 Embedding 与向量库写入

分块完成后就是向量化写入。原本我想把全部代码放在这里展示,但实际核心逻辑很短,主要是两个动作:用 Embedding 接口把每个分块变成向量,再把向量和原文元数据写进向量库。

核心流程大概长这样:

from vector_store import VectorStore # 封装好的向量库操作 def load_knowledge_base(file_paths): store = VectorStore(collection_name="decoration_kb") for path in file_paths: chunks = chunk_markdown(path) for idx, chunk in enumerate(chunks): store.add( text=chunk["content"], metadata={ "source": chunk["source"], "category": chunk["category"], "title": chunk["title"], "chunk_id": idx } ) return store

写入的时候,metadata(来源、分类、标题、分块编号)一定要完整保存,这一步决定了后面能不能做引用溯源。很多人觉得 metadata 无所谓,省掉以后再想补,就得重新做一遍向量化,很麻烦。

3.4 检索与答案生成的完整链路

检索时,核心就两步:先把问题向量化,查向量库取 topK 候选;再把候选列表和问题一起交给大模型。但为了让代码干净、易维护,我把流程拆成三个函数:

def retrieve(query, top_k=8): # 1. 查询改写(可选,交给大模型做同义扩展) rewritten = rewrite_query(query) # 2. 向量检索 vector_results = vector_store.query(rewritten, top_k=top_k) # 3. 关键词检索 BM25 keyword_results = bm25_search(rewritten, top_k=top_k) # 4. 融合去重,按分数重排 return merge_rank(vector_results, keyword_results) def generate_answer(question, contexts): system_prompt = build_system_prompt() user_prompt = f"问题:{question}\n\n资料:\n{contexts}" # 调用大模型接口,返回答案和引用标记 return llm_call(system_prompt, user_prompt) def chat(question): docs = retrieve(question) answer_text, citations = generate_answer(question, docs) return format_response(answer_text, citations)

三个函数各管一件事,哪一层出了问题都能单独排查。我在开发过程中发现,检索层的问题最多,因为向量召回是有一定随机性的,同一问题改写一版和原版召回结果会有差异,所以我在查询改写时特意要求大模型"不能改变原意,只能做同义替换和关键实体补充",这样改写出来的 query 更稳。

4. 实操过程:从零搭建一套最小可用系统

4.1 环境准备与依赖安装

环境这块不用多说,Python 3.10 以上版本,虚拟环境隔离依赖,避免和系统环境冲突。需要安装的库也不复杂:向量库客户端、Sentence Transformers 系列 Embedding 模型、大模型 SDK、HTML/文本解析工具。

装完依赖后,我先用一个最小的冒烟测试验证链路通不通——造两三条假知识,跑一遍检索和生成,确认每个环节都能正常出结果。这一步做扎实,后面扩展知识库就只是数据活。

4.2 构建知识库:一次可重复的流程

我把知识库构建写成一个脚本,确保任何时候新增文档都能一键重建。流程是:读入 Markdown 文档 → 按结构分块 → 文本清洗 → 向量化 → 写入向量库 → 记录一份索引文件。

索引文件记录的是每篇文档的标题、来源、分块数、向量库中的 ID 区间。为什么要记录这个?因为后面查"这个答案引用的是哪篇文章"只需要反查这个索引,不用翻向量库的原始记录。另外,知识库更新时,如果某篇文章被替换了,得能知道哪些旧的向量分块要被清掉,否则会出现新旧知识打架的问题。

4.3 提示词工程:让模型"知道边界"比"发挥聪明"更重要

大模型生成答案时,提示词直接决定了回答质量。我在多次调试后,把系统提示词固定为四个部分:

第一,角色设定。明确告诉模型"你是一名装修顾问,你的回答必须基于提供的资料,不要随意发挥"。第二,边界约束。如果资料里找不到答案,必须说"根据现有资料无法回答",不能编造。第三,引用要求。回答中涉及关键结论时,要标注对应的资料编号。第四,格式要求。如果问题包含多个要点,用分点回答,方便用户阅读。

一个适合装修咨询场景的提示词模板大致是:

你是装修咨询助手。你的任务是基于用户问题,从给定的资料片段中寻找答案。 规则: 1. 如果资料中没有相关信息,请直接回答"根据现有资料暂时无法回答这个问题"。 2. 不要编造工艺参数、材料性能或价格数据。 3. 回答中的每个关键结论,请在末尾用[参考片段n]标注来源。 4. 当问题涉及规范性要求(如防水高度、闭水试验时长),请优先引用权威规范类资料。 5. 回答要口语化、有条理,但不要偏离资料内容。

实测这套提示词能大幅减少幻觉。有一次我故意把一个很偏的问题"阳台可以改成卫生间吗?"丢给系统,知识库里完全没有相关内容,模型正确回答"根据现有资料暂时无法回答这个问题",还补了一句"建议咨询当地物业和相关专业设计师",这个补充没有编造实质内容,是我可以接受的边界输出。

4.4 完整问答演示:一个真实可跑的案例

写完代码后,我用高频问题做了一遍验收。拿"卫生间防水做几遍"举例。

第一步,查询改写。原问题被发给大模型做改写,返回的改写结果是"卫生间防水 施工 刷几遍 涂刷遍数 要求",比原问题多了几个规范化的关键词。

第二步,向量检索加 BM25 检索。向量召回的结果里包括卫生间防水的施工文章和几篇关于"涂料涂刷工艺"的泛化文章;BM25 因为他包含"卫生间""防水""几遍"这几个明确关键词,命中了知识库里专门的"防水施工"章节。

第三步,重排融合。经过重排后,排在首位的是"卫生间防水施工要点"这篇文章里的"防水涂刷遍数与厚度"小节,内容包含"墙面防水涂料涂刷两遍,高度不低于 1.8 米""地面防水涂刷两遍以上,厚度达到 1.5 毫米"等具体参数。这个结果正是用户需要的。

第四步,生成。模型基于这些片段生成了一段有引用标注的回答,关键信息完整,还特别说明"不同品牌涂料可能存在差异,具体以产品说明和施工规范为准"。

整个链路从提出问题到拿到回答大概三秒。演示时我比较注意的点是,回答内容要稳定——同一个问题连续问三遍,答案应该基本一致。如果模型偶尔抽风给出不同版本的回答,就需要排查是不是检索结果不稳定,或者是温度参数设置过高。

4.5 加一层简单的对话界面

虽然项目核心是后端逻辑,但为了演示和测试方便,我加了一个极简的 Web 界面。技术选型上直接用轻量级框架,后端起一个问答接口,前端写一个静态 HTML 页面,包含对话输入框和历史消息列表。这个界面没有做复杂的功能,但保留了引用来源的展示区,回答中的[参考片段n]会转成可点击的链接,点开能看到原始知识片段。

这一步的价值在演示时体现得很明显。给用户测试时,如果他们看到回答底部跟着一段"来自某施工规范的原文摘要"的引用,信任感会提升很多,也更愿意继续问下去。

5. 常见问题与排查技巧实录

5.1 检索结果为空,或者答非所问

这是 RAG 项目最常见的问题。排查思路按顺序来:

  • 查知识库有没有相关内容。如果库本身没有,检索结果为空是正常的,先补数据。
  • 查同义词扩展。用户问"墙皮要不要铲掉",库里的标题是"原墙面基层处理",向量可能召回,BM25 召不回。这种情况必须靠查询改写,把两者兜住。
  • 查 Embedding 模型在垂直领域的表现。通用中文模型在装修领域的效果基本够用,但如果你发现某些行业术语的向量表示明显有问题,考虑换垂直微调过的 Embedding 模型。

我实测发现,很多"答非所问"其实是查询改写太激进导致的。比如用户问"半包和全包的区别",改写成了"装修包工包料方式对比",反而把"半包""全包"这两个最关键的用户词丢掉了,召回结果自然乱了。所以改写规则里有一条硬约束:保留原问题中的核心名词和数字,只能增加同义表达,不能删除原词。

5.2 模型幻觉:编造参数和价格

装修咨询里最怕的就是 AI 编造工艺参数。比如用户问闭水试验要多久,如果模型回答"48小时",而规范要求是"不少于24小时",这个错误会直接误导施工。

我的解决办法有三层。第一层是提示词约束,明确要求没有资料不得回答;第二层是引用机制,关键结论必须标注来源片段,用户和开发者都能溯源检查;第三层是幻觉自检后处理,大模型生成完回答后,让一个独立质检环节(可以是另一个模型调用,也可以是自己写规则)检查回答中的数字、参数是否能在已检索到的资料片段里找到对应描述,不一致就标记并重新要求模型修正。

三层叠加之后,致幻率明显下降。当然,这个质检逻辑会增加一次大模型调用,成本要多算一点,但在装修咨询这种对正确性要求高的场景下,这笔开销值得。

5.3 多轮对话:用户会说"那价格呢"

单轮问答能跑通之后,马上会遇到多轮对话问题。用户问完"卫生间防水怎么做",下一句很可能就是"那大概要花多少钱?"这里的"那"指的是卫生间的防水施工,而不是泛指装修报价。

我的做法比较简单但有效:前端维护一个历史消息上下文,传递给后端时,先让大模型做一次"指代消解",把当前问题和历史问题合并成一个完整独立的问题,再用合并后的问题去检索。比如"那大概要花多少钱"加上历史"卫生间防水怎么做",会被改写为"卫生间防水施工大概要花多少钱"。这样检索才能命中预算相关的知识片段。

要注意的是,多轮会话历史不可能无限增长,超过十轮就截断最老的消息,防止上下文太长影响改写效果。同时在改写时明确告诉模型:如果当前问题与历史问题无关,不要强行关联。

5.4 知识库更新:新旧知识打架怎么办

装修知识是有时效性的,尤其是材料品牌、流行风格和施工工艺。比如前几年流行实木踢脚线,现在很多项目开始用铝合金极简踢脚线,旧知识和新知识并存时,AI 可能同时引用两者,给出矛盾的建议。

我整理了一套简单的更新策略:每条知识在进入库时打上"入库时间"标签;检索阶段,如果候选片段之间存在明显冲突(比如在同一个问题上参数不一致),优先选择入库时间更新、来源可信度更高的一方;生成阶段也会要求模型遇到冲突时"优先采用更新更权威的来源"。这套策略避免了大部分矛盾情况,但前提是知识库本身必须经过人工审核,不能无脑堆数据。

5.5 成本控制:别让每个问题都烧钱

RAG 的成本大头是大模型生成的 token 消耗,以及查询改写、质检等环节增加的额外调用。实测下来,一个普通问题平均要消耗约两千 token 的输入上下文,加上改写和质检,成本大概是直接问通用模型的两到三倍。

控制成本的办法有几个:一是知识库分块质量做高,检索命中准确,就不需要把十几篇文档全部塞给模型,控制上下文字数;二是缓存高频问题,装修咨询里的高频问题其实就那几十个,完全可以把第一次回答存进缓存,后续命中直接返回;三是优化改写逻辑,简单问题(比如"你好"“在吗”)不走改写,直接进普通对话流程。

我从一开始就把成本控制纳入设计,而不是等项目跑大了再优化,建议做类似项目的也这么做,否则每个测试问题都在烧钱,测试意愿会大打折扣。

6. 测试与验收:怎么衡量这个系统"能用"

6.1 建立评测集,不要凭感觉判断

没有评测集就谈不上优化。我从真实咨询记录里挑了一百个高频问题,涵盖开头整理的六类场景,构成了一个最小评测集。每次改动知识库、提示词或检索逻辑,就跑一遍评测集,统计"回答是否可接受"。

"可接受"的标准我自己定了一套:回答正确(关键参数准确)、有出处(能从知识库追溯)、不编造(库中没有的不乱说)、可操作(用户听完知道怎么做)。这套标准偏主观,但用于横向对比版本迭代已经够了。如果要做更严谨的评测,可以引入人工打分的机制,代价高一些,但结果更可靠。

6.2 边界案例测试

除了常规问题,我还会测一批"边界案例"。比如问"装修公司跑路了怎么办",知识库里没有合同纠纷相关的权威资料,模型应该拒绝回答而不是瞎建议;问"请帮我设计一套三室两厅的方案",这种开放式的创作问题,RAG 的系统约束效果也很明显——模型会基于知识库中关于空间规划的文档给出框架性建议,但不会越界去渲染具体户型图。

这些边界案例的通过标准是"不犯错"而不是"回答得好"。把"不犯错"这条底线守住,系统才真正可对外演示。

我知道很多人做这类项目会把精力全放在模型和提示词上,实际上数据质量、检索逻辑、评测闭环才是让它"像个真正的产品"的关键。这个项目做下来,我最深的体会是:垂直领域的 AI 应用,难点不在 AI 本身,而在于把领域知识整理成模型能用的形式——分块、检索、引用,每一步都是在跟信息的组织方式打交道。装修咨询只是我挑的一个方向,这套思路完全能迁移到其他垂直行业,比如家电维护、园艺种植、宠物喂养,逻辑是一样的:找一批信得过的资料,搭一个能查能引的链路,再配一套严格的评测标准,剩下的就是不断迭代数据了。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进