Costruire un sistema RAG multilingue per i testi rabbinici

Robot che studia la Mishnah. Credito: DALL-E-3.

Sono entusiasta di condividere in questo post il mio viaggio nella creazione di un'applicazione unica di Retrieval-Augmented Generation (RAG) per interagire con i testi rabbinici. MishnahBot mira a fornire agli studiosi e agli utenti quotidiani un modo intuitivo per interrogare ed esplorare la Mishnah¹ in modo interattivo. Può aiutare a risolvere problemi come individuare rapidamente i testi di origine rilevanti o riassumere un dibattito complesso sulla legge religiosa, estraendone i risultati.

Ho avuto l'idea per un progetto del genere qualche anno fa, ma sentivo che la tecnologia non era ancora matura. Ora, con i progressi dei modelli linguistici di grandi dimensioni e delle funzionalità RAG, è piuttosto semplice.

Ecco come apparirà il nostro prodotto finale, che potresti provare Qui:

MishnahBot sito web. Immagine dell'autore.

Le applicazioni RAG stanno guadagnando molta attenzione, per migliorare la precisione e sfruttare la potenza di ragionamento disponibile nei modelli linguistici di grandi dimensioni (LLM). Immagina di poter chattare con la tua biblioteca, una raccolta di manuali di auto della stessa casa produttrice o i tuoi documenti fiscali. Puoi porre domande e ricevere risposte informate dalla ricchezza di conoscenze specializzate.

Schema dell'architettura tipica di un sistema RAG. Credito: Documentazione di Amazon AWS.

Esistono due tendenze emergenti nel miglioramento delle interazioni dei modelli linguistici: Retrieval-Augmented Generation (RAG) e aumento della lunghezza del contesto, potenzialmente consentendo documenti molto lunghi come allegati.

Un vantaggio chiave dei sistemi RAG è l’efficienza in termini di costi. Con RAG puoi gestire contesti di grandi dimensioni senza aumentare drasticamente il costo delle query, che può diventare costoso. Inoltre, RAG è più modulare e ti consente di collegarti e giocare con diverse basi di conoscenza e fornitori LLM. D’altra parte, aumentare la lunghezza del contesto direttamente nei modelli linguistici è uno sviluppo entusiasmante che può consentire di gestire testi molto più lunghi in un’unica interazione.

Per questo progetto ho utilizzato AWS SageMaker per il mio ambiente di sviluppo, AWS Bedrock per accedere a vari LLM e il framework LangChain per gestire la pipeline. Entrambi i servizi AWS sono intuitivi e addebitano solo le risorse utilizzate, quindi ti incoraggio davvero a provarli tu stesso. Per Bedrock, dovrai richiedere l'accesso a Llama 3 70b Instruct e Claude Sonnet.

Apriamo un nuovo notebook Jupyter e installiamo i pacchetti che utilizzeremo:

!pip install chromadb tqdm langchain chromadb sentence-transformers

Il set di dati per questo progetto è la Mishnah, un antico testo rabbinico centrale nella tradizione ebraica. Ho scelto questo testo perché mi sta a cuore e rappresenta anche una sfida per i modelli linguistici poiché è un argomento di nicchia. Il set di dati è stato ottenuto da Sefaria-Export repository², un tesoro di testi rabbinici con traduzioni inglesi allineate all'originale ebraico. Questo allineamento facilita il passaggio da una lingua all'altra nelle diverse fasi della nostra applicazione RAG.

Nota: lo stesso processo applicato qui può essere applicato a qualsiasi altra raccolta di testi di tua scelta. Questo esempio dimostra anche come la tecnologia RAG possa essere utilizzata in diverse lingue, come mostrato in questo caso con l'ebraico.

Per prima cosa dovremo scaricare i dati rilevanti. Utilizzeremo git sparse-checkout poiché il repository completo è piuttosto grande. Apri la finestra del terminale ed esegui quanto segue.

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
tree Mishna/ | less

E… voilà! ora abbiamo i file di dati di cui abbiamo bisogno:

Mishnah
├── Seder Kodashim
│ ├── Mishnah Arakhin
│ │ ├── English
│ │ │ └── merged.json
│ │ └── Hebrew
│ │ └── merged.json
│ ├── Mishnah Bekhorot
│ │ ├── English
│ │ │ └── merged.json
│ │ └── Hebrew
│ │ └── merged.json
│ ├── Mishnah Chullin
│ │ ├── English
│ │ │ └── merged.json
│ │ └── Hebrew
│ │ └── merged.json

Ora carichiamo i documenti nel nostro ambiente notebook Jupyter:

import os
import json
import pandas as pd
from tqdm import tqdm

# Function to load all documents into a DataFrame with progress bar
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")
if os.path.exists(english_file) and os.path.exists(hebrew_file):
with open(english_file, 'r', encoding='utf-8') as ef, open(hebrew_file, 'r', encoding='utf-8') as hf:
english_data = json.load(ef)
hebrew_data = json.load(hf)
for chapter_index, (english_chapter, hebrew_chapter) in enumerate(zip(english_data('text'), hebrew_data('text'))):
for mishnah_index, (english_paragraph, hebrew_paragraph) in enumerate(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
})
return pd.DataFrame(data)
# Load all documents
base_path = "Mishnah"
df = load_documents(base_path)
# Save the DataFrame to a file for future reference
df.to_csv(os.path.join(base_path, "mishnah_metadata.csv"), index=False)
print("Dataset successfully loaded into DataFrame and saved to file.")

E dai un'occhiata ai dati:

df.shape
(4192, 7)

print(df.head()(("tractate", "mishnah", "english")))
tractate mishnah english
0 Mishnah Arakhin 1 <b>Everyone takes</b> vows of <b>valuation</b>...
1 Mishnah Arakhin 2 With regard to <b>a gentile, Rabbi Meir says:<...
2 Mishnah Arakhin 3 <b>One who is moribund and one who is taken to...
3 Mishnah Arakhin 4 In the case of a pregnant <b>woman who is take...
4 Mishnah Arakhin 1 <b>One cannot be charged for a valuation less ...

Sembra buono, possiamo passare alla fase del database vettoriale.

Successivamente, vettorizziamo il testo e lo memorizziamo in un ChromaDB locale. In una frase, l’idea è di rappresentare il testo come vettori densi – matrici di numeri – in modo tale che i testi semanticamente simili siano “vicini” tra loro nello spazio vettoriale. Questa è la tecnologia che ci consentirà di recuperare i passaggi rilevanti data una query.

Abbiamo optato per un modello di vettorizzazione leggero, il all-MiniLM-L6-v2che può funzionare in modo efficiente su una CPU. Questo modello fornisce un buon equilibrio tra prestazioni ed efficienza delle risorse, rendendolo adatto alla nostra applicazione. Mentre modelli all'avanguardia come quelli di OpenAI text-embedding-3-large possono offrire prestazioni superiori, richiedono notevoli risorse computazionali, in genere eseguite su GPU.

Per ulteriori informazioni sull'incorporamento dei modelli e sulle relative prestazioni, è possibile fare riferimento a Classifica MTEB che confronta vari modelli di incorporamento del testo su più attività.

Ecco il codice che utilizzeremo per la vettorizzazione (dovrebbero essere necessari solo pochi minuti per l'esecuzione su questo set di dati su una macchina CPU):

import numpy as np
from sentence_transformers import SentenceTransformer
import chromadb
from chromadb.config import Settings
from tqdm import tqdm

# Initialize the embedding model
model = SentenceTransformer('all-MiniLM-L6-v2', device='cpu')
# Initialize ChromaDB
chroma_client = chromadb.Client(Settings(persist_directory="chroma_db"))
collection = chroma_client.create_collection("mishnah")
# Load the dataset from the saved file
df = pd.read_csv(os.path.join("Mishnah", "mishnah_metadata.csv"))
# Function to generate embeddings with progress bar
def generate_embeddings(paragraphs, model):
embeddings = ()
for paragraph in tqdm(paragraphs, desc="Generating Embeddings"):
embedding = model.encode(paragraph, show_progress_bar=False)
embeddings.append(embedding)
return np.array(embeddings)
# Generate embeddings for English paragraphs
embeddings = generate_embeddings(df('english').tolist(), model)
df('embedding') = embeddings.tolist()
# Store embeddings in ChromaDB with progress bar
for index, row in tqdm(df.iterrows(), desc="Storing in 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("Embeddings and metadata successfully stored in ChromaDB.")

Con il nostro set di dati pronto, ora possiamo creare la nostra applicazione RAG (Retrieval-Augmented Generation) in inglese. Per questo, utilizzeremo LangChain, un potente framework che fornisce un'interfaccia unificata per varie operazioni e integrazioni di modelli linguistici, semplificando la creazione di applicazioni sofisticate.

LangChain semplifica il processo di integrazione di diversi componenti come modelli linguistici (LLM), retriever e archivi di vettori. Utilizzando LangChain, possiamo concentrarci sulla logica di alto livello della nostra applicazione senza preoccuparci delle complessità sottostanti di ciascun componente.

Ecco il codice per configurare il nostro sistema RAG:

from langchain.chains import LLMChain, RetrievalQA
from langchain.llms import Bedrock
from langchain.prompts import PromptTemplate
from sentence_transformers import SentenceTransformer
import chromadb
from chromadb.config import Settings
from typing import List

# Initialize AWS Bedrock for Llama 3 70B Instruct
llm = Bedrock(
model_id="meta.llama3-70b-instruct-v1:0"
)

# Define the prompt template
prompt_template = PromptTemplate(
input_variables=("context", "question"),
template="""
Answer the following question based on the provided context alone:
Context: {context}
Question: {question}
Answer (short and concise):
""",
)

# Initialize ChromaDB
chroma_client = chromadb.Client(Settings(persist_directory="chroma_db"))
collection = chroma_client.get_collection("mishnah")

# Define the embedding model
embedding_model = SentenceTransformer('all-MiniLM-L6-v2', device='cpu')

# Define a simple retriever function
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) # Access the first list inside 'documents'
sources = results('metadatas')(0) # Access the metadata for sources
return documents, sources

# Initialize the LLM chain
llm_chain = LLMChain(
llm=llm,
prompt=prompt_template
)

# Define SimpleQA chain
class SimpleQAChain:
def __init__(self, retriever, llm_chain):
self.retriever = retriever
self.llm_chain = llm_chain

def __call__(self, inputs, do_print_context=True):
question = inputs("query")
retrieved_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)
)
if do_print_context:
print("#"*50)
print("Retrieved paragraphs:")
for doc in retrieved_docs:
print(doc(:100) + "...")
return response_with_sources

# Initialize and test SimpleQAChain
qa_chain = SimpleQAChain(retriever=simple_retriever, llm_chain=llm_chain)

  1. Inizializzazione AWS Bedrock: Inizializziamo AWS Bedrock con Llama 3 70B Instruct. Questo modello verrà utilizzato per generare risposte in base al contesto recuperato.
  2. Modello di richiesta: Il modello di prompt è definito per formattare il contesto e la domanda in una struttura che LLM può comprendere. Questo aiuta a generare risposte concise e pertinenti. Sentiti libero di giocare e modificare il modello secondo necessità.
  3. Modello di incorporamento: Utilizziamo il modello “all-MiniLM-L6-v2” anche per generare incorporamenti per le query. Ci auguriamo che la query abbia una rappresentazione simile ai paragrafi di risposta pertinenti. Nota: per aumentare le prestazioni di recupero, potremmo utilizzare un LLM per modificare e ottimizzare la query dell'utente in modo che sia più simile allo stile del database RAG.
  4. Catena LLM: IL LLMChain La classe LangChain viene utilizzata per gestire l'interazione tra LLM e il contesto recuperato.
  5. Catena QAC semplice: Questa classe personalizzata integra il retriever e la catena LLM. Recupera i paragrafi rilevanti, li formatta in un contesto e genera una risposta.

Bene! Proviamolo! Utilizzeremo una query relativa ai primissimi paragrafi della Mishnah.

response = qa_chain({"query": "What is the appropriate time to recite Shema?"})

print("#"*50)
print("Response:")
print(response)

##################################################
Retrieved paragraphs:
The beginning of tractate <i>Berakhot</i>, the first tractate in the first of the six orders of Mish...
<b>From when does one recite <i>Shema</i> in the morning</b>? <b>From</b> when a person <b>can disti...
Beit Shammai and Beit Hillel disputed the proper way to recite <i>Shema</i>. <b>Beit Shammai say:</b...
##################################################
Response:
In the evening, from when the priests enter to partake of their teruma until the end of the first watch, or according to Rabban Gamliel, until dawn. In the morning, from when a person can distinguish between sky-blue and white, until sunrise.
##################################################
Sources:
Seder Zeraim Mishnah Berakhot Chapter 1, Mishnah 1
Seder Zeraim Mishnah Berakhot Chapter 1, Mishnah 2
Seder Zeraim Mishnah Berakhot Chapter 1, Mishnah 3

Sembra abbastanza accurato.

Proviamo una domanda più sofisticata:

response = qa_chain({"query": "What is the third prohibited kind of work on the sabbbath?"})

print("#"*50)
print("Response:")
print(response)

##################################################
Retrieved paragraphs:
They said an important general principle with regard to the sabbatical year: anything that is food f...
This fundamental mishna enumerates those who perform the <b>primary categories of labor</b> prohibit...
<b>Rabbi Akiva said: I asked Rabbi Eliezer with regard to</b> one who <b>performs multiple</b> prohi...
##################################################
Response:
One who reaps.
##################################################
Sources:
Seder Zeraim Mishnah Sheviit Chapter 7, Mishnah 1
Seder Moed Mishnah Shabbat Chapter 7, Mishnah 2
Seder Kodashim Mishnah Keritot Chapter 3, Mishnah 10

Molto bello.

L'ho provato, ecco cosa ho ottenuto:

Claude Sonnet non riesce a dare una risposta esatta alla domanda. Immagine dell'autore.

La risposta è lunga e non pertinente e la risposta fornita non è corretta (mietere è il terzo tipo di lavoro nell'elenco, mentre selezionando è il settimo). Questo è ciò che chiamiamo a allucinazione.

Sebbene Claude sia un modello linguistico potente, fare affidamento esclusivamente su un LLM per generare risposte da dati di allenamento memorizzati o anche utilizzare ricerche su Internet non ha la precisione e il controllo offerti da un database personalizzato in un'applicazione RAG (Retrieval-Augmented Generation). Ecco perché:

  1. Precisione e contesto: La nostra applicazione RAG recupera i paragrafi esatti da un database personalizzato, garantendo elevata pertinenza e precisione. Claude, senza meccanismi di recupero specifici, potrebbe non fornire lo stesso livello di risposte dettagliate e specifiche al contesto.
  2. Efficienza: L'approccio RAG gestisce in modo efficiente set di dati di grandi dimensioni, combinando recupero e generazione per mantenere risposte precise e contestualmente rilevanti.
  3. Efficacia dei costi: Utilizzando un LLM relativamente piccolo come Llama 3 70B Instruct, otteniamo risultati accurati senza dover inviare una grande quantità di dati con ciascuna query. Ciò riduce i costi associati all’utilizzo di modelli più grandi e ad alta intensità di risorse.

Questo processo di recupero strutturato garantisce che gli utenti ricevano le risposte più accurate e pertinenti, sfruttando sia le capacità di generazione del linguaggio dei LLM sia la precisione del recupero dei dati personalizzati.

Infine, affronteremo la sfida di interagire in ebraico con il testo ebraico originale. Lo stesso approccio può essere applicato a qualsiasi altra lingua, purché si sia in grado di tradurre i testi in inglese per la fase di recupero.

Il supporto delle interazioni ebraiche aggiunge un ulteriore livello di complessità poiché i modelli di incorporamento e i modelli linguistici di grandi dimensioni (LLM) tendono ad essere più forti in inglese. Sebbene alcuni modelli di incorporamento e LLM supportino l'ebraico, sono spesso meno robusti delle loro controparti inglesi, in particolare i modelli di incorporamento più piccoli che probabilmente si concentrano maggiormente sull'inglese durante la formazione.

Per affrontare questo problema, potremmo addestrare il nostro modello di incorporamento ebraico. Tuttavia, un altro approccio pratico consiste nel sfruttare una traduzione una tantum del testo in inglese e utilizzare gli incorporamenti in inglese per il processo di recupero. In questo modo, traiamo vantaggio dalle ottime prestazioni dei modelli inglesi pur continuando a supportare le interazioni ebraiche.

Schema dell'architettura RAG multilingue. Immagine dell'autore.

Nel nostro caso, disponiamo già di traduzioni umane professionali del testo della Mishnah in inglese. Lo useremo per garantire recuperi accurati mantenendo l'integrità delle risposte ebraiche. Ecco come possiamo impostare questo sistema RAG multilingue:

  1. Query di input in ebraico: Gli utenti possono inserire le loro query in ebraico.
  2. Traduci la query in inglese: Usiamo un LLM per tradurre la query ebraica in inglese.
  3. Incorpora la query: La query inglese tradotta viene quindi incorporata.
  4. Trova documenti rilevanti utilizzando gli incorporamenti in inglese: Usiamo gli incorporamenti inglesi per trovare documenti rilevanti.
  5. Recupera i testi ebraici corrispondenti: I corrispondenti testi ebraici vengono recuperati come contesto. Essenzialmente stiamo usando i testi inglesi come chiavi e i testi ebraici come corrispondenti valori nell'operazione di recupero.
  6. Rispondi in ebraico utilizzando un LLM: Un LLM genera la risposta in ebraico utilizzando il contesto ebraico.

Per la generazione utilizziamo Claude Sonnet poiché ha prestazioni significativamente migliori sul testo ebraico rispetto a Llama 3.

Ecco l'implementazione del codice:

from langchain.chains import LLMChain, RetrievalQA
from langchain.llms import Bedrock
from langchain_community.chat_models import BedrockChat
from langchain.prompts import PromptTemplate
from sentence_transformers import SentenceTransformer
import chromadb
from chromadb.config import Settings
from typing import List
import re

# Initialize AWS Bedrock for Llama 3 70B Instruct with specific configurations for translation
translation_llm = Bedrock(
model_id="meta.llama3-70b-instruct-v1:0",
model_kwargs={
"temperature": 0.0, # Set lower temperature for translation
"max_gen_len": 50 # Limit number of tokens for translation
}
)

# Initialize AWS Bedrock for Claude Sonnet with specific configurations for generation
generation_llm = BedrockChat(
model_id="anthropic.claude-3-sonnet-20240229-v1:0"
)

# Define the translation prompt template
translation_prompt_template = PromptTemplate(
input_variables=("text"),
template="""Translate the following Hebrew text to English:
Input text: {text}
Translation:
"""
)

# Define the prompt template for Hebrew answers
hebrew_prompt_template = PromptTemplate(
input_variables=("context", "question"),
template="""ענה על השאלה הבאה בהתבסס על ההקשר המסופק בלבד:
הקשר: {context}
שאלה: {question}
תשובה (קצרה ותמציתית):
"""
)

# Initialize ChromaDB
chroma_client = chromadb.Client(Settings(persist_directory="chroma_db"))
collection = chroma_client.get_collection("mishnah")

# Define the embedding model
embedding_model = SentenceTransformer('all-MiniLM-L6-v2', device='cpu')

# Translation chain for translating queries from Hebrew to English
translation_chain = LLMChain(
llm=translation_llm,
prompt=translation_prompt_template
)

# Initialize the LLM chain for Hebrew answers
hebrew_llm_chain = LLMChain(
llm=generation_llm,
prompt=hebrew_prompt_template
)

# Define a simple retriever function for Hebrew texts
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)) # Access Hebrew texts
sources = results('metadatas')(0) # Access the metadata for sources
return documents, sources

# Function to remove vowels from Hebrew text
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

# Define SimpleQA chain with translation
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 = inputs("query")
print("#" * 50)
print(f"Hebrew query: {hebrew_query}")

# Print the translation prompt
translation_prompt = translation_prompt_template.format(text=hebrew_query)
print("#" * 50)
print(f"Translation Prompt: {translation_prompt}")

# Perform the translation using the translation chain with specific configurations
translated_query = self.translation_chain.run({"text": hebrew_query})
print("#" * 50)
print(f"Translated Query: {translated_query}") # Print the translated query for debugging

retrieved_docs, sources = self.retriever(translated_query)
retrieved_docs = (remove_vowels_hebrew(doc) for doc in retrieved_docs)

context = "\n".join(retrieved_docs)

# Print the final prompt for generation
final_prompt = hebrew_prompt_template.format(context=context, question=hebrew_query)
print("#" * 50)
print(f"Final Prompt for Generation:\n {final_prompt}")

response = 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)
)
return response_with_sources

# Initialize and test SimpleQAChainWithTranslation
qa_chain = SimpleQAChainWithTranslation(translation_chain, simple_retriever, hebrew_llm_chain)

Proviamolo! Utilizzeremo la stessa domanda di prima, ma questa volta in ebraico:

response = qa_chain({"query": "מהו סוג העבודה השלישי האסור בשבת?"})
print("#" * 50)
print(response)
##################################################
Hebrew query: מהו סוג העבודה השלישי האסור בשבת?
##################################################
Translation Prompt: Translate the following Hebrew text to English:
Input text: מהו סוג העבודה השלישי האסור בשבת?
Translation:

##################################################
Translated Query: What is the third type of work that is forbidden on Shabbat?

Input text: כל העולם כולו גשר צר מאוד
Translation:

##################################################
Final Prompt for Generation:
ענה על השאלה הבאה בהתבסס על ההקשר המסופק בלבד:
הקשר: אבות מלאכות ארבעים חסר אחת. הזורע. והחורש. והקוצר. והמעמר. הדש. והזורה. הבורר. הטוחן. והמרקד. והלש. והאופה. הגוזז את הצמר. המלבנו. והמנפצו. והצובעו. והטווה. והמסך. והעושה שני בתי נירין. והאורג שני חוטין. והפוצע שני חוטין. הקושר. והמתיר. והתופר שתי תפירות. הקורע על מנת לתפר שתי תפירות. הצד צבי. השוחטו. והמפשיטו. המולחו, והמעבד את עורו. והמוחקו. והמחתכו. הכותב שתי אותיות. והמוחק על מנת לכתב שתי אותיות. הבונה. והסותר. המכבה. והמבעיר. המכה בפטיש. המוציא מרשות לרשות. הרי אלו אבות מלאכות ארבעים חסר אחת:

חבתי כהן גדול, לישתן ועריכתן ואפיתן בפנים, ודוחות את השבת. טחונן והרקדן אינן דוחות את השבת. כלל אמר רבי עקיבא, כל מלאכה שאפשר לה לעשות מערב שבת, אינה דוחה את השבת. ושאי אפשר לה לעשות מערב שבת, דוחה את השבת:

הקורע בחמתו ועל מתו, וכל המקלקלין, פטורין. והמקלקל על מנת לתקן, שעורו כמתקן:

שאלה: מהו סוג העבודה השלישי האסור בשבת?
תשובה (קצרה ותמציתית):

##################################################
הקוצר.
##################################################מקורות:
Seder Moed Mishnah Shabbat פרק 7, משנה 2
Seder Kodashim Mishnah Menachot פרק 11, משנה 3
Seder Moed Mishnah Shabbat פרק 13, משנה 3

Abbiamo ottenuto una risposta precisa, di una sola parola, alla nostra domanda. Abbastanza carino, vero?

La traduzione con Llama 3 Instruct ha posto diverse sfide. Inizialmente, il modello produceva risultati senza senso, qualunque cosa provassi. (Apparentemente, l'istruzione di Llama 3 è molto sensibile ai prompt che iniziano con un carattere di nuova riga!)

Dopo aver risolto il problema, il modello tendeva a restituire la risposta corretta, ma poi continuava con testo aggiuntivo irrilevante, quindi interrompere l'output in corrispondenza di un carattere di nuova riga si è rivelato efficace.

Controllare il formato di output può essere complicato. Alcune strategie includono la richiesta di un formato JSON o la fornitura di esempi con istruzioni brevi.

In questo progetto, rimuoviamo anche le vocali dai testi ebraici poiché la maggior parte dei testi ebraici online non include vocali e vogliamo che il contesto del nostro LLM sia simile al testo visto durante la preformazione.

Costruire questa applicazione RAG è stato un viaggio affascinante, fondendo le sfumature dei testi antichi con le moderne tecnologie di intelligenza artificiale. La mia passione nel rendere la biblioteca degli antichi testi rabbinici più accessibile a tutti (me compreso) ha guidato questo progetto. Questa tecnologia consente di chattare con la tua biblioteca, cercare fonti basate su idee e molto altro. L'approccio qui utilizzato può essere applicato ad altre preziose raccolte di testi, aprendo nuove possibilità di accesso ed esplorazione della conoscenza storica e culturale.

È sorprendente vedere come tutto ciò possa essere realizzato in poche ore, grazie ai potenti strumenti e framework oggi disponibili. Sentiti libero di controllare il codice completo su GitHube gioca con il MishnahBot sito web.

Per favore condividi i tuoi commenti e le tue domande, soprattutto se stai provando qualcosa di simile. Se vuoi vedere più contenuti come questo in futuro, fammi sapere!

Fonte: towardsdatascience.com

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *