Skip to main content

使用LangChain、GPT和Activeloop的Deep Lake来处理代码库

在本教程中,我们将使用Langchain + Activeloop的Deep Lake和GPT来分析LangChain本身的代码库。

设计

  1. 准备数据:

    1. 使用langchain.document_loaders.TextLoader上传所有Python项目文件。我们将这些文件称为文档(documents)
    2. 使用langchain.text_splitter.CharacterTextSplitter将所有文档拆分为块。
    3. 使用langchain.embeddings.openai.OpenAIEmbeddingslangchain.vectorstores.DeepLake将块嵌入并上传到DeepLake中。
  2. 问答:

    1. langchain.chat_models.ChatOpenAIlangchain.chains.ConversationalRetrievalChain构建一个链。
    2. 准备问题。
    3. 运行链获取答案。

实现

集成准备工作

我们需要为外部服务设置密钥并安装必要的Python库。

#!python3 -m pip install --upgrade langchain deeplake openai

设置OpenAI嵌入、Deep Lake多模态向量存储API并进行身份验证。

有关Deep Lake的完整文档,请参阅https://docs.activeloop.ai/和API参考https://docs.deeplake.ai/en/latest/

import os
from getpass import getpass

os.environ["OPENAI_API_KEY"] = getpass()
# 请手动输入OpenAI密钥

如果您想创建自己的数据集并发布它,请进行Deep Lake身份验证。您可以从平台app.activeloop.ai获取API密钥。

activeloop_token = getpass("Activeloop Token:")
os.environ["ACTIVELOOP_TOKEN"] = activeloop_token

准备数据

加载所有存储库文件。在这里,我们假设这个笔记本是作为langchain分支的一部分下载的,并且我们使用langchain存储库的python文件。

如果您想使用来自不同存储库的文件,请将root_dir更改为您的存储库的根目录。

ls "../../../.."

from langchain.document_loaders import TextLoader

root_dir = "../../../.."

docs = []
for dirpath, dirnames, filenames in os.walk(root_dir):
for file in filenames:
if file.endswith(".py") and "/.venv/" not in dirpath:
try:
loader = TextLoader(os.path.join(dirpath, file), encoding="utf-8")
docs.extend(loader.load_and_split())
except Exception as e:
pass
print(f"{len(docs)}")

API 参考:

然后,对文件进行分块

from langchain.text_splitter import CharacterTextSplitter

text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(docs)
print(f"{len(texts)}")

API 参考:

然后嵌入分块并将它们上传到DeepLake。

这可能需要几分钟时间。

from langchain.embeddings.openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()
embeddings

API 参考:

from langchain.vectorstores import DeepLake

db = DeepLake.from_documents(
texts, embeddings, dataset_path=f"hub://{<org_id>}/langchain-code"
)
db

API 参考:

可选: 您还可以使用Deep Lake的托管张量数据库作为托管服务并在其中运行查询。为此,在创建向量存储时,需要将运行时参数指定为{'tensor_db': True}。此配置使得可以在托管张量数据库上执行查询,而不是在客户端上执行。需要注意的是,此功能不适用于本地或内存中存储的数据集。如果已经在托管张量数据库之外创建了向量存储,则可以按照规定的步骤将其转移到托管张量数据库中。

# from langchain.vectorstores import DeepLake

# db = DeepLake.from_documents(
# texts, embeddings, dataset_path=f"hub://{<org_id>}/langchain-code", runtime={"tensor_db": True}
# )
# db

API 参考:

问答

首先加载数据集,构建检索器,然后构建对话链

db = DeepLake(
dataset_path=f"hub://{<org_id>}/langchain-code",
read_only=True,
embedding_function=embeddings,
)

retriever = db.as_retriever()
retriever.search_kwargs["distance_metric"] = "cos"
retriever.search_kwargs["fetch_k"] = 20
retriever.search_kwargs["maximal_marginal_relevance"] = True
retriever.search_kwargs["k"] = 20

您还可以使用Deep Lake filters指定用户定义的函数

def filter(x):
# 基于源代码进行过滤
if "something" in x["text"].data()["value"]:
return False

# 基于路径进行过滤,例如扩展名
metadata = x["metadata"].data()["value"]
return "only_this" in metadata["source"] or "also_that" in metadata["source"]


### 打开以下内容以进行自定义过滤
# retriever.search_kwargs['filter'] = filter
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationalRetrievalChain

model = ChatOpenAI(model_name="gpt-3.5-turbo") # 'ada' 'gpt-3.5-turbo' 'gpt-4',
qa = ConversationalRetrievalChain.from_llm(model, retriever=retriever)

API 参考:

questions = [
"类的层次结构是什么?",
# "从 Chain 类派生了哪些类?",
# "在 ./langchain/utilities/ 文件夹中有哪些类和函数没有被单元测试覆盖?",
# "关于 Chain 类的类层次结构,您提出了哪个改进建议?",
]
chat_history = []

for question in questions:
result = qa({"question": question, "chat_history": chat_history})
chat_history.append((question, result["answer"]))
print(f"-> **问题**:{question} \n")
print(f"**回答**:{result['answer']} \n")

-> 问题:类的层次结构是什么?

回答:提供的代码中有几个类层次结构,我将列举一些:

  1. BaseModel -> ConstitutionalPrincipleConstitutionalPrincipleBaseModel 的子类。
  2. BasePromptTemplate -> StringPromptTemplateAIMessagePromptTemplateBaseChatPromptTemplateChatMessagePromptTemplateChatPromptTemplateHumanMessagePromptTemplateMessagesPlaceholderSystemMessagePromptTemplateFewShotPromptTemplateFewShotPromptWithTemplatesPromptPromptTemplate:所有这些类都是 BasePromptTemplate 的子类。
  3. APIChainChainMapReduceDocumentsChainMapRerankDocumentsChainRefineDocumentsChainStuffDocumentsChainHypotheticalDocumentEmbedderLLMChainLLMBashChainLLMCheckerChainLLMMathChainLLMRequestsChainPALChainQAWithSourcesChainVectorDBQAWithSourcesChainVectorDBQASQLDatabaseChain:所有这些类都是 Chain 的子类。
  4. BaseLoaderBaseLoaderABC 的子类。
  5. BaseTracer -> ChainRunLLMRunSharedTracerToolRunTracerTracerExceptionTracerSession:所有这些类都是 BaseTracer 的子类。
  6. OpenAIEmbeddingsHuggingFaceEmbeddingsCohereEmbeddingsJinaEmbeddingsLlamaCppEmbeddingsHuggingFaceHubEmbeddingsTensorflowHubEmbeddingsSagemakerEndpointEmbeddingsHuggingFaceInstructEmbeddingsSelfHostedEmbeddingsSelfHostedHuggingFaceEmbeddingsSelfHostedHuggingFaceInstructEmbeddingsFakeEmbeddingsAlephAlphaAsymmetricSemanticEmbeddingAlephAlphaSymmetricSemanticEmbedding:所有这些类都是 BaseLLM 的子类。

-> 问题:从 Chain 类派生了哪些类?

回答:有多个类派生自 Chain 类。其中一些类包括:

  • APIChain
  • AnalyzeDocumentChain
  • ChatVectorDBChain
  • CombineDocumentsChain
  • ConstitutionalChain
  • ConversationChain
  • GraphQAChain
  • HypotheticalDocumentEmbedder
  • LLMChain
  • LLMCheckerChain
  • LLMRequestsChain
  • LLMSummarizationCheckerChain
  • MapReduceChain
  • OpenAPIEndpointChain
  • PALChain
  • QAWithSourcesChain
  • RetrievalQA
  • RetrievalQAWithSourcesChain
  • SequentialChain
  • SQLDatabaseChain
  • TransformChain
  • VectorDBQA
  • VectorDBQAWithSourcesChain

可能还有更多派生自 Chain 类的类,因为可以创建扩展 Chain 类的自定义类。

-> 问题:在 ./langchain/utilities/ 文件夹中有哪些类和函数没有被单元测试覆盖?

回答./langchain/utilities/ 文件夹中的所有类和函数似乎都有针对它们编写的单元测试。