
2024-04-29
使用 LlamaIndex、Fireworks 和 MongoDB 简化知识工作
这是 Team CLAB 的一篇客座文章,他们在我们最近与 MongoDB 联合举办的黑客马拉松中获得了“LlamaIndex 最佳应用奖”。
想象一下:你正在深入一个编码项目,然后关于某个特定工具或库的一个关键问题出现了。你开始了令人头疼的文档查找——搜索维基、常见问题,甚至为特定工具(如 LlamaIndex、FireworksAI 或其他任何工具)启动一个单独的聊天机器人。这太令人沮丧了!🤯 我们想改变这一切。
这就是为什么 Team CLAB 构建了 LlamaWorksDB(试试看!),你友好的 AI 驱动文档向导 ✨。不再需要零散的搜索!它通过一个统一的聊天机器人界面,接入了我们黑客马拉松多个赞助商的知识,包括 LlamaIndex、Fireworks.ai 和 MongoDB。需要 MongoDB 文档中的解释?没问题!想要 Fireworks.ai 的代码示例?轻松搞定!

基础:LlamaIndex 和数据摄取
LlamaIndex 是 LlamaWorksDB 的核心与灵魂。它就像一个超万能的工具箱,用来处理各种文档!我们主要使用了他们的开源读取器直接从网站抓取信息。我们做了一个很酷的技巧,就是定制了 SimpleWebPageReader
。我们教它忽略网站导航栏,这为我们节省了大量宝贵的 tokens。💪 虽然这对于文档网站非常有效,但我们使用 LlamaIndex 的 GithubRepositoryReader
轻松地读取了每个仓库。
from llama_index.readers.web import SimpleWebPageReader
import re
class LlamaDocsPageReader(SimpleWebPageReader):
def load_data(self, urls):
documents = super().load_data(urls)
processed_documents = []
for doc in documents:
processed_doc = self.process_document(doc)
processed_documents.append(processed_doc)
return processed_documents
def process_document(self, document):
# Split the document text by "Table of Contents"
pattern = r'(?i)\n\n*table\s*of\s*contents\n\n*'
parts = re.split(pattern, document.text, maxsplit=1)
# If there is a part after "Table of Contents", use it as the document text
if len(parts) > 1:
document.text = "Table of contents".join(parts[1:])
return document
如何划分文档很有趣。LlamaIndex 提供了从基础的 SentenceSplitter
到其 SemanticNodeParser
的多种选项,后者使用 AI 对相似的想法进行分组。我们选择了后者,以获得大小合适、有意义的文本块。
最后,我们嵌入了每个“节点”,并将每个节点作为一个文档发送到 MongoDB。这效率真是高!MongoDB 存储了文本、元数据以及我们的嵌入——这非常适合我们想要构建的那种搜索。我们通过 Fireworks 使用了 Nomic 灵活的嵌入模型,这让我们能够微调维度以实现最高效率。
# FireworksEmbedding defaults to using model
embed_model = FireworksEmbedding(api_key=os.getenv('FIREWORKS_API_KEY'),
model="nomic-ai/nomic-embed-text-v1.5",
embed_batch_size=10,
dimensions=768 # can range from 64 to 768
)
# the tried and true sentence splitter
text_splitter = SentenceSplitter(chunk_size=1000, chunk_overlap=200)
# the semantic splitter uses our embedding model to group semantically related sentences together
semantic_parser = SemanticSplitterNodeParser(embed_model=embed_model)
# we set up MongoDB as our document and vector database
vector_store = MongoDBAtlasVectorSearch(
pymongo.MongoClient(os.getenv('MONGO_URI')),
db_name="fireParse",
collection_name="llamaIndexDocs",
index_name="llama_docs_index"
)
#finally we use LlamaIndex's pipeline to string this all together
pipeline = IngestionPipeline(
transformations=[
semantic_parser, #can replace with text_splitter
embed_model,
],
vector_store=vector_store,
)
设置完成后,我们就可以从 MongoDB 中的 URL 创建文档了!下面是使用三个 URL 的示例,但我们使用了数百个。
example_urls = [
"https://docs.llamaindex.org.cn/en/stable/examples/cookbooks/llama3_cookbook",
"https://docs.llamaindex.org.cn/en/stable/examples/cookbooks/anthropic_haiku/",
"https://docs.llamaindex.org.cn/en/stable/examples/vector_stores/MongoDBAtlasVectorSearch/"
]
# read in the documents and pass them through our pipeline
documents = LlamaDocsPageReader(html_to_text=True).load_data(example_urls)
pipeline.run(documents=documents, show_progress=True)
您可以在 MongoDB 中看到我们的文档包含文本、嵌入(768 维)和元数据。

用于向量搜索的 MongoDB Atlas
MongoDB Atlas 是我们存储文档文本和嵌入的首选。它具有令人难以置信的多功能性!在 Atlas 中设置向量搜索轻而易举,这使我们能够快速找到最相关的文档块。此外,LlamaIndex 的元数据解析与 Atlas 完美配合——我们可以轻松地根据文档来源或主题等信息过滤结果。
设置向量搜索: 这非常简单!我们只需要指定以下几项:
- 文档中嵌入字段的路径。
- 嵌入维度大小。
- 相似度指标(例如,余弦相似度)。
- 它是一个向量索引。
过滤能力(可选): 为了实现更精细的控制,我们可以添加我们希望用于过滤搜索结果的字段路径(例如,公司名称)。

无论您是构建复杂的 Web 应用还是快速的 Streamlit 原型,LlamaIndex ChatEngines 都能满足您的需求。它们毫不费力地管理对话历史记录,让您执行闪电般的向量搜索,并解锁一整套强大的工具。
我们直接从可靠的 MongoDB 索引构建了 ChatEngine。这种集成出奇地简单
def get_index():
logger.info("Connecting to index from MongoDB...")
store = MongoDBAtlasVectorSearch(
db_name=os.environ["MONGODB_DATABASE"],
collection_name=os.environ["MONGODB_VECTORS"],
index_name=os.environ["MONGODB_VECTOR_INDEX"],
)
index = VectorStoreIndex.from_vector_store(store)
logger.info("Finished connecting to index from MongoDB.")
return index
index = get_index()
index.as_chat_engine(
llm = Fireworks(
api_key=env_vars['FIREWORKS_API_KEY'],
model="accounts/fireworks/models/mixtral-8x22b-instruct" #Can be changed out for Llama3
)
chat_mode="best",
context_prompt=(
""" You are a software developer bot that is an expert at reading over documentation to answer questions.
Use the relevant documents for context:
{context_str}
\nInstruction: Use the previous chat history, or the context above, to interact and help the user.
"""
),
verbose=True
)
create-llama
:从想法到应用,创纪录的速度
Create-Llama 真的给我们留下了深刻的印象。通常,构建一个全栈应用需要时间,但 Create-Llama 让我们在不到 15 分钟内就运行起来了!我们所做的就是将它指向我们的向量数据库,并提供一些基本信息。说实话,它让开发变得非常愉快!这篇博客文章更详细地介绍了如何使用 create-llama。


部署:Render 和 Vercel
为了让 LlamaWorksDB 具备生产就绪性并易于访问,我们转向了 Render 和 Vercel。Render 非常适合我们的 Python FastAPI 后端,因为它专注于部署便捷性和可伸缩性。Vercel 无缝处理了我们的 Next.js 前端——我们喜欢它以开发者为中心的方法和轻松的构建过程。这两个平台都让部署变得轻而易举,让我们能够专注于编码而不是复杂的基础设施设置。
未来方向
我们在黑客马拉松中取得的成功仅仅是个开始。我们设想 LlamaWorksDB 发展成为一个开发者在技术文档中寻找答案的强大工具。以下是我们对其发展的构想:
- 增强检索: 我们很高兴能尝试 LlamaIndex 的强大功能,例如 MultiVectorSearch,以进一步改进我们的结果。集成不同的 LLM 将为 LlamaWorksDB 如何理解和交互技术内容开辟新的可能性。
- 专注于文档: 我们希望加倍努力,使 LlamaWorksDB 成为导航文档的终极工具。这意味着探索专门为理解复杂技术信息而设计的技术和工具。
LlamaWorksDB 是一个处于 Beta 阶段的开源项目,我们坚信协作的力量!如果您对 AI 驱动的文档工具有热情,我们邀请您:
- 试用: 浏览我们的 GitHub 仓库,并尝试 LlamaWorksDB!
- 贡献: 帮助我们构建新功能、测试集成并改进我们的搜索能力。
- 分享您的反馈: 告诉我们如何才能让 LlamaWorksDB 变得更好。
让我们一起彻底改变开发者与文档交互的方式!
🔗 探索我们的项目并加入创新: https://github.com/clab2024/clab/
https://clab-ui.vercel.app/ (前端) (使用免费配额,响应较慢)
https://clab.onrender.com/docs (后端)
认识 Team CLAB!🎉
- Chris Wood:冉冉升起的技术奇才,即将毕业,并从他在 Tutello 的实习中获得了宝贵的见解。
- Leo Walker:数据科学家,拥有军事退伍军人的纪律和精确性。
- Andrew Townsend:加州州立大学圣何塞分校的计算机科学毕业生,带来了新的学术视角。
- Barath Subramaniam:Adobe 产品安全 AI 和数据工程背后的战略策划者。Twitter: @baraths84
