零基础也能搞定!使用 Langchain + Ollama 构建本地知识库系统详解

在这里插入图片描述


🌟 零基础也能搞定!使用 Langchain + Ollama 构建本地知识库系统详解

🎯 应用场景

痛点场景
某制造企业仓库管理员每天需要处理上百次物料查询请求,面对散落在多个Excel中的库存数据,每次查询都需要10分钟以上,且容易出错…
适合对象
希望在局域网/本地环境下部署智能问答系统的人群(比如公司内部知识管理、物料库存查询等应用场景)

解决方案
通过本地化部署的智能问答系统,实现:

  • ✅ 自然语言提问秒级响应
  • ✅ 数据100%本地存储
  • ✅ 无需GPU等高端硬件
  • ✅ 支持离线环境运行

本地大模型的优势
很多人以为做 AI 一定得上云,其实不是!在很多业务里,本地部署才是王道,比如:

  • 不想数据上传云端,怕泄密 ✅
  • 网络条件有限或敏感场景 ✅
  • 小规模团队不想付费 API,节省成本 ✅

于是,我们有了主角 —— Langchain + Ollama + Chroma 向量数据库。


🛠️ 技术栈全景图

组件作用选型理由
LangChainAI应用开发框架标准化流程,快速搭建AI链
Ollama本地大模型引擎支持多种开源模型,CPU即可运行
Chroma向量数据库轻量级,支持持久化存储
BGE-M3文本嵌入模型中文表现优异,支持多语言

🧩 核心模块拆解

模块1:数据预处理

你的数据长这样吗?

  ["A001", "螺钉", "M5*20", "12345678", "PLM001", 100, "仓库A"],
  原始数据为JSON格式
  ...
]

这是典型的结构化物料数据。我们希望把它变成 LLM 能理解的文本。

来看下关键函数:


```python
class Chatollama_base3:
    def create_documents_from_txt(self, file_path):
        """
        将原始物料数据转化为LangChain文档对象
        :param file_path: 数据文件路径
        :return: Document对象列表
        
        处理逻辑:
        1. 读取JSON格式的物料数据
        2. 结构化拼接字段(编码+名称+规格+...)
        3. 生成带元数据的文档对象
        """
        # 示例数据转换
        ["M001", "螺钉", "M6", "TW001", 1000]"编码:M001, 名称:螺钉, 规格:M6, 库存:1000"
        documents = []
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
                data_list = json.loads(content)
                for item in data_list:
                    if isinstance(item, list) and len(item) >= 2:
                        material_name = item[0]
                        page_content = (
                            f"编码:{item[0]},"
                            f"名称:{item[1]},"
                            f"规格:{item[2] if len(item) > 2 else ''},"
                            f"图文号:{item[3] if len(item) > 3 else ''},"
                            f"PLM码:{item[4] if len(item) > 4 else ''},"
                            f"数量:{item[5] if len(item) > 5 else ''},"
                            f"仓库:{item[-1] if item else ''}"
                        )
                        metadata = {"source": material_name}
                        doc_id = str(uuid.uuid4())  # 生成唯一的 UUID 作为 id
                        document = Document(page_content=page_content, metadata=metadata, id=doc_id)
                        documents.append(document)
                    else:
                        print(f"跳过无效数据项: {item}")
        except FileNotFoundError:
            print(f"错误: 文件未找到: {file_path}")
        except json.JSONDecodeError:
            print(f"错误: 文件内容不是有效的 JSON 格式。请检查文件格式是否正确。")
        return documents

技术细节

  • 使用UUID生成唯一文档ID,避免重复
  • 元数据记录物料编码,便于溯源
  • 结构化拼接提升检索准确率

每条物料信息都被转换成一段规范化的文本,形如:

Document(id='0ef27170-6d73-4908-8984-6eae11af413e', metadata={'source': '01070692'}, page_content='编码:01070692,名称:内六角圆柱头螺钉,规格:M20*60 8.8镀锌 GB/T70.1,图文号:GB/T70.1,PLM码:00D01M20x60G031,数量:14.0,仓库:紧固件仓')

这一步就是知识的原始表达转换


模块2:向量化引擎

    def load_embedding_model(self):
        embeddings = OllamaEmbeddings(
            model="bge-m3",
            # base_url="http://localhost:11434"  # 本地模型服务
        )
        return embeddings

为什么选择BGE-M3

  1. 专为中文优化的嵌入模型
  2. 支持多向量混合检索
  3. 在MTEB中文榜排名前列

模块3:向量数据库

    def store_chroma(self, docs, persist_directory="chroma3"):
        db = Chroma.from_documents(
            documents=docs,
            embedding=self.embeddings,
            persist_directory=persist_directory
        )
        return db

Chroma特性

  • 数据持久化存储(重启不丢失)
  • 支持相似度阈值过滤
  • 自动管理向量索引

模块4:问答系统核心

    def get_qa(self):
        QA_CHAIN_PROMPT = PromptTemplate.from_template("""
        Human:
        你是一位专业的物料管家,请根据上下文回答:
        {context}

        要求:
        1. 以表格呈现关键字段
        2. 添加库存状态分析
        3. 给出管理建议

        问题:{question}
        Assistant:
        """)
        
        retriever = db.as_retriever(
            search_type="similarity_score_threshold",
            search_kwargs={'score_threshold': 0.45}
        )
        
        return RetrievalQA.from_chain_type(
            llm=self.llm,
            retriever=retriever,
            chain_type_kwargs={"prompt": QA_CHAIN_PROMPT}
        )

为什么我们要写提示词?

  • 强调 AI 的角色(物料管理助手)
  • 限定回答格式(表格 + 数据解读 + 提醒)
  • 避免模型瞎猜,提升可控性

📌 建议:

写 Prompt 时,不要只告诉模型你是谁,还要告诉它怎么做(输出格式、用不用单位、是否给总结建议)

Prompt设计精髓

  • 角色定位 → 专业物料管家
  • 格式规范 → 强制表格输出
  • 业务规则 → 库存分析+建议
  • 安全边际 → 限定回答范围

🧱 系统架构

[JSON/TXT 数据文件]
       ↓
[切片 + 嵌入 Embedding]
       ↓
[Chroma 向量数据库存储]
       ↓
[LangChain 检索 QA链 + Prompt模板]
       ↓
[本地 LLM 响应问答]

在这里插入图片描述
在这里插入图片描述

🚀 完整工作流程

  1. 数据初始化阶段
JSON原始数据
数据转换
Document对象
向量化处理
Chroma存储
  1. 查询响应阶段
用户提问
语义解析
向量检索
上下文组装
LLM生成回答

💻 实战演示

场景:查询特定物料库存

# 初始化系统
manager = Chatollama_base3()

# 自然语言提问
question = "请列出A仓库所有规格为M6的螺钉类物料,并按库存量降序排列"

# 获取智能回复
result = manager.query_material(question)

输出结果示例

【智能回复】
根据A仓库库存数据,规格为M6的螺钉物料如下:

| 物料编码 | 名称       | 规格 | 库存量 | 最低库存 |
|----------|------------|------|--------|----------|
| M006     | 内六角螺钉 | M6   | 1500   | 500      |
| M012     | 平头螺钉   | M6   | 800    | 300      |

库存分析:
1. 内六角螺钉库存充足(300%安全库存)
2. 平头螺钉接近安全库存线,建议15日内补货

【数据溯源】
- 物料编码:M006
- 物料编码:M012

🛠 调优技巧

检索优化

retriever = db.as_retriever(
    search_kwargs={
        'k': 5,                 # 返回Top5结果
        'score_threshold': 0.4, # 相似度阈值
        'filter': {'仓库': 'A仓'} # 元数据过滤
    }
)

模型参数配置

ChatOllama(
    model="qwen2.5:latest",
    temperature=0.1,      # 降低随机性
    num_predict=1024,     # 响应长度限制
    top_p=0.9             # 聚焦高概率token
)

⚠️ 常见问题排查

  1. 中文乱码问题

    • 确保所有文件操作指定编码:open(..., encoding='utf-8')
    • 检查系统默认编码:import sys; print(sys.getdefaultencoding())
  2. Ollama服务异常

    # 启动服务命令
    ollama serve
    
    # 常用模型列表
    ollama list
    
    # 安装中文模型
    ollama pull qwen:7b
    
  3. 向量检索不准确

    • 检查字段拼接逻辑是否丢失关键信息
    • 调整相似度阈值(0.3-0.6范围调试)
    • 尝试混合检索模式(MMR)

📈 拓展应用

本方案稍作修改即可应用于:

  1. 企业内部知识库(HR政策、技术文档等)
  2. 生产质检标准查询系统
  3. 客户服务智能问答
  4. 个人知识管理(论文/笔记检索)

结语:让AI在本地生根发芽

通过本文,我们完成了从原始数据到智能问答系统的蜕变。这个本地化方案不仅解决了数据隐私的担忧,更展现了开源生态的强大能力。当最后一个代码块运行成功时,您已经为传统仓库管理装上了AI引擎。

技术发展的真谛,不在于追求最前沿,而在于用合适的技术解决实际问题。 希望这个方案能成为您AI应用开发的起跑线,期待看到更多精彩的本地化AI实践!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值