探索跨语言的 RAG 应用:与 Mishnah 对话
为拉比文本构建跨语言 RAG 系统
机器人正在学习《米什纳》。来源:DALL-E-3。
介绍:
我很高兴在这篇文章中分享我构建一个独特的检索增强生成 (RAG) 应用程序以与拉比文本交互的历程。MishnahBot 旨在为学者和日常用户提供一种直观的方式来交互式查询和探索 Mishnah¹。它可以帮助解决诸如快速找到相关源文本或总结有关宗教法的复杂辩论、提取底线等问题。
几年前我就有这个想法,但我觉得技术还不够成熟。现在,随着大型语言模型和 RAG 功能的进步,这已经相当简单了。
这就是我们的最终产品的样子,你可以在这里尝试一下:
MishnahBot网站。图片由作者提供。
那么 RAG 系统为什么受到如此热捧呢?
RAG 应用正受到广泛关注,因为它可以提高准确性并利用大型语言模型 (LLM) 中可用的推理能力。想象一下,您可以与您的图书馆、同一制造商的汽车手册集合或您的税务文件聊天。您可以提出问题,并获得基于丰富专业知识的答案。
典型 RAG 系统架构图。来源:[Amazon AWS 文档](https://aws.amazon.com/what-is/retrieval-augmented-generation/#:~:text=Retrieval-Augmented Generation (RAG),sources before generating a response.)。
RAG 与增加上下文长度的优缺点
在改进语言模型交互方面出现了两种新兴趋势:检索增强生成(RAG)和增加上下文长度,可能通过允许非常长的文档作为附件来实现。
RAG 系统的一个关键优势是成本效益。使用 RAG,您可以处理大型上下文,而不会大幅增加查询成本,这可能会变得昂贵。此外,RAG 更加模块化,允许您使用不同的知识库和 LLM 提供商进行即插即用。另一方面,直接在语言模型中增加上下文长度是一项令人兴奋的发展,可以在一次交互中处理更长的文本。
设置
对于这个项目,我使用 AWS SageMaker 作为我的开发环境,使用 AWS Bedrock 访问各种 LLM,并使用 LangChain 框架管理管道。这两种 AWS 服务都非常方便用户使用,并且只对使用的资源收费,因此我非常鼓励您亲自尝试一下。对于 Bedrock,您需要请求访问 Llama 3 70b Instruct 和 Claude Sonnet。
让我们打开一个新的 Jupyter 笔记本,并安装我们将要使用的软件包:
!pip 安装 chromadb tqdm langchain chromadb 句子转换器
数据集
该项目的数据集是《米什纳》,这是一部古老的拉比文本,是犹太传统的核心。我之所以选择这部文本,是因为它与我息息相关,而且由于它是一个小众主题,因此对语言模型也提出了挑战。该数据集来自Sefaria-Export存储库²,这是一个拉比文本宝库,其中的英语翻译与希伯来语原文保持一致。这种一致性有助于在我们的 RAG 应用程序的不同步骤中切换语言。
注意:此处应用的相同流程可应用于您选择的任何其他文本集合。此示例还演示了如何跨不同语言使用 RAG 技术,如本例中的希伯来语所示。
让我们开始吧
1.加载数据集
首先,我们需要下载相关数据。由于完整存储库相当大,我们将使用 git sparse-checkout。打开终端窗口并运行以下命令。
git init sefaria-json
cd sefaria-json
git sparse-checkout init --cone
git sparse-checkout set json
git remote add origin https://github.com/Sefaria/Sefaria-Export.git
git pull origin master
树 Mishna/ | 少
瞧!我们现在有了所需的数据文件:
Mishnah
│ │ │ └── Seder Kodashim
│ │ │ │ └── Mishnah Arakhin
│ │ │ │ │
│ └── 英文 │ │ │ └── 合并.json │ │ └──
希伯来语│ │ └──合并.json │ │ │ └── Mishnah Bekhorot │ │ │ │ │ │ └── 英文│ │ │ └── 合并.json │ │ └── 希伯来语│ │ └── 合并.json │ │ │ └── Mishnah Chullin │ │ │ │ │ │ └── 英文│ │ │ └── 合并.json │ │ └── 希伯来语│ │ └── 合并.json
现在让我们在 Jupyter 笔记本环境中加载文档:
导入操作系统
导入JSON
导入pandas作为pd
从tqdm导入tqdm
# 函数将所有文档加载到带进度条的 DataFrame 中
def load_documents ( base_path ):
data = []
for seder in tqdm(os.listdir(base_path), desc= "Loading Seders" ):
seder_path = os.path.join(base_path, seder)
if os.path.isdir(seder_path):
for tractate in tqdm(os.listdir(seder_path), desc= f"Loading Tractates in {seder} " , leave= False ):
tractate_path = os.path.join(seder_path, tractate)
if os.path.isdir(tractate_path):
english_file = os.path.join(tractate_path, "English" , "merged.json" )
hebrew_file = os.path.join(tractate_path, "Hebrew" , "merged.json" )
如果os.path.exists(english_file)和os.path.exists(hebrew_file):
使用 open (english_file, 'r' , encoding= 'utf-8' )作为ef,打开(hebrew_file, 'r' , encoding= 'utf-8' )作为hf:
english_data = json.load(ef)
hebrew_data = json.load(hf)
对于chapter_index, (english_chapter, hebrew_chapter)在 枚举中(zip (english_data[ 'text' ], hebrew_data[ 'text' ])):
对于mishnah_index, (english_paragraph, hebrew_paragraph)在 枚举中(zip (english_chapter, hebrew_chapter)):
data.append({
“seder”:seder,
“tractate”:tractate,
“chapter”:chapter_index + 1,
“mishnah”:mishnah_index + 1,
“english”:english_paragraph,
“hebrew”:hebrew_paragraph
})
返回pd。DataFrame(data)
# 加载所有文档
base_path = "Mishnah"
df = load_documents(base_path)
# 将 DataFrame 保存到文件中以供将来参考
df.to_csv(os.path.join(base_path, "mishnah_metadata.csv" ), index= False )
print ( "数据集已成功加载到 DataFrame 并保存到文件中。" )
看一下数据:
df.shape
(4192,7)打印(df.head()[[ “tractate”,“mishnah”,“english” ] ])tractate mishnah english 0 Mishnah Arakhin 1 <b>每个人都</b>发誓<b>评估</b>...... 1 Mishnah Arakhin 2 关于<b>非犹太人,拉比梅尔(Rabbi Meir)说:<... 2 Mishnah Arakhin 3 <b>一个垂死的人和一个被带到... 3 Mishnah Arakhin 4 对于 怀孕<b>的妇女... 4 Mishnah Arakhin 1 <b> 不能为低于...的估价收取费用
看起来不错,我们可以进入矢量数据库阶段。
2.矢量化并存储在 ChromaDB 中
接下来,我们将文本向量化并将其存储在本地 ChromaDB 中。简而言之,这个想法是将文本表示为密集向量(数字数组),这样语义相似的文本在向量空间中就会“接近”。这项技术使我们能够根据查询检索相关段落。
我们选择了一种轻量级矢量化模型,它all-MiniLM-L6-v2
可以在 CPU 上高效运行。该模型在性能和资源效率之间实现了良好的平衡,非常适合我们的应用程序。虽然像 OpenAI 这样的先进模型text-embedding-3-large
可以提供卓越的性能,但它们需要大量的计算资源,通常在 GPU 上运行。
有关嵌入模型及其性能的更多信息,您可以参考MTEB 排行榜,它比较了多个任务上的各种文本嵌入模型。
下面是我们将用于矢量化的代码(在 CPU 机器上运行该数据集只需要几分钟):
import numpy as np
from sentence_transformers import SentenceTransformer
import chromadb
from chromadb.config import Settings
from tqdm import tqdm
# 初始化嵌入模型
model = SentenceTransformer( 'all-MiniLM-L6-v2' , device= 'cpu' )
# 初始化 ChromaDB
chroma_client = chromadb.Client(Settings(persist_directory= "chroma_db" ))
collection = chroma_client.create_collection( "mishnah" )
# 从保存的文件加载数据集
df = pd.read_csv(os.path.join( "Mishnah" , "mishnah_metadata.csv" ))
# 生成带进度条的嵌入的函数
def generate_embeddings ( passages, model ):
embeddings = []
for passage in tqdm(paragraphs, desc= "生成嵌入" ):
embedding = model.encode(paragraph, show_progress_bar= False )
embeddings.append(embedding)
return np.array(embeddings)
# 为英文段落生成嵌入 embeddings
= generate_embeddings(df[ 'english' ].tolist(), model)
df[ 'embedding' ] = embeddings.tolist()
# 将嵌入存储在 ChromaDB 中,并带有进度条
for index, row in tqdm(df.iterrows(), desc= "存储在 ChromaDB 中" , total= len (df)):
collection.add(embeddings=[row[ 'embedding' ]], documents=[row[ 'english' ]], metadatas=[{
"seder" : row[ 'seder' ],
"tractate" : row[ 'tractate' ],
"chapter" : row[ 'chapter' ],
"mishnah" : row[ 'mishnah' ],
"hebrew" : row[ 'hebrew' ]
}])
print ( "嵌入和元数据已成功存储在 ChromaDB 中。" )
3. 用英语创建我们的 RAG
数据集准备就绪后,我们现在可以创建英语检索增强生成 (RAG) 应用程序。为此,我们将使用 LangChain,这是一个功能强大的框架,它为各种语言模型操作和集成提供了统一的界面,使构建复杂的应用程序变得容易。
LangChain 简化了语言模型 (LLM)、检索器和向量存储等不同组件的集成过程。通过使用 LangChain,我们可以专注于应用程序的高级逻辑,而不必担心每个组件的底层复杂性。
以下是设置 RAG 系统的代码:
从langchain.chains导入LLMChain、RetrievalQA
从langchain.llms导入Bedrock
从langchain.prompts导入PromptTemplate
从sentence_transformers导入SentenceTransformer
导入chromadb
从chromadb.config导入设置
从typing导入 列表
# 为 Llama 3 70B 初始化 AWS Bedrock Instruct
llm = Bedrock(
model_id= "meta.llama3-70b-instruct-v1:0"
)
# 定义提示模板
prompt_template = PromptTemplate(
input_variables=[ "context" , "question" ],
template= """
仅根据提供的上下文回答以下问题:
上下文:{context}
问题:{question}
答案(简短而简洁):
“” ,
)
# 初始化 ChromaDB
chroma_client = chromadb.Client(Settings(persist_directory= "chroma_db" ))
collection = chroma_client.get_collection( "mishnah" )
# 定义嵌入模型
embedding_model = SentenceTransformer( 'all-MiniLM-L6-v2' , device= 'cpu' )
# 定义一个简单的检索函数
def simple_retriever ( query: str , k: int = 3 ) -> List [ str ]:
query_embedding = embedding_model.encode(query).tolist()
results = collection.query(query_embeddings=[query_embedding], n_results=k)
documents = results[ 'documents' ][ 0 ] # 访问“documents”中的第一个列表
sources = results[ 'metadatas' ][ 0 ] # 访问源的元数据
return documents, sources
# 初始化 LLM 链
llm_chain = LLMChain(
llm=llm,
prompt=prompt_template
)
# 定义 SimpleQA 链
class SimpleQAChain :
def __init__ ( self, triester, llm_chain ):
self.retriever = triester
self.llm_chain = llm_chain
def __call__ (self,inputs,do_print_context = True ):
question = input[ "query" ]
retriever_docs,sources = self.retriever(question)
context = "\n\n" .join(retrieved_docs)
response = self.llm_chain.run({ "context":context,"question":question})
response_with_sources = f" {response} \n" + "#" * 50 + "\nSources:\n" + "\n" .join(
[ f" {source[ 'seder' ]} {source[ 'tractate' ]} Chapter {source[ 'chapter' ]},Mishnah {source[ 'mishnah' ]} " for source in sources]
)
如果do_print_context:
print ( "#" * 50 )
print ( "检索到的段落:" )
for doc in removed_docs:
print (doc[: 100 ] + "..." )
return response_with_sources
# 初始化并测试 SimpleQAChain
qa_chain = SimpleQAChain(retriever=simple_retriever, llm_chain=llm_chain)
解释:
- **AWS Bedrock 初始化:**我们使用 Llama 3 70B Instruct 初始化 AWS Bedrock。此模型将用于根据检索到的上下文生成响应。
- **提示模板:**提示模板旨在将上下文和问题格式化为 LLM 可以理解的结构。这有助于生成简洁且相关的答案。您可以随意尝试并根据需要调整模板。
- **嵌入模型:**我们还使用“all-MiniLM-L6-v2”模型为查询生成嵌入。我们希望查询与相关答案段落具有相似的表示。注意:为了提高检索性能,我们可以使用 LLM 修改和优化用户查询,使其更类似于 RAG 数据库的风格。
- **LLM Chain:**来自 LangChain 的类
LLMChain
用于管理 LLM 与检索到的上下文之间的交互。 - **SimpleQAChain:**这个自定义类集成了检索器和 LLM 链。它检索相关段落,将其格式化为上下文,然后生成答案。
好吧!让我们尝试一下!我们将使用与 Mishnah 中第一段相关的查询。
response = qa_chain({ "query" : "什么时候背诵 Shema 比较合适?" })
print ( "#" *50)
print ( "Response:" )
print (response)
#####################################################
检索到的段落:
论文<i>Berakhot</i>的开头,这是Mish 六个命令中的第一个论文... <b>早上
什么时候开始背诵<i>Shema</i> ?<b>从</b>一个人<b>可以区分... Beit Shammai 和 Beit Hillel 对背诵<i>Shema</i>的正确方法存在争议。<b>Beit Shammai 说:</b... #####################################################回应:晚上,从祭司进来享用他们的 teruma 直到第一班结束,或者根据 Rabban Gamliel 的说法,直到黎明。 早晨,从一个人可以区分天蓝色和白色开始,直到日出。#####################################################资料来源:Seder Zeraim Mishnah Berakhot 第 1 章,Mishnah 1 Seder Zeraim Mishnah Berakhot 第 1 章,Mishnah 2 Seder Zeraim Mishnah Berakhot 第 1 章,Mishnah 3
这看起来相当准确。
让我们尝试问一个更复杂的问题:
response = qa_chain({ "query" : "安息日禁止从事的第三种工作是什么?" })
print ( "#" * 50 )
print ( "Response:" )
print (response)
##################################################
检索到的段落:
他们说,关于安息年,有一个重要的一般原则:任何作为食物的东西......
这个基本的米什纳列举了那些执行<b>主要劳动类别</b>的人禁止......
<b>拉比阿基瓦说: 我问拉比埃利泽关于</b>一个<b>执行多个</b>禁止的人......
##################################################
回答:收割的
人。##################################################来源:Seder Zeraim Mishnah Sheviit 第 7 章,Mishnah 1 Seder Moed Mishnah Shabbat 第 7 章,Mishnah 2 Seder Kodashim Mishnah Keritot 第 3 章,Mishnah 10
很不错。
我们可以通过直接查询 Claude 来实现同样的效果吗?
我尝试了一下,结果如下:
克劳德·桑奈特没有对这个问题给出确切的答案。图片由作者提供。
回答很长,没有切中要点,给出的答案是错误的(收割是列表中的第三个工作类型,而选择是第七个)。这就是我们所说的幻觉。
虽然 Claude 是一个强大的语言模型,但仅依靠 LLM 从记忆的训练数据生成响应或甚至使用互联网搜索,缺乏检索增强生成 (RAG) 应用程序中自定义数据库所提供的精度和控制。原因如下:
- **精确度和语境:**我们的 RAG 应用程序从自定义数据库中检索精确的段落,确保高相关性和准确性。如果没有特定的检索机制,Claude 可能无法提供相同级别的详细和语境相关的响应。
- 效率: RAG 方法可以有效地处理大型数据集,结合检索和生成来保持精确且与上下文相关的答案。
- **成本效益:**通过使用相对较小的 LLM(例如 Llama 3 70B Instruct),我们可以获得准确的结果,而无需在每次查询时发送大量数据。这降低了使用更大、资源更密集的模型所产生的成本。
这种结构化的检索过程可确保用户收到最准确和最相关的答案,充分利用 LLM 的语言生成能力和自定义数据检索的精确度。
4. 跨语言 RAG 方法
最后,我们将解决用希伯来语与原始希伯来语文本进行交互的挑战。同样的方法可以应用于任何其他语言,只要您能够在检索阶段将文本翻译成英语即可。
支持希伯来语交互会增加一层额外的复杂性,因为嵌入模型和大型语言模型 (LLM) 往往更擅长处理英语。虽然一些嵌入模型和 LLM 确实支持希伯来语,但它们的稳健性通常不如英语模型,尤其是较小的嵌入模型,它们在训练期间可能更侧重于英语。
为了解决这个问题,我们可以训练自己的希伯来语嵌入模型。但是,另一种实用的方法是利用一次性将文本翻译成英语,并在检索过程中使用英语嵌入。这样,我们可以从英语模型的强大性能中受益,同时仍然支持希伯来语交互。
处理步骤
跨语言 RAG 架构图。图片由作者提供。
在我们的案例中,我们已经有专业的人工翻译将《米什纳》文本翻译成英文。我们将利用这一点来确保检索的准确性,同时保持希伯来语响应的完整性。以下是我们如何设置这个跨语言 RAG 系统:
- **用希伯来语输入查询:**用户可以用希伯来语输入他们的查询。
- **将查询翻译成英语:**我们使用 LLM 将希伯来语查询翻译成英语。
- **嵌入查询:**然后嵌入翻译后的英语查询。
- **使用英语嵌入查找相关文档:**我们使用英语嵌入来查找相关文档。
- **检索相应的希伯来语文本:**检索相应的希伯来语文本作为上下文。本质上,我们在检索操作中使用英语文本作为键,希伯来语文本作为相应的值。
- 使用 LLM 以希伯来语回复: LLM 使用希伯来语上下文以希伯来语生成回复。
对于生成,我们使用 Claude Sonnet,因为它在希伯来语文本上的表现比 Llama 3 好得多。
以下是代码实现:
从langchain.chains导入LLMChain、RetrievalQA
从langchain.llms导入Bedrock
从langchain_community.chat_models导入BedrockChat
从langchain.prompts导入PromptTemplate
从sentence_transformers导入SentenceTransformer
导入chromadb
从chromadb.config导入设置
从typing导入 List
导入re
# 使用特定的配置为 Llama 3 70B Instruct 初始化 AWS Bedrock 以进行翻译
Translation_llm = Bedrock(
model_id= "meta.llama3-70b-instruct-v1:0" ,
model_kwargs={
"temperature" : 0.0 , # 设置较低的翻译温度
"max_gen_len" : 50 # 限制翻译的 token 数量
}
)
# 使用特定的配置为 Claude Sonnet 初始化 AWS Bedrock 以进行生成
Generation_llm = BedrockChat(
model_id= "anthropic.claude-3-sonnet-20240229-v1:0"
)
# 定义翻译提示模板
translation_prompt_template = PromptTemplate(
input_variables=[ "text" ],
template= """将以下希伯来语文本翻译成英语:
输入文本:{text}
Translation:
"""
)
# 定义希伯来语答案的提示模板
hebrew_prompt_template = PromptTemplate(
input_variables=[ "context " , "question" ],
template= """ ענה על השאלה הבאה בהתבסס על ההקשר המסופק בלבד:
הקשר: {context}
שאלה: {question}
תשובה (קצרה ותמציתית):
"""
)
# 初始化 ChromaDB
chroma_client = chromadb.Client(Settings(persist_directory= "chroma_db" ))
collection = chroma_client.get_collection( "mishnah" )
# 定义嵌入模型
embedding_model = SentenceTransformer( 'all-MiniLM-L6-v2' , device= 'cpu' )
# 用于将查询从希伯来语翻译为英语的翻译链
Translation_chain = LLMChain(
llm=translation_llm,
提示=翻译提示模板
)
# 初始化希伯来语答案的 LLM 链
hebrew_llm_chain = LLMChain(
llm=generation_llm,
prompt=hebrew_prompt_template
)
# 定义一个简单的希伯来语文本检索函数
def simple_retriever ( query: str , k: int = 3 ) -> List [ str ]:
query_embedding = embedding_model.encode(query).tolist()
results = collection.query(query_embeddings=[query_embedding], n_results=k)
documents = [meta[ 'hebrew' ] for meta in results[ 'metadatas' ][ 0 ]] # 访问希伯来语文本
sources = results[ 'metadatas' ][ 0 ] # 访问来源的元数据
return documents, sources
# 从希伯来语文本中删除元音的函数
def remove_vowels_hebrew ( hebrew_text ):
pattern = re. compile(r'[\u0591-\u05C7]')
hebrew_text_without_vowels = re.sub(pattern,'',hebrew_text)
return hebrew_text_without_vowels
# 定义带有翻译的 SimpleQA 链
class SimpleQAChainWithTranslation:
def __init__(self,translation_chain,retriever,llm_chain):
self.translation_chain = Translation_chain
self.retriever = Retriever
self.llm_chain = llm_chain
def __call__(self,inputs):
hebrew_query = input[ "query" ]
print(“#” * 50)
print(f“Hebrew query:{hebrew_query} ”)
# 打印翻译提示
translation_prompt = Translation_prompt_template。格式(text=hebrew_query)
print ( "#" * 50 )
print ( f"翻译提示: {translation_prompt} " )
# 使用具有特定配置的翻译链执行
翻译lingual_query = self.translation_chain.run({ "text" : hebrew_query})
print ( "#" *50 )
print ( f"Translated Query: {translated_query} " ) # 打印翻译后的查询以供调试
retrieved_docs, sources = self.retriever(translated_query)
retrieved_docs = [remove_vowels_hebrew(doc) for doc in removed_docs]
context = "\n" .join(retrieved_docs)
# 打印最终提示以供生成
final_prompt = hebrew_prompt_template.格式(context=context, question=hebrew_query)
打印( "#" * 50 )
打印( f"Final Prompt for Generation:\n {final_prompt} " )
响应 = self.llm_chain.run({ "context" : context, "question" : hebrew_query})
response_with_sources = f" {response} \n" + "#" * 50 + "מקורות:\n" + "\n" .join(
[ f" {source[ 'seder' ]} {source[ 'tractate' ]} פרק {source[ 'chapter' ]} , משנה {source[ 'mishnah' ]} " for source in sources]
)
返回response_with_sources
# 初始化并测试 SimpleQAChainWithTranslation
qa_chain = SimpleQAChainWithTranslation(translation_chain,simple_retriever,hebrew_llm_chain)
让我们尝试一下!我们将使用与之前相同的问题,但这次使用希伯来语:
响应 = qa_chain({ "query" : "העבודה השלששй האסור בשבת?" })
print ( "#" * 50 )
print (response)
####################################################
希伯来语查询: מהו סוג העבודה השלййй האסור בשבת?
####################################################
翻译提示:将以下希伯来语文本翻译成英语:
输入文本: מהו סוג העבודה השלйשй האסור בשבת?
翻译:
################################################ ##
查询 翻译:安息日禁止的第三类工作是什么 ?输入文本:כל העולם כולו גשר צר מאוד翻译:######################################## ###########生成的最终提示:ענה על השאלה הבאה בהתבסס על ההקשר המסופק בלבד: הקשר: אבות מלא是的。原来如此。原来如此。原来如此。原来如此。唷。原来如此。原来如此。好吧。就是这样。原来如此。原来如此。就这样吧。。就这样吧。原来如此。原来如此。原来如此。一切皆有可能。是的。是的。唷。原来如此。这就是我们要说的。一切都已结束。唷唷唷。好吧。就这样。等等,等等。原来如此。原来如此。是的。一切都已完成。唷。原来如此。唷唷唷。是的。已完成。一切都已完成。正确的方式: 正确的方式正确的方式正确的方式正确的方式一切都好,一切都好。是的。囍圜圜圜圜
一切都已结束 ,一切都已结束。英语:英语:英语:英语:英语一切都好,一切都好。效果图效果图,效果图:效果图: 效果图 效果图 效果图效果图啥?תשובה ( תשובה ): ############################################## ###### 。####################################################歌曲: Seder Moed Mishnah Shabbat 3 7 , 2 Seder Kodashim Mishnah Menachot 11 , 3 Seder Moed Mishnah Shabbat 13 , 3
我们得到了一个准确的、一字一句的答案。很简洁,对吧?
有趣的挑战和解决方案
使用 Llama 3 Instruct 进行翻译带来了一些挑战。最初,无论我怎么尝试,模型都会产生无意义的结果。(显然,Llama 3 instruct 对以换行符开头的提示非常敏感!)
解决该问题后,模型倾向于输出正确的响应,但随后继续输出其他不相关的文本,因此在换行符处停止输出被证明是有效的。
控制输出格式可能比较棘手。一些策略包括请求 JSON 格式或提供带有少量提示的示例。
在这个项目中,我们还从希伯来语文本中删除了元音,因为大多数在线希伯来语文本不包含元音,并且我们希望我们的 LLM 的上下文与预训练期间看到的文本相似。
结论
构建这个 RAG 应用程序是一段迷人的旅程,将古代文本的细微差别与现代人工智能技术融合在一起。我对让古代拉比文本图书馆更容易被所有人(包括我自己)访问的热情推动了这个项目。这项技术可以与你的图书馆聊天,根据想法搜索资源等等。这里使用的方法可以应用于其他珍贵的文本集合,为获取和探索历史和文化知识开辟新的可能性。
令人惊讶的是,得益于当今强大的工具和框架,所有这些工作只需几个小时就能完成。欢迎随时查看GitHub上的完整代码,并使用MishnahBot网站进行操作。
对以换行符开头的提示非常敏感!)
解决该问题后,模型倾向于输出正确的响应,但随后继续输出其他不相关的文本,因此在换行符处停止输出被证明是有效的。
控制输出格式可能比较棘手。一些策略包括请求 JSON 格式或提供带有少量提示的示例。
在这个项目中,我们还从希伯来语文本中删除了元音,因为大多数在线希伯来语文本不包含元音,并且我们希望我们的 LLM 的上下文与预训练期间看到的文本相似。
结论
构建这个 RAG 应用程序是一段迷人的旅程,将古代文本的细微差别与现代人工智能技术融合在一起。我对让古代拉比文本图书馆更容易被所有人(包括我自己)访问的热情推动了这个项目。这项技术可以与你的图书馆聊天,根据想法搜索资源等等。这里使用的方法可以应用于其他珍贵的文本集合,为获取和探索历史和文化知识开辟新的可能性。
令人惊讶的是,得益于当今强大的工具和框架,所有这些工作只需几个小时就能完成。欢迎随时查看GitHub上的完整代码,并使用MishnahBot网站进行操作。
请分享您的评论和问题,特别是如果您正在尝试类似的东西。如果您希望将来看到更多类似的内容,请告诉我!
博客原文:专业人工智能技术社区