Skip to main content

知识库更新服务

代码实践​

实现class KnowledgeBaseService​

继续在knowledge_base.py实现

# 知识库
import os
import config_data as config
import hashlib
from langchain_chroma import Chroma
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from datetime import datetime
from dotenv import load_dotenv

load_dotenv()
LLM_API_KEY = os.getenv("LLM_API_KEY")

def check_md5(md5_str: str):
"""检查传入的md5字符串是否已经处理过了
return False(md5未处理过) True(已经处理过,已有记录)
"""
if not os.path.exists(config.md5_path):
# if进入表示文件不存在,那肯定没有处理md5
open(config.md5_path, 'w', encoding='utf-8').close()
return False
else:
for line in open(config.md5_path, 'r', encoding='utf-8').readlines():
line = line.strip() # 处理字符串前后的空格和回车
if line == md5_str:
return True # 已处理过

return False



def save_md5(md5_str: str):
"""将传入的md5字符串,记录到文件内保存"""
with open(config.md5_path, 'a', encoding='utf-8') as f:
f.write(md5_str + '\n')


def get_string_md5(input_str: str, encoding='utf-8'):
"""将传入的字符串转换为md5字符串"""
# 将字符串转换为bytes字节数组
str_bytes = input_str.encode(encoding=encoding)

# 创建md5对象
md5_obj = hashlib.md5() # 得到md5对象
md5_obj.update(str_bytes) # 更新内容(传入即将要转换的字节数组)
md5_hex = md5_obj.hexdigest()

return md5_hex

class KnowledgeBaseService(object):

def __init__(self):
# 如果文件夹不存在则创建,如果存在则跳过
os.makedirs(config.persist_directory, exist_ok=True)

self.chroma = Chroma(
collection_name=config.collection_name, # 数据库的表名
embedding_function=DashScopeEmbeddings(model="text-embedding-v4",dashscope_api_key=LLM_API_KEY),
persist_directory=config.persist_directory # 数据库本地存储文件夹
) # 向量存储的实例Chroma向量库对象

self.spliter = RecursiveCharacterTextSplitter(
chunk_size=config.chunk_size, # 分割后的文本段最大长度
chunk_overlap=config.chunk_overlap, # 连续文本段之间的字符重叠数量
separators=config.separators, # 自然段落划分的符号
length_function=len, # 使用python自带的len函数做长度统计的依据
) # 文本分割器的对象

def upload_by_str(self, data: str, filename):
"""将传入的字符串,进行向量化,存储向量数据库中"""
# 先得到传入字符串的md5值
md5_hex = get_string_md5(data)

if check_md5(md5_hex):
return "[跳过]内容已经存在知识库中"

if len(data) > config.max_split_char_number:
knowledge_chunks: list[str] = self.spliter.split_text(data)
else:
knowledge_chunks = [data]

metadata = {
"source": filename,
# 2025-01-01 10:00:00
"create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"operator": "小熊",
}
self.chroma.add_texts(
# iterable -> list/tuple
knowledge_chunks,
metadatas=[metadata for _ in knowledge_chunks]
)

save_md5(md5_hex)

return "[成功]内容已经成功载入向量库"


if __name__ == '__main__':
service = KnowledgeBaseService()
res = service.upload_by_str("周杰伦1", "testfile")
print(res)

更新配置文件config_data.py​

md5_path = "./md5.txt"

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


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