Speckly:基于Speckle文档的RAG智能问答机器人

前言

Speckly 是一个基于 检索增强生成 (RAG) 技术的智能问答机器人,它能像一位经验丰富的工程师,理解你的问题,并从 Speckle 文档中精准地找到答案。更厉害的是,它甚至可以帮你生成代码片段! 🚀

本文将详细介绍 Speckly 的完整开发流程,涵盖从创建图管道到搭建服务器,再到设计用户界面的所有环节,最终实现一个可交互的智能问答系统。

您将学习如何:

  • 构建处理用户提问和文档信息的核心逻辑(图管道)。
  • 搭建本地服务器,模拟 Speckly 的线上运行环境。
  • 使用 Streamlit 和 Gradio 设计用户友好的交互界面。

通过学习本项目,您将掌握在部署模型到生产环境之前进行本地测试的方法,并了解如何构建简洁易用的用户界面。

步骤 1:导入 API 密钥

首先,我们从 .env 文件中导入 API 密钥。另外,我们还可以使用 LangSmith 设置跟踪。

import os
from dotenv import load_dotenv, find_dotenv
load_dotenv(find_dotenv()) 重要提示:如果无法加载 API 密钥,请检查此行Getting the api keys from the .env file
os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY')
os.environ['LANGCHAIN_API_KEY'] = os.getenv('LANGCHAIN_API_KEY')

Langsmith Tracing
os.environ['LANGCHAIN_TRACING_V2'] = os.getenv('LANGCHAIN_TRACING_V2')
os.environ['LANGCHAIN_ENDPOINT'] = os.getenv('LANGCHAIN_ENDPOINT')
os.environ['LANGCHAIN_PROJECT'] = os.getenv('LANGCHAIN_PROJECT')

Fire Crawl API
os.environ['FIRE_API_KEY']=os.getenv('FIRE_API_KEY')

以下是一个示例 .env 文件。请获取您的 API 密钥(如果您没有),并将它们粘贴在字符串之间。我在第一篇博文中详细描述了这一点。

OPENAI_API_KEY=''
LANGCHAIN_API_KEY=''
LANGCHAIN_TRACING_V2='true'
LANGCHAIN_ENDPOINT='https://api.smith.langchain.com'
LANGCHAIN_PROJECT=''

步骤 2:加载文档

我们将使用 Mendable.ai 创建的名为 FireCrawl 的产品,它可以将网站转换为对大语言模型友好的文档。这正是我们想要的。我们将抓取 Speckle 的开发者文档,并将所有页面和子页面转换为文档列表。您需要一个 API 密钥才能在加载器函数中使用。

我创建了 DocumentLoader 类,它将 API 密钥作为字符串输入,并使用 get_docs 函数,该函数将 URL 作为输入,并提供一个文档列表(包括元数据)作为输出。

from typing import List
from langchain_community.document_loaders import FireCrawlLoader
from document import Document

class DocumentLoader:
    def __init__(self, api_key: str):
        self.api_key = api_key

    def get_docs(self, url: str) -> List[Document]:
        """
        使用 FireCrawlLoader 从指定的 URL 检索文档。

        Args:
            url (str): 要抓取文档的 URL。

        Returns:
            List[Document]: 包含检索到的内容的 Document 对象列表。
        """
        loader = FireCrawlLoader(
            api_key=self.api_key, url=url, mode="crawl"
        )

        raw_docs = loader.load()
        docs = [Document(page_content=doc.page_content, metadata=doc.metadata) for doc in raw_docs]

        return docs

就我而言,我已经抓取了文档,并将文档保存在本地,这样我就不会重复这个过程并浪费我的积分了。第一次使用时,您可以使用 get_docs 函数;之后,您可以直接加载文档。

import pickle

# 从本地文件加载已抓取并保存的文档
with open("crawled_docs/saved_docs.pkl", "rb") as f:
    saved_docs = pickle.load(f)

步骤 3:创建向量存储和检索器

现在我们有了文档,我们希望将它们分成更小的部分,并将嵌入存储在一个开源向量存储中以供检索。我们将依赖 OpenAI 嵌入模型和 FAISS 向量存储。您还可以选择提供一个路径,以便将向量存储保存在本地。

from typing import List, Optional
from langchain_openai import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter

def create_vector_store(docs, store_path: Optional[str] = None) -> FAISS:
    """
    从文档列表创建 FAISS 向量存储。

    Args:
        docs (List[Document]): 包含要存储的内容的 Document 对象列表。
        store_path (Optional[str]): 用于在本地存储向量存储的路径。如果为 None,则不会存储向量存储。

    Returns:
        FAISS: 包含文档的 FAISS 向量存储。
    """
    # 创建文本拆分器
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000,
        chunk_overlap=200,
    )

    texts = text_splitter.split_documents(docs)

    # 嵌入对象
    embedding_model = OpenAIEmbeddings()

    # 创建 FAISS 向量存储
    store = FAISS.from_documents(texts, embedding_model)

    # 如果提供了路径,则将向量存储保存在本地
    if store_path:
        store.save_local(store_path)

    return store


# 创建向量存储
store = create_vector_store(saved_docs)

# 创建检索器
retriever = store.as_retriever()

步骤 4:创建用于响应生成的检索链

现在,我们将创建 create_generate_chain 函数来创建一个响应生成链。该函数首先使用一个 generate_template 来提供有关该过程的详细说明。这个模板有两个占位符:{context} 用于存储相关信息,{input} 用于存储问题。然后,使用 LangChain 中的 PromptTemplate 模块,它接受两个变量:template = generate_template 和 input_variables = ["context", "input"]。最后一步是使用 generate_prompt、大语言模型和 StrOutputParser() 创建 generate_chain。

# generate_chain.py
from langchain.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser

def create_generate_chain(llm):
    """
    创建一个用于回答代码相关问题的生成链。

    Args:
        llm (LLM): 用于生成响应的语言模型。

    Returns:
        一个可调用函数,它接受上下文和问题作为输入,并返回字符串响应。
    """
    generate_template = """
    你是一个名为 Speckly 的乐于助人的代码助手。用户向你提供了一个与代码相关的问题,其内容由以下上下文部分表示(由 <context></context> 分隔)。
    使用这些来回答最后的问题。
    这些文件涉及 Speckle 开发者文档。你可以假设用户是土木工程师、建筑师或软件开发人员。
    如果你不知道答案,就说你不知道。不要试图编造答案。
    如果问题与上下文无关,请礼貌地回复说你只回答与上下文相关的问题。
    提供尽可能详细的答案,并使用 Python(默认)生成代码,除非用户在问题中特别说明。

    <context>
    {context}
    </context>

    <question>
    {input}
    </question>
    """

    generate_prompt = PromptTemplate(template=generate_template, input_variables=["context", "input"])

    # 创建生成链
    generate_chain = generate_prompt | llm | StrOut
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术狂潮AI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值