下篇:从检索到交互 — 物流RAG问答系统与WebUI全实现

一、RAG问答系统总览

上篇完成了知识库构建(离线),下篇聚焦在线推理链路

text

复制代码
用户问题 → 向量检索(Top-K)→ 上下文注入Prompt → LLM生成 → 返回
  • 核心问答逻辑(检索 + Prompt构建 + LLM调用)

  • 基于Streamlit的Web交互界面


二、核心问答实现

2.1 加载向量库
python 复制代码
db = FAISS.load_local("../faiss/wuliu", embeddings, allow_dangerous_deserialization=True)

注意allow_dangerous_deserialization=True 是LangChain的安全机制,因为pickle反序列化可能存在风险,在可信环境中可开启。


python 复制代码
docs = db.similarity_search(question, k=2)
  • 将用户问题通过同一Embedding模型向量化

  • FAISS计算余弦相似度,返回Top-K最相关文档块

  • k=2 控制召回数量:过少则上下文不足,过多则Prompt超长


设计细节:将检索到的多个文档块合并为一个字符串,作为LLM的上下文。换行符清理保证文本整洁,避免干扰模型理解。

python 复制代码
def get_related_content(related_docs):
    related_content = []
    for doc in related_docs:
        related_content.append(doc.page_content.replace("\n\n", "\n"))
    return "\n".join(related_content)

设计细节:将检索到的多个文档块合并为一个字符串,作为LLM的上下文。换行符清理保证文本整洁,避免干扰模型理解。


2.4 Prompt工程:模板设计

模板设计要点

python 复制代码
PROMPT_TEMPLATE = """
基于以下已知信息,简洁和专业的来回答用户的问题。不允许在答案中添加编造成分。
已知内容:
{context}
问题:
{question}"""

模板设计要点

  • 角色约束:要求"简洁和专业",控制回答风格

  • 知识边界:明确"不允许添加编造成分",限制幻觉

  • 结构化{context}{question} 占位符清晰分离


2.5 LLM调用:ChatOpenAI兼容接口

设计亮点

python 复制代码
llm = ChatOpenAI(
    model="qwen3.7-max",
    api_key=os.getenv("QWEN_API_KEY"),
    base_url=os.getenv("QWEN_BASE_URL")
)

设计亮点

  • 使用 ChatOpenAI 统一接口,兼容OpenAI、Qwen、DeepSeek等多种模型

  • 通过 base_url 灵活切换API端点

  • 环境变量管理敏感信息(dotenv 加载)


三、WebUI实现

3.1 会话式检索链:ConversationalRetrievalChain

这个Chain做了什么?

python 复制代码
from langchain_classic.chains import ConversationalRetrievalChain

chain = ConversationalRetrievalChain.from_llm(
    llm=llm,
    retriever=db.as_retriever()
)

这个Chain做了什么?

  1. 将用户问题 + 历史聊天记录合并成一个"新问题"

  2. 用新问题检索向量库

  3. 将检索结果 + 历史上下文一起送入LLM生成回答

相比基础RAG,它支持多轮对话,能在上下文基础上理解指代(如"那它什么时候到?"中的"它")。


3.2 Streamlit交互界面

Streamlit优势

python 复制代码
st.set_page_config(page_title="物流行业信息咨询系统", layout="wide")
st.title("物流行业信息咨询系统")

Streamlit优势

  • 纯Python构建WebUI,无需前端知识

  • 热重载,修改代码即刷新

  • st.chat_message 提供类ChatGPT的对话气泡样式


3.3 会话状态管理
python 复制代码
if "messages" not in st.session_state:
    st.session_state.messages = []

for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])

st.session_state 核心作用

  • 跨用户交互保持数据(类似内存中的全局状态)

  • 存储 messages 列表实现聊天历史持久化(单会话内)


3.4 流式输出模拟
python 复制代码
full_response = ""
for chunk in assistant_response.split():
    full_response += chunk + " "
    message_placeholder.markdown(full_response + "▌")
message_placeholder.markdown(full_response)

实现思路

  • 按空格切分回答,逐个词追加显示

  • 配合 光标闪烁效果,模拟流式生成体验

  • 虽然不是真正的SSE流式,但用户体验显著提升


3.5 聊天历史维护
python 复制代码
chat_history.append((prompt, result["answer"]))

ConversationalRetrievalChain 需要 chat_history 参数,格式为 List[Tuple[str, str]],分别存储用户问题和AI回答。这保证了多轮对话的上下文连贯性。


四、完整请求链路图

复制代码
用户输入 "我的快递从哪发?"
         │
         ▼
┌─────────────────────────┐
│ 1. st.chat_input 接收    │
└─────────┬───────────────┘
          ▼
┌─────────────────────────┐
│ 2. ConversationalRetrieval │
│    Chain 处理             │
│    - 合并历史上下文        │
│    - 检索FAISS向量库       │
│    - 构建最终Prompt        │
└─────────┬───────────────┘
          ▼
┌─────────────────────────┐
│ 3. Qwen3.7-max 推理      │
└─────────┬───────────────┘
          ▼
┌─────────────────────────┐
│ 4. 逐词渲染 + 会话保存    │
└─────────────────────────┘

五、生产环境优化建议

优化方向 具体措施
检索质量 增加 k 值(如5),结合 MMR 算法提升多样性
响应速度 FAISS索引升级为IVF系列(倒排索引),Embedding模型使用GPU加速
多轮对话 增加对话摘要节点,防止历史过长导致Prompt超限
并发处理 Streamlit部署时使用 --server.enableXsrfProtection false,配合Nginx负载均衡
私有化部署 全部使用Ollama本地模型(qwen2.5:7b + bge-m3),实现完全离线

六、项目演示效果

基于Streamlit构建的Web界面,用户输入"我的快递出发地是哪?预计几天到达?",系统会:

  1. 从FAISS检索相关文档块

  2. 将检索结果注入Prompt

  3. Qwen模型生成专业回答

  4. 界面逐词展示最终结果


总结(下篇 + 整体回顾)

下篇我们完成了:

  • 向量检索与上下文构建的工程实现

  • Prompt模板设计思路

  • ConversationalRetrievalChain的多轮对话能力

  • Streamlit WebUI的全流程交互设计

整体而言,这个物流RAG系统是一个标准的"离线索引 + 在线检索生成"架构,核心亮点包括:

  • 完全本地化部署(BGE-M3 + Qwen + FAISS)

  • 多轮对话支持

  • 开箱即用的WebUI

这套代码结构同样适用于金融、医疗、法律、教育等领域的私有知识问答场景,只需替换PDF文档和调整分块参数即可快速迁移。


两篇博客均提供了完整的技术剖析与工程实践参考,希望对你的RAG学习之旅有所帮助!

相关推荐
AlienZHOU2 小时前
DeepSeek Harness 插件:HTML 实时可视化编辑
前端·agent·deepseek
怕浪猫3 小时前
DeepSeek Harness 源码实战第3章:Profile / Bundle / Patch——dsh 的装配系统
openai·agent·ai编程
CTA量化套保3 小时前
近期零基础量化学习:先分阶段,再用 AI 检查缺口
人工智能·python
清水白石0084 小时前
Python 死锁排查全攻略:从线程卡死到锁依赖定位与工程化修复
linux·网络·python
Elias不吃糖5 小时前
Langfuse 入门:Trace、Prompt、Dataset、Experiment、Evaluator
前端·python·prompt·langfuse
TechWayfarer5 小时前
批量查IP归属地,在线API、脚本、离线库怎么选?三种方案实测对比
网络·python·网络协议·tcp/ip
七牛开发者6 小时前
为什么 Go 很适合 AI 辅助开发?
数据库·人工智能·python·elasticsearch·log4j
冬奇Lab6 小时前
Code Agent 解剖(04):系统提示词是怎么组装的,agent 的「人格」从哪来?
人工智能·开源·agent
河南凹凸环境艺术设计6 小时前
性价比高的民宿酒店设计企业
大数据·人工智能·python
一点一木7 小时前
Hermes Desktop 重磅更新,Bot Mode 正式上线——把你的 AI 变成一支可协作的专属团队
人工智能·agent