如何使用LangChain、RStudio和足够的Python生成人工智能( 三 )

可以在R和Python中检查结果:
c_split_docs <- py$c_split_docslength(c_split_docs)该代码生成695个块,最大为1000 。
成本是多少?
在进一步讨论之前,如果想知道为所有这些块生成嵌入是否会非常昂贵 。将从默认的306项递归拆分开始 。可以计算R对象上这些块中的字符总数:
purrr::map_int(my_split_docs, get_characters) |> sum()答案是513506 。保守地估计每个令牌有两个字符,其结果大约是20万个 。
如果想更准确,TheOpenAIR R包有一个count_tokens()函数(确保安装该函数和purrr以使用下面的R代码):
purrr::map_int(my_split_docs,~ TheOpenAIR::count_tokens(.x$page_content)) |>sum ()【如何使用LangChain、RStudio和足够的Python生成人工智能】该代码显示了126,343个令牌 。
那要花费多少成本?OpenAI用于生成嵌入的模型是ada-2 。现在ada-2的1000个令牌价格为0.0001美元,126,000代币的价格约为1.3美分 。这些费用在预算之内 。
步骤4:生成嵌入LangChain有预制的组件,可以从文本块创建嵌入并存储它们 。对于存储,将使用LangChain中最简单的选项之一:Chroma,这是一个可以在本地使用的开源嵌入数据库 。
首先,将用R代码为docs目录创建一个子目录,因为建议在Chroma目录中除了数据库之外什么都不要 。这是R代码:
if(!dir.exists("docs/chroma_db")) { dir.create("docs/chromaba_db")}下面是使用LangChain的OpenAIEmbeddings生成嵌入的一些Python代码 。这是目前默认为OpenAI的ada-2模型,因此不需要指定它 。LangChain通过其嵌入类支持许多其他LLM , 包括Hugging Face Hub、Cohere、Llama cpp和Spacy 。
下面的Python代码稍微修改了一下DeepLearning.AI的LangChain与其数据聊天在线教程 。
from langchain.embeddings.openai import OpenAIEmbeddingsembed_object = OpenAIEmbeddings()from langchain.vectorstores import Chromachroma_store_directory = "docs/chroma_db"vectordb = Chroma.from_documents( documents=my_split_docs, embedding=embed_object, persist_directory=chroma_store_directory)# Check how many embeddings were createdprint(vectordb._collection.count())注意_collection.count()中的下划线!
可以看到有306个嵌入 , 与ggplot2文本块的数量相同 。
Python新手的另一个注意事项:缩进在Python中很重要 。确保非缩进行之前没有空格,并且缩进行都使用相同数量的缩进空格 。
在这个系统上,这段代码似乎将数据保存到了磁盘上 。但是 , 教程指出用户应该运行以下Python代码来保存嵌入以供以后使用 。这样做的原因是不想在文档更改之前重新生成嵌入 。
vectordb.persist()现在,已经完成了为查询准备文档的工作 。将创建qanda.py这个新文件 , 来使用创建的矢量嵌入 。
步骤5:嵌入用户查询和查找文档块现在是时候提出一个问题,为该问题生成嵌入,并根据块的嵌入检索与该问题最相关的文档 。
由于vectordb对象的内置方法 , LangChain提供了在一行代码中完成所有这些工作的几种方法 。它的similarity_search()方法直接计算向量相似度,并返回最相似的文本块 。
不过,还有其他几种方法可以做到这一点,包括max_marginal_relevance e_search() 。这背后的想法是,不一定想要三个几乎相同的文本块 。如果文本中有一点多样性,以获得额外的有用信息 , 也许最终会得到一个更丰富的回答 。因此,max_marginal_relevance e_search()检索的相关文本比实际计划传递给LLM以获取答案的文本多一些(用户决定多出多少) 。然后,结合一定程度的多样性 , 它选择最后的文本片段 。
用户可以指定希望similarity_search()返回多少相关文本块及其k参数 。对于max_marginal_relevance(),用户指定最初应该使用fetch_k检索多少块,以及希望LLM查找其使用k的答案的最终文本片段 。
如果文档没有更改 , 不想运行文档准备文件,将首先在新的qanda.py文件中加载必要的包和环境变量(即OpenAI API密钥),就像在使用doc_prepare .py之前所做的那样 。然后 , 将加载chromadb矢量数据库:
# If running from RStudio, remember to first run in R:# library(reticulate)# use_virtualenv("the_virtual_environment_you_set_up")# api_key_py <- r_to_py(Sys.getenv("OPENAI_API_KEY"))import openaiopenai.api_key = r.api_key_for_py from langchain.embeddings.openai import OpenAIEmbeddingsembed_object = OpenAIEmbeddings()from langchain.vectorstores import Chromachroma_store_directory = "docs/chroma_db"vectordb = Chroma(persist_directory=chroma_store_directory,embedding_functinotallow=embed_object)


推荐阅读