当前位置: 首页 > article >正文

本地大模型编程实战(03)语义检索(2)

文章目录

    • 准备
    • 按批次嵌入
    • 加载csv文件,分割文档并嵌入
    • 测试嵌入效果
    • 总结
    • 代码


上一篇文章: 本地大模型编程实战(02)语义检索(1) 详细介绍了如何使用 langchain 实现语义检索,为了演示方便,使用的是 langchain 提供的内存数据库。
在实际工作中,更多的使用场景是将矢量化的数据物理存储下来,在查询的时候在从存储介质中读取矢量数据进行查询,不会每次使用矢量数据时都必须想做嵌入。

本文描述了如何使用 Chroma 对csv数据进行矢量化,并且将矢量存储在硬盘中,未来查询矢量数据时,直接从硬盘中读取矢量数据进行查询。
另外,如果数据量大一些,矢量化数据是很花时间的,我们将使用进度条显示嵌入csv的进度。

准备

在正式开始撸代码之前,需要准备一下编程环境。

  1. 计算机
    本文涉及的所有代码可以在没有显存的环境中执行。 我使用的机器配置为:

    • CPU: Intel i5-8400 2.80GHz
    • 内存: 16GB
  2. Visual Studio Code 和 venv
    这是很受欢迎的开发工具,相关文章的代码可以在 Visual Studio Code 中开发和调试。 我们用 pythonvenv 创建虚拟环境, 详见:
    在Visual Studio Code中配置venv。

  3. Ollama
    Ollama 平台上部署本地大模型非常方便,基于此平台,我们可以让 langchain 使用 llama3.1qwen2.5 等各种本地大模型。详见:
    在langchian中使用本地部署的llama3.1大模型 。

  4. C++编译器
    安装 Chroma 时需要C++编译器的支持。我是通过安装 Visual Studio .Net Community 2022 来安装C++编译器的。
    点击这里下载Visual Studio .Net Community

按批次嵌入

一般来说,将文本矢量化很消耗资源,所以耗时较长,我们定义一个按照批次嵌入文档的方法,使用 tqdm 显示进度:

def embed_documents_in_batches(documents, batch_size=10):
    """
    按批次嵌入,可以显示进度。
    vectordb会自动持久化存储在磁盘。
    """
    vectordb = Chroma(persist_directory=persist_directory,embedding_function=embedding)
    for i in tqdm(range(0, len(documents), batch_size), desc="嵌入进度"):
        batch = documents[i:i + batch_size]
        # 从文本块生成嵌入,并将嵌入存储在本地磁盘。
        vectordb.add_documents(batch)

加载csv文件,分割文档并嵌入

这里调用之前的按批次嵌入方法,完成嵌入:

def create():
    """对文本矢量化并存储在本地磁盘"""

    data_file = os.path.join(current_dir,'assert/law.csv')

    loader = CSVLoader(file_path=data_file,
                       csv_args={"delimiter": "#"},
                       autodetect_encoding=True)
    docs = loader.load()
    #print(f'加载文件成功,第一个文件内容:{docs[0]}')

    # 用于将长文本拆分成较小的段,便于嵌入和大模型处理。
    # 每个文本块的最大长度是1000个字符,拆分的文本块之间重叠部分为200。
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    texts = text_splitter.split_documents(docs)   

    # 耗时较长,需要耐心等候...
    embed_documents_in_batches(texts,batch_size=3)

在执行的过程中,我们会在 VS Code 的 Terminal 中直观的看到进入:
矢量化嵌入过程

测试嵌入效果

此时在assert文件夹中已经生成了一个 db_law 文件夹,这里面存储的就是矢量化的数据。

def search(query):
    """查询矢量数据库"""
    vector_store = Chroma(persist_directory=persist_directory,embedding_function=embedding)
    results = vector_store.similarity_search_with_score(query,k=2)
    return results

我们调用此方法做一下测试:

results = search("恶意商标申请")
print(f'search results:\n{results}')
search results:
[(Document(id='3ef03cff-e0b1-416c-93f6-1ff281af323c', metadata={'row': 1, 'source': 'E:\\project\\my_opensource\\programming-with-local-large-language-model-gitee\\server\\services\\practice\\assert/law.csv'}, page_content='第六章  法律责任    第三十三条  管理专利工作的部门认定专利侵权行为成立,作出处理决定的,应当责令侵权人立即停止侵权行为,采取下列制止侵权行为的措施:    (一)侵权人制造专利产品
的,责令其立即停止制造行为,销毁制造侵权产品的专用设备、模具,并且不得销售、使用尚未售出的侵权产品或者以任何其他形式将其投放市场;侵权产品难以保存的,责令侵权人销毁该产品。    (二)侵权人使用专利方法
的,责令其立即停止使用行为,销毁实施专利方法的专用设备、模具,并且不得销售、使用尚未售出的依照专利方法所直接获得的产品或者以任何其他形式将其投放市场;侵权产品难以保存的,责令侵权人销毁该产品。    (三
)侵权人销售专利产品或者依照专利方法直接获得产品的,责令其立即停止销售行为,并且不得使用尚未售出的侵权产品或者以任何其他形式将其投放市场;尚未售出的侵权产品难以保存的,责令侵权人销毁该产品。    (四)
侵权人许诺销售专利产品或者依照专利方法直接获得产品的,责令其立即停止许诺销售行为,消除影响,并且不得进行任何实际销售行为。    (五)侵权人进口专利产品或者依照专利方法直接获得产品的,责令侵权人立即停止
进口行为;侵权产品已经入境的,不得销售、使用该侵权产品或者以任何其他形式将其投放市场;侵权产品难以保存的,责令侵权人销毁该产品;侵权产品尚未入境的,可以将处理决定通知有关海关。    (六)停止侵权行为的
其他必要措施。    第三十四条  管理专利工作的部门作出认定专利侵权行为成立的处理决定后,被请求人向人民法院提起行政诉讼的,在诉讼期间不停止决定的执行。    侵权人对管理专利工作的部门作出的认定侵权行为成立
的处理决定期满不起诉又不停止侵权行为的,管理专利工作的部门可以申请人民法院强制执行。    第三十五条  假冒他人专利,涉嫌触犯刑法第二百一十六条的,由管理专利工作的部门移送司法机关依法追究刑事责任。    伪
造或者变造专利证书,涉嫌触犯刑法第二百八十条规定的,由管理专利工作的部门移送司法机关追究刑事责任。    第三十六条  管理专利工作的部门认定假冒他人专利、冒充专利行为成立的,应当责令行为人采取下列改正措施
:'), 0.9691819652571181)]

总结

通过以上步骤,我们实现了将csv数据矢量化并存储在本地,后面我们可以基于此继续开发 RAG 系统和 Agent

代码

本文涉及的所有代码以及相关资源都已经共享,参见:

  • github
  • gitee

🪐祝好运🪐


http://www.kler.cn/a/520881.html

相关文章:

  • unity实现回旋镖函数
  • mysql DDL可重入讨论
  • 立创开发板入门ESP32C3第八课 修改AI大模型接口为deepseek3接口
  • 14-6-3C++STL的list
  • Oracle 创建用户和表空间
  • C#面试常考随笔6:ArrayList和 List的主要区别?
  • 【Linux课程学习】:锁封装(Mutex)线程封装(Thread),this指针
  • 壁纸设计过程中如何增加氛围感
  • Linux 内核进程调度
  • 3.Flink中重要API的使用
  • 《Kotlin核心编程》中篇
  • 能说说MyBatis的工作原理吗?
  • 牛客周赛77B:JAVA
  • redis如何备份文件?
  • 重构进行时:一秒告别 !=null 判空
  • 【记录】日常|从零散记录到博客之星Top300的成长之路
  • 从CRUD到高级功能:EF Core在.NET Core中全面应用(四)
  • Ansible自动化运维实战--通过role远程部署nginx并配置(8/8)
  • Vue 3 中的计算属性:只读与可读写的使用与案例
  • 图论汇总1
  • 项目概述与规划 (I)
  • 【算法】BFS
  • vue3和vue2的区别有哪些差异点
  • 【JavaEE进阶】图书管理系统 - 壹
  • LabVIEW 保存文件 生产者/消费者设计
  • Golang Gin系列-7:认证和授权