想象一下,编写一个可以理解、协助甚至生成代码的软件,就像经验丰富的开发人员所做的那样。
使用LangChain就可以实现这一点。利用 VectorStore、Conversational RetrieverChain 和 LLM等先进模型,LangChain将我们的代码理解和生成提升到了一个新的水平。
在本指南中,我们将对 Twitter 的推荐算法进行逆向工程,以更好地理解代码库并提供见解以制作更好的内容。我们将使用 OpenAI 的嵌入技术和一个名为Activeloop 的工具来使代码易于理解,并使用DeepInfra上托管的名为Dolly 的LLM 与代码进行对话。
当我们完成后,我们将能够通过要求人工智能为我们提供最紧迫问题的答案来简化理解算法所需的艰巨工作,而不是花费数周时间自己进行筛选。让我们开始。
LangChain 代码理解的概念纲要
LangChain是一个非常有用的工具,可以分析GitHub上的代码存储库。它汇集了三个重要部分:VectorStores、Conversational RetrieverChain 和 LLM(大语言模型),以帮助您理解代码、在上下文中回答有关代码的问题,甚至在 GitHub 存储库中生成新代码。
Conversational RetrieverChain 是一个帮助从 VectorStore 查找和检索有用信息的系统。它使用上下文感知过滤和排名等智能技术来找出哪些代码片段和信息与您的特定问题或查询最相关。它的独特之处在于它考虑了对话的历史和提出问题的上下文。这意味着它可以为您提供专门满足您需求的高质量且相关的结果。简而言之,这就像拥有一个智能助手,可以理解您问题的背景,并根据该背景为您提供最佳答案。
现在,让我们看看 LangChain 的工作流程,看看它在高层次上是如何工作的:
索引代码库
第一步是克隆要分析的目标存储库。加载存储库中的所有文件,将它们分成更小的块,然后启动索引过程。如果您已有索引数据集,甚至可以跳过此步骤。
嵌入和代码存储
为了使代码片段更容易理解,LangChain 采用了代码感知嵌入模型。该模型有助于捕获代码的本质,并将嵌入的代码片段存储在 VectorStore 中,以便将来可以轻松访问它们。
简单来说,LangChain 使用一种称为代码感知嵌入的特殊技术来使代码片段更易于理解。它有一个模型可以分析代码并捕获其重要特征。然后,它将这些分析的代码片段存储在 VectorStore 中,这就像一个易于访问的存储位置。这样,代码片段就可以组织起来,并在您将来有疑问或问题时可以快速检索。
查询理解
这就是你的LLM 发挥作用的地方。您可以使用databricks/dolly-v2-12b等模型来处理您的查询。该模型用于分析您的查询并通过考虑上下文并提取重要信息来理解查询背后的含义。通过这样做,该模型可以帮助 LangChain 准确地解释您的查询,并为您提供精确且相关的结果。
构造检索器:
一旦您的问题或查询明确,对话检索链就会发挥作用。它会遍历存储代码片段的 VectorStore,并找到与您的查询最相关的代码片段。该搜索过程非常灵活,可以根据您的要求进行定制。您可以调整设置并应用特定于您的需求的过滤器,确保您获得最准确、最有用的查询结果。
建立对话链
一旦设置了检索器,就可以构建对话链了。此步骤涉及调整检索器的设置以更好地满足您的需求,并应用可能需要的任何其他过滤器。通过这样做,您可以缩小搜索范围,并确保收到最精确、准确且相关的查询结果。从本质上讲,它允许您微调检索过程以获得对您最有用的信息。
提出问题:现在是令人兴奋的部分!
您可以使用 ConversationalRetrievalChain 询问有关代码库的问题。它将为您生成全面且上下文相关的答案。您的LLM 作为对话链的一部分,会考虑检索到的代码片段和对话历史记录,为您提供详细且准确的答案。
通过遵循此工作流程,您将能够有效地使用 LangChain 来更深入地了解代码,获得问题的上下文感知答案,甚至在 GitHub 存储库中生成代码片段。现在,让我们一步步看看它的实际效果。
分步指南
让我们深入了解实际的实现。
获取钥匙
首先,您需要在各自的网站上注册并获取 Activeloop、DeepInfra 和 OpenAI 的 API 密钥。
设置Indexer.py文件
创建一个 Python 文件,例如indexer.py,您将在其中索引数据。导入必要的模块并将 API 密钥设置为环境变量:
import os
from langchain.document_loaders import TextLoader
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import DeepLake
os.environ['OPENAI_API_KEY'] = 'YOUR KEY HERE'
os.environ['ACTIVELOOP_TOKEN'] = 'YOUR KEY HERE'
embeddings = OpenAIEmbeddings(disallowed_special=())
用简单的英语来说,嵌入是捕获不同文本字符串的含义和相关性的文本表示。它们是数值向量或数字列表,用于测量不同文本输入之间的相似性或距离。
嵌入通常用于各种任务,例如搜索、聚类、推荐、异常检测、多样性测量和分类。在搜索中,嵌入有助于对搜索结果与查询的相关性进行排名。在聚类中,嵌入将相似的文本字符串分组在一起。
推荐利用嵌入来建议具有相关文本字符串的项目。异常检测使用嵌入来识别相关性很小的异常值。多样性测量涉及分析文本字符串之间相似性的分布。分类利用嵌入将文本字符串分配给最相似的标签。
两个嵌入向量之间的距离指示相应文本字符串的相关或相似程度。较小的距离表明相关性高,而较大的距离表明相关性低。
克隆目标存储库并为其建立索引
接下来,我们将克隆 Twitter 算法存储库,加载、拆分和索引文档。您可以从此链接克隆该算法。
root_dir = './the-algorithm'
docs = []
for dirpath, dirnames, filenames in os.walk(root_dir):
for file in filenames:
try:
loader = TextLoader(os.path.join(dirpath, file), encoding='utf-8')
docs.extend(loader.load_and_split())
except Exception as e:
pass
此代码遍历目录及其子目录 (os.walk(root_dir))。对于遇到的每个文件(文件名),它尝试执行以下步骤:
-
它创建一个 TextLoader 对象,指定当前正在处理的文件的路径
(os.path.join(dirpath, file))
并将编码设置为 UTF-8。 -
然后,它调用
load_and_split()
TextLoader 对象的方法,该方法可能会读取文件的内容,执行某些处理或拆分操作,并返回结果文本数据。 -
然后使用该方法将获得的文本数据添加到名为 docs 的现有列表中
extend()
。 -
如果在此过程中发生任何异常,则会被 try-except 块捕获并简单地忽略 (
pass\
)。
基本上,此代码片段递归地遍历目录,从文件中加载和分割文本数据,并将结果数据添加到名为 docs 的列表中。
嵌入代码片段
接下来,我们使用 OpenAI 嵌入来嵌入代码片段。然后这些嵌入被存储在 VectorStore 中,这将使我们能够执行有效的相似性搜索:
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(docs)
username = "mikelabs" # replace with your username from app.activeloop.ai
db = DeepLake(dataset_path=f"hub://{username}/twitter-algorithm", embedding_function=embeddings, public=True) #dataset would be publicly available
db.add_documents(texts)print(“done”)
此代码导入该类CharacterTextSplitter
并初始化其实例,块大小为 1000 个字符且无重叠。然后,它使用 split_documents 方法将提供的文档分割成更小的文本块,并将它们存储在 texts 变量中。
接下来,它设置用户名(您用于注册 Activeloop 的用户名!)并创建一个名为 db 的 DeepLake 实例,其数据集路径指向指定用户名下托管在“ app.activeloop.ai ”上的公开可用数据集。embedding_function 处理所需的嵌入。
最后,它使用 add_documents 方法将文本添加到数据库中,大概是出于存储或进一步处理的目的。
运行该文件,然后等待几分钟(它可能会挂起一段时间……通常不超过 5 分钟)。然后,进行下一步。
利用 dolly-v2-12b 处理和理解用户查询
现在,我们设置另一个 Python 文件Question.py来使用dolly-v2-12b ( DeepInfra平台中提供的语言模型)来处理和理解用户查询。
构建检索器
我们使用之前创建的 VectorStore 构造一个检索器。
db = DeepLake(dataset_path="hub://mikelabs/twitter-algorithm", read_only=True, embedding_function=embeddings) #use your username
retriever = db.as_retriever()
retriever.search_kwargs['distance_metric'] = 'cos'
retriever.search_kwargs['fetch_k'] = 100
retriever.search_kwargs['maximal_marginal_relevance'] = True
retriever.search_kwargs['k'] = 10
以下是该代码正在执行的操作的详细说明:
该代码初始化一个名为 db 的 DeepLake 对象。它从指定为“hub://mikelabs/twitter-algorithm”的路径读取数据集。值得注意的是,您需要将“mikelabs”替换为您自己的用户名!
然后使用 as_retriever() 方法将 db 对象转换为检索器。这一步允许我们对 VectorStore 中存储的数据执行搜索操作。
通过修改字典来定制几个搜索选项:retriever.search_kwargs
设置distance_metric
为“cos”,表示将使用余弦相似度来衡量文本输入之间的相似度。想象一下,您有两个表示不同文本片段的向量,例如句子或文档。余弦相似度是衡量这两段文本相似程度或相关程度的一种方法。
为了计算余弦相似度,我们查看两个向量之间的角度。如果向量指向相同方向或彼此非常接近,则余弦相似度将接近 1。这意味着文本片段彼此非常相似。
另一方面,如果向量指向相反方向或相距较远,则余弦相似度将接近 -1。这表明文本片段非常不同或不相似。
余弦相似度为 0 意味着向量彼此垂直或成 90 度角。在这种情况下,文本片段之间不存在相似性。
在上面的代码中,余弦相似度被用作比较文本输入之间相似度的度量。它有助于确定两个文本片段的相关程度。通过使用余弦相似度,代码可以排名并检索与给定查询最相似的顶级匹配。
该fetch_k
参数设置为100,意味着检索器将根据余弦相似度检索前100个最接近的匹配项。
设置maximal_marginal_relevance
为True
,表明检索器将优先考虑不同的结果,而不是返回高度相似的匹配。
该k
参数设置为10,表示检索器每次查询将返回10个结果。
构建对话链
我们使用 ConversationalRetrievalChain 来链接检索器和语言模型。这使我们的系统能够处理用户查询并生成上下文感知响应:
model = DeepInfra(model_id="databricks/dolly-v2-12b")
qa = ConversationalRetrievalChain.from_llm(model,retriever=retriever)
ConversationalRetrievalChain 充当检索器和语言模型之间的连接。此连接允许系统处理用户查询并生成了解上下文的响应。
问问题
我们现在可以询问有关 Twitter 算法代码库的问题。ConversationalRetrievalChain 提供的答案是上下文感知的,并且直接基于代码库。
questions = ["What does favCountParams do?", ...]
chat_history = []
for question in questions:
result = qa({"question": question, "chat_history": chat_history})
chat_history.append((question, result['answer']))
print(f"-> **Question**: {question} \n")
print(f"**Answer**: {result['answer']} \n")
以下是一些示例问题,摘自 LangChain 文档:
questions = [
"What does favCountParams do?",
"is it Likes + Bookmarks, or not clear from the code?",
"What are the major negative modifiers that lower your linear ranking parameters?",
"How do you get assigned to SimClusters?",
"What is needed to migrate from one SimClusters to another SimClusters?",
"How much do I get boosted within my cluster?",
"How does Heavy ranker work. what are it’s main inputs?",
"How can one influence Heavy ranker?",
"why threads and long tweets do so well on the platform?",
"Are thread and long tweet creators building a following that reacts to only threads?",
"Do you need to follow different strategies to get most followers vs to get most likes and bookmarks per tweet?",
"Content meta data and how it impacts virality (e.g. ALT in images).",
"What are some unexpected fingerprints for spam factors?",
"Is there any difference between company verified checkmarks and blue verified individual checkmarks?",
]
这是我收到的示例答案:
**Question**: What does favCountParams do?
**Answer**: FavCountParams helps count your favorite videos in a way that is friendlier to the video hosting service (i.e., TikTok). For example, it skips counting duplicates and doesn't show recommendations that may not be relevant to you.
资源
以下是一些可能对您有用的其他资源:
-
Activeloop 文档
-
AIModels.fyi LangChain 指南
-
OpenAI 嵌入文档
结论
在本指南中,我们探索了使用 LangChain 对 Twitter 的推荐算法进行逆向工程。通过利用人工智能功能,我们节省了宝贵的时间和精力,用自动查询响应取代了手动代码检查。
LangChain 是一个强大的工具,彻底改变了代码理解和生成。通过使用 VectorStores、Conversational RetrieverChain 等高级模型以及 DeepInfra 等服务上托管的 LLM,LangChain 使开发人员能够高效分析代码存储库、提供上下文感知答案并生成新代码。
LangChain的工作流程包括索引代码库、嵌入代码片段、使用语言模型处理用户查询以及利用Conversational RetrieverChain检索相关代码片段。通过定制检索器并构建对话链,开发人员可以微调检索过程以获得精确的结果。
通过遵循分步指南,您可以利用 LangChain 来增强代码理解能力、获得上下文感知答案,甚至在 GitHub 存储库中生成代码片段。LangChain为生产力和理解开辟了新的可能性。你将用它构建什么?