黑马大模型RAG与Agent智能体实战教程LangChain提示词——35、RAG项目(服装商品智能客服)——知识库更新服务(md5)

教程:https://www.bilibili.com/video/BV1yjz5BLEoY

代码:https://github.com/shangxiang0907/HeiMa-AI-LLM-RAG-Agent-Dev

云开发平台:https://hzh.sealos.run

文章目录

  • RAG项目-04、RAG项目-知识库更新服务
    • 代码截图
    • [→提示词:帮我根据图中内容,完善目录@rag-clothing-customer-service 中代码,图中内容仅供参考,你要适当修改](#→提示词:帮我根据图中内容,完善目录@rag-clothing-customer-service 中代码,图中内容仅供参考,你要适当修改)
    • ←AI回复
      • [1. **完善 `config_data.py`**](#1. 完善 config_data.py)
      • [2. **完善 `knowledge_base.py`**](#2. 完善 knowledge_base.py)
      • [3. **更新 `app_file_uploader.py`**](#3. 更新 app_file_uploader.py)
    • 代码
    • [→问AI: "根据配置的最大字符数决定是否分割文本"这段代码是否多余了?](#→问AI: “根据配置的最大字符数决定是否分割文本”这段代码是否多余了?)
    • ←AI回复
    • [→问AI:@rag-clothing-customer-service/knowledge_base.py:22-27 @bash (6-104) 是不是没帮我加载环境变量,参照这个目录里文件弄下@AI_LLM_RAG_Agent_Dev](#→问AI:@rag-clothing-customer-service/knowledge_base.py:22-27 @bash (6-104) 是不是没帮我加载环境变量,参照这个目录里文件弄下@AI_LLM_RAG_Agent_Dev)
    • ←AI回复
    • 总结

RAG项目-04、RAG项目-知识库更新服务

代码截图




→提示词:帮我根据图中内容,完善目录@rag-clothing-customer-service 中代码,图中内容仅供参考,你要适当修改




←AI回复

查看现有代码,根据图片内容完善代码。

4 tools called

搜索代码库中的相关依赖和导入信息:

2 tools called

根据图片内容完善代码。先完善 config_data.py,再完善 knowledge_base.py

2 tools called

完善 knowledge_base.py

4 tools called

更新 app_file_uploader.py,集成 KnowledgeBaseService

3 tools called

检查代码是否有错误:

2 tools called

完成所有任务。查看最终文件:

2 tools called

已根据图片内容完善代码。主要修改如下:

1. 完善 config_data.py

  • 添加 ChromaDB 配置(collection_namepersist_directory
  • 添加文本分割器配置(chunk_sizechunk_overlapseparators
  • 添加 max_split_char_number 配置项

2. 完善 knowledge_base.py

  • __init__ 方法
    • 自动创建持久化目录
    • 初始化 Chroma 向量数据库(使用 DashScopeEmbeddings)
    • 初始化 RecursiveCharacterTextSplitter 文本分割器
  • upload_by_str 方法
    • 实现 MD5 校验,避免重复上传
    • 根据配置的最大字符数决定是否分割文本
    • 构建包含文件名、创建时间和操作员的元数据
    • 将文本块上传到向量数据库
    • 保存 MD5 值并返回成功消息

3. 更新 app_file_uploader.py

  • 集成 KnowledgeBaseService
  • 添加文件内容预览功能
  • 添加"上传到知识库"按钮和处理状态提示

代码已通过语法检查,无错误。现在可以通过 Streamlit 应用上传文本文件到向量知识库了。

代码

config_data.py

py 复制代码
md5_path = "./md5.text"

# Chroma
collection_name = "rag"
persist_directory = "./chroma_db"

# splitter
chunk_size = 1000
chunk_overlap = 100
separators = ["\n\n", "\n", ".", "!", "?", ". ", "!", "?", " ", ""]

knowledge_base.py

py 复制代码
"""
知识库服务类
用于管理文件上传、MD5校验和向量数据库存储
"""
import hashlib
import os
from datetime import datetime

from langchain_chroma import Chroma
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

import config_data as config


class KnowledgeBaseService(object):
    def __init__(self):
        # 如果文件夹不存在则创建,如果存在则跳过
        os.makedirs(config.persist_directory, exist_ok=True)
        
        # 向量存储的实例 Chroma向量库对象
        self.chroma = Chroma(
            collection_name=config.collection_name,  # 数据库的表名
            embedding_function=DashScopeEmbeddings(model="text-embedding-v4"),
            persist_directory=config.persist_directory,  # 数据库本地存储文件夹
        )
        
        # 文本分割器的对象
        self.spliter = RecursiveCharacterTextSplitter(
            chunk_size=config.chunk_size,  # 分割后的文本段最大长度
            chunk_overlap=config.chunk_overlap,  # 连续文本段之间的字符重叠数量
            separators=config.separators,  # 自然段落划分的符号
            length_function=len,  # 使用Python自带的len函数做长度统计的依据
        )

    def check_md5(self, md5_str):
        """检查传入的md5字符串是否已经被处理过了"""
        if not os.path.exists(config.md5_path):
            return False
        
        with open(config.md5_path, 'r', encoding='utf-8') as f:
            existing_md5s = f.read().splitlines()
        
        return md5_str in existing_md5s

    def save_md5(self, md5_str):
        """将传入的md5字符串,记录到文件内保存"""
        # 确保目录存在
        os.makedirs(os.path.dirname(config.md5_path) if os.path.dirname(config.md5_path) else '.', exist_ok=True)
        
        with open(config.md5_path, 'a', encoding='utf-8') as f:
            f.write(md5_str + '\n')

    def get_string_md5(self, str_data):
        """将传入的字符串转换为md5字符串"""
        md5_hash = hashlib.md5()
        md5_hash.update(str_data.encode('utf-8'))
        return md5_hash.hexdigest()

    def upload_by_str(self, data: str, filename):
        """将传入的字符串,进行向量化,存入向量数据库中"""
        # 先得到传入字符串的md5值
        md5_hex = self.get_string_md5(data)
        if self.check_md5(md5_hex):
            return "[跳过]内容已经存在知识库中"
        
        # 使用文本分割器分割文本(分割器会根据 chunk_size 自动决定是否分割)
        knowledge_chunks: list[str] = self.spliter.split_text(data)
        
        # 构建元数据
        metadata = {
            "source": filename,
            "create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "operator": "小曹",
        }
        
        # 内容就加载到向量库中了
        # iterable -> list \ tuple
        self.chroma.add_texts(
            knowledge_chunks,
            metadatas=[metadata for _ in knowledge_chunks],
        )
        
        # 保存MD5值
        self.save_md5(md5_hex)
        return "[成功]内容已经成功载入向量库"

app_file_uploader.py

py 复制代码
"""
基于Streamlit完成WEB网页上传服务
pip install streamlit
"""

import streamlit as st
from knowledge_base import KnowledgeBaseService

# 添加网页标题
st.title("知识库更新服务")

# 初始化知识库服务
if 'kb_service' not in st.session_state:
    st.session_state.kb_service = KnowledgeBaseService()

# file_uploader
uploader_file = st.file_uploader(
    label="请上传TXT文件",
    type=['txt'],
    accept_multiple_files=False,
    # False表示仅接受一个文件的上传
)

if uploader_file is not None:
    # 提取文件的信息
    file_name = uploader_file.name
    file_type = uploader_file.type
    file_size = uploader_file.size / 1024  # KB
    
    st.subheader(f"文件名: {file_name}")
    st.write(f"格式: {file_type} | 大小: {file_size:.2f} KB")
    
    # get_value -> bytes -> decode('utf-8')
    text = uploader_file.getvalue().decode("utf-8")
    
    # 显示文件内容预览
    with st.expander("文件内容预览"):
        st.text(text[:1000] + "..." if len(text) > 1000 else text)
    
    # 上传按钮
    if st.button("上传到知识库"):
        with st.spinner("正在处理文件..."):
            result = st.session_state.kb_service.upload_by_str(text, file_name)
            st.success(result)

→问AI: "根据配置的最大字符数决定是否分割文本"这段代码是否多余了?

←AI回复

分析这段代码的必要性:

2 tools called

分析这段代码的必要性:

1 tool called

分析这段代码的逻辑问题:

1 tool called

这段代码多余且存在逻辑问题。分析如下:

当前配置:

  • chunk_size = 1000(文本块最大长度)
  • max_split_char_number = 10000(最大分割字符数)

问题:

  1. RecursiveCharacterTextSplitter 会自动处理:文本长度 ≤ chunk_size 时不分割,> chunk_size 时按配置分割。
  2. 当前逻辑:len(data) > 10000 才分割,否则不分割。这会导致 1000-10000 之间的文本不分割,产生过大的块,违背 chunk_size 的设计。

建议:移除这段判断,直接使用分割器,让它根据 chunk_size 自动决定是否分割。

1 tool called

检查是否还有其他地方使用 max_split_char_number

2 tools called

已移除多余代码。max_split_char_number 配置项现在未被使用,可考虑删除。保留它也不影响功能。

→问AI:@rag-clothing-customer-service/knowledge_base.py:22-27 @bash (6-104) 是不是没帮我加载环境变量,参照这个目录里文件弄下@AI_LLM_RAG_Agent_Dev

←AI回复

检查相关文件,查看环境变量的加载方式。

3 tools called

查看一个具体示例,了解环境变量的加载方式:

2 tools called

knowledge_base.py 中添加环境变量加载逻辑,参照 AI_LLM_RAG_Agent_Dev 目录中的做法。

1 tool called

knowledge_base.py 中添加环境变量加载逻辑:

2 tools called

检查是否有 lint 错误:

2 tools called

已修复环境变量加载问题。修改如下:

  1. 导入 dotenv :添加 from dotenv import load_dotenv
  2. __init__ 方法中加载环境变量
    • 调用 load_dotenv() 加载 .env 文件
    • 从环境变量读取 DASHSCOPE_API_KEYAPI_KEY(兼容两种命名)
    • 如果未找到,抛出清晰的错误提示
    • 将 API key 设置到 os.environ["DASHSCOPE_API_KEY"],供 DashScopeEmbeddings 使用

修改后的代码与 AI_LLM_RAG_Agent_Dev 目录下的示例保持一致。现在 DashScopeEmbeddings 可以正确读取 API key。

请确保:

  • 项目根目录或 rag-clothing-customer-service 目录下有 .env 文件
  • .env 文件中包含 DASHSCOPE_API_KEY=你的密钥API_KEY=你的密钥

重新运行应用应可正常工作。

总结

这段代码确实多余,原因:

  1. RecursiveCharacterTextSplitter 会根据 chunk_size 自动决定是否分割:

    • 文本 ≤ 1000 字符:不分割,返回单个块
    • 文本 > 1000 字符:按 chunk_sizeseparators 分割
  2. 原逻辑会导致 1000-10000 字符的文本不分割,产生过大的块,违背 chunk_size 的设计。

  3. 直接使用分割器更简洁,逻辑由分割器统一处理。

代码已简化,现在直接使用分割器处理所有文本,它会根据 chunk_size 自动决定是否分割。

相关推荐
南_山无梅落5 小时前
从LangChain到LangGraph:构建智能Agent的实战指南(一)——AI应用的“工具箱“
人工智能·langchain
lhxcc_fly5 小时前
0.LangChain--大模型篇
langchain·大模型·llm·openai·deepseek
coding者在努力5 小时前
LangChain之Prompt核心组件.2026年新版讲解,超详细
android·langchain·prompt
不会敲代码16 小时前
用 LangChain 把大模型串起来:一个前端开发者的 AI 入门笔记
langchain·llm·aigc
无聊的小坏坏6 小时前
精准控制:提示词工程与结构化输出
langchain·提示词·大模型应用
ZWZhangYu17 小时前
【LangChain专栏】LangChain 调用Ollama本地大模型
langchain
njsgcs18 小时前
langchain+vlm示例
windows·python·langchain
勇气要爆发18 小时前
LangGraph 实战:10分钟打造带“人工审批”的智能体流水线 (Python + LangChain)
开发语言·python·langchain
Dontla1 天前
黑马大模型RAG与Agent智能体实战教程LangChain提示词——32、RAG项目(服装商品智能客服)——案例介绍(离线流程、在线流程)
langchain