加载数据,并切分

news/2025/2/4 17:55:16 标签: java, 前端, 服务器
# Step 3 . WebBaseLoader 配置为专门从 Lilian Weng 的博客文章中抓取和加载内容。它仅针对网页的相关部分(例如帖子内容、标题和标头)进行处理。

加载信息

from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader(
    web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("post-content", "post-title", "post-header")
        )
    ),
)
Step 4. 使用 RecursiveCharacterTextSplitter 将内容分割成更小的块,这有助于通过将长文本分解为可管理的大小并有一些重叠来保留上下文来管理长文本。
# LangChain 规范下统一的 Document 对象,需要封装成document对象
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
打印预览
# splits 是一个列表,其中每个元素也是一个列表,表示一个文档的分割结果
for doc_index, doc_splits in enumerate(splits):
    print(f"Document {doc_index + 1}:")  # 显示文档编号
    for split_index, split_text in enumerate(doc_splits):
        print(f"  Split {split_index + 1}: {split_text[:50]}...")  # 打印每个分段的前50个字符
    print("\n" + "-"*60 + "\n")  # 在每个文档之间加入分隔线,增加可读性

 

Step 4. 对每个块,构建Embeddings。 智谱的 GLM Embedding 在线模型:https://open.bigmodel.cn/dev/api#text_embedding

这只是一个例子,实际存储到向量数据库的时候不能直接这样用

embeddings = []

from zhipuai import ZhipuAI

#GLM 4 官方调用说明:https://open.bigmodel.cn/dev/api#vector

client = ZhipuAI(api_key="a3e6e780f4be48b3adc831f4269d999b.V3ikmBpvQ06MQPgO")

for doc_splits in splits:
    for split_type, split_content in doc_splits:
        if split_type == 'page_content' and split_content.strip():  # 确保处理的是 'page_content' 且内容不为空
            try:
                response = client.embeddings.create(
                    model="embedding-2",
                    input=split_content
                )
                if hasattr(response, 'data'):
                    embeddings.append(response.data[0].embedding)

                else:
                    print("未能成功获取嵌入向量")
            except Exception as e:
                print(f"请求失败,错误信息:{e}")

# # 打印嵌入向量
for i, embedding in enumerate(embeddings):
    print(f"Embedding {i + 1}: {embedding[:3]}...")  # 仅展示前10个值以示例

 

step 5. Chroma 使用 GLM 4 的 Embedding 模型 提供的嵌入从这些块创建向量存储,从而促进高效检索。

到现在已经转化为了向量,然后就是

存储到向量数据库中

因为向量数据库在langchain中接受到的是一个对象,而不是一个列表,所以我们要对智普的模型做一个封装,需要重写两个方法

class EmbeddingGenerator:
    def __init__(self, model_name):
        self.model_name = model_name
        self.client = ZhipuAI(api_key="a3e6e780f4be48b3adc831f4269d999b.V3ikmBpvQ06MQPgO")

    def embed_documents(self, texts):
        embeddings = []
        for text in texts:
            response = self.client.embeddings.create(model=self.model_name, input=text)
            # hasattr用来判断response是否有data属性
            if hasattr(response, 'data') and response.data:
                embeddings.append(response.data[0].embedding)
            else:
                # 如果获取嵌入失败,返回一个零向量
                embeddings.append([0] * 1024)  # 假设嵌入向量维度为 1024
        return embeddings


    def embed_query(self, query):
        # 使用相同的处理逻辑,只是这次只为单个查询处理
        response = self.client.embeddings.create(model=self.model_name, input=query)
        if hasattr(response, 'data') and response.data:
            return response.data[0].embedding
        return [0] * 1024  # 如果获取嵌入失败,返回零向量


embedding_generator = EmbeddingGenerator(model_name="embedding-2")

 创建向量数据库

# 拿到文本列表,和上面的打印出来遍历是一样的
texts = [content for document in splits for split_type, content in document if split_type == 'page_content']


# Step 6. 创建 Chroma VectorStore, 并存入向量。
# 源码:https://api.python.langchain.com/en/latest/_modules/langchain_chroma/vectorstores.html#Chroma
chroma_store = Chroma(
    collection_name="example_collection",
    embedding_function=embedding_generator,  # 使用定义的嵌入生成器实例
    create_collection_if_not_exists=True
)


# 添加文本到 Chroma VectorStore
IDs = chroma_store.add_texts(texts=texts)

 这个hub.pull 如果没翻墙的话可能有问题

# 这里从 'hub.pull' 是从某处获取提示的方法,就相当于拉去了一个提示末班
prompt = hub.pull("rlm/rag-prompt")

# prompt = """You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.
# Question: {question} 
# Context: {context} 
# Answer:
# """
# ChatPromptTemplate
# 

# 自定义函数 format_docs 用于适当地格式化这些片段。
def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)


# vectorstore 被转换为一个检索器,能够根据查询获取最相关的文本片段。

# Step 7. RAG 链集成了检索、提示工程(通过 hub.pull )和初始化语言模型 ( llm ) 来处理查询并生成响应,最后使用 StrOutputParser 。
"""
其过程如下:
1. 查询输入:字符串“什么是任务分解?”作为输入传递给 rag_chain 。
2. 上下文检索:链的 retriever 组件链接到矢量存储,激活以从索引的博客内容中查找并获取最相关的文本片段。这些片段是根据与问题的语义相似性与查询最匹配的片段。
3. 格式化检索的内容:然后, format_docs 函数获取这些检索到的文档,并将它们格式化为单个字符串,每个文档内容由双换行符分隔。此格式化字符串提供了一个连贯的上下文,其中封装了回答查询所需的所有相关信息。
4. 生成答案:此格式化上下文字符串与查询一起被输入到 glm-4 模型中。该模型使用提供的上下文和查询的细节,根据检索到的信息生成上下文相关且准确的响应。
5. 输出解析:最后, ChatZhipu 模型生成的响应由 StrOutputParser 进行解析,将模型的输出转换为干净的、用户可读的格式。


RunnableParallel 可以并发执行多个任务,而 RunnablePassthrough 用于需要顺序执行而不需修改的任务。
"""

#
rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | chat
    | StrOutputParser()
)


# Step 8. 进行提问
"""
1. 查询处理:该命令接受查询“什么是任务分解?”并将其传递给 retriever 组件。检索器本质上是系统中的搜索功能,设置为在预先索引的数据集中查找信息 - 这里是根据博客内容创建的矢量存储。
2. 语义搜索:检索器使用向量存储中存储的文本片段的嵌入(向量表示)来执行语义搜索。它将查询的向量表示与存储的片段的向量进行比较,以识别在语义上与查询最相似的片段。
3. 检索相关文本片段:根据相似度分数,检索器从博客中选择并返回与查询最匹配的文本片段。这些片段包含被认为与回答任务分解问题最相关的信息。
"""

rag_res = rag_chain.invoke("What is Task Decomposition?")
print(rag_res)


# Step 9. 此命令指示 vectorstore 删除其保存的整个数据集合。这里的集合是指所有文档(文本片段)及其相应的已被索引并存储在向量存储中的向量表示的集合。
chroma_store.delete_collection()

 


http://www.niftyadmin.cn/n/5841716.html

相关文章

深入解析 Chrome 浏览器的多进程架构:标签页是进程还是线程?(中英双语)

深入解析 Chrome 浏览器的多进程架构:标签页是进程还是线程? 1. 引言 Google Chrome 作为全球最流行的浏览器之一,以其稳定性、安全性和多任务处理能力而闻名。而其高效的表现,很大程度上归功于其独特的多进程架构(M…

【含文档+PPT+源码】基于小程序的智能停车管理系统设计与开发

项目介绍 本课程演示的是一款基于小程序的智能停车管理系统设计与开发,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 3…

[c语言日寄]C语言类型转换规则详解

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…

Altium Designer绘制原理图时画斜线的方法

第一步:检查设置是否正确 打开preferences->PCB Editor ->Interactive Routing->Interactive Routing Options->Restrict TO 90/45去掉勾选项,点击OK即可。如下图所示: 然后在划线时,按下shift空格就能够切换划线…

pandas中的apply方法使用

apply 用于对 DataFrame 或 Series 中的数据进行逐行或逐列的操作。它可以接受一个函数(通常是 lambda 函数或自定义函数),并将该函数应用到每一行或每一列上。apply语法: DataFrame.apply(func, axis0, rawFalse, result_typeNo…

Java 大视界 -- Java 大数据在智能电网中的应用与发展趋势(71)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…

深入剖析 Bitmap 数据结构:原理、应用与优化策略

深入理解 Bitmap 数据结构 一、引言 在计算机科学领域,数据的高效存储和快速处理一直是核心问题。随着数据量的不断增长,如何用最少的空间和最快的速度来表示和操作数据变得至关重要。Bitmap(位图)作为一种简洁而强大的数据结构…

golang命令大全8--跨平台构建

Go 语言以其强大的跨平台能力而著称,其内置的工具链使得构建适配不同平台的二进制可执行文件变得非常简单。在本章中,我们将详细讲解跨平台构建的基本概念、环境变量的配置方法、如何构建适配不同平台的二进制文件,以及相关的注意事项。 1、…