AGI
Bygga LLM-agenter för RAG frÄn scratch och bortom: En komplett guide
LLM:er som GPT-3, GPT-4 och deras öppen källkods motsvarighet kämpar ofta med att hämta uppdaterad information och kan ibland generera hallucinationer eller felaktig information.
Retrieval-Augmented Generation (RAG) är en teknik som kombinerar kraften i LLM:er med extern kunskapshämtning. RAG låter oss grunda LLM-svar i faktiska, uppdaterade uppgifter, vilket förbättrar betydligt noggrannheten och tillförlitligheten hos AI-genererat innehåll.
I den här bloggposten kommer vi att utforska hur man bygger LLM-agenter för RAG från scratch, med djupgående diskussioner om arkitektur, implementationsdetaljer och avancerade tekniker. Vi kommer att täcka allt från RAG-grunderna till att skapa sofistikerade agenter som kan utföra komplexa resonemang och uppgifter.
Innan vi dyker in i att bygga vår LLM-agent, låt oss förstå vad RAG är och varför det är viktigt.
RAG, eller Retrieval-Augmented Generation, är en hybridapproach som kombinerar informationshämtning med textgenerering. I ett RAG-system:
- En fråga används för att hämta relevanta dokument från en kunskapsbas.
- De här dokumenten matas sedan in i en språkmodell tillsammans med den ursprungliga frågan.
- Modellen genererar ett svar baserat på både frågan och den hämtade informationen.
Den här approachen har flera fördelar:
- Förbättrad noggrannhet: Genom att grunda svar i hämtad information minskar RAG hallucinationer och förbättrar faktisk noggrannhet.
- Uppdaterad information: Kunskapsbasen kan uppdateras regelbundet, vilket gör att systemet kan komma åt aktuell information.
- Transparens: Systemet kan tillhandahålla källor för sin information, vilket ökar förtroendet och möjliggör faktakontroll.
Att förstå LLM-agenter
När du står inför ett problem med inget enkelt svar behöver du ofta följa flera steg, tänka noga och komma ihåg vad du har provat tidigare. LLM-agenter är utformade för exakt sådana situationer i språkmodellstillämpningar. De kombinerar grundlig dataanalys, strategisk planering, datahämtning och förmågan att lära av tidigare handlingar för att lösa komplexa problem.
Vad är LLM-agenter?
LLM-agenter är avancerade AI-system utformade för att skapa komplex text som kräver sekventiellt resonemang. De kan tänka i förväg, komma ihåg tidigare samtal och använda olika verktyg för att anpassa sina svar efter situationen och den stil som behövs.
Överväg en fråga inom juridik som: “Vilka är de potentiella rättsliga resultaten av en specifik typ av kontraktbrott i Kalifornien?” En grundläggande LLM med ett RAG-system kan hämta den nödvändiga informationen från juridiska databaser.
För en mer detaljerad scenarie: “I ljuset av nya dataskyddslagar, vilka är de vanliga rättsliga utmaningarna som företag står inför, och hur har domstolarna hanterat dessa frågor?” Den här frågan gräver djupare än att bara leta upp fakta. Det handlar om att förstå nya regler, deras påverkan på olika företag och domstolarnas svar. En LLM-agent skulle bryta ner den här uppgiften i underuppgifter, som att hämta de senaste lagarna, analysera historiska fall, sammanfatta juridiska dokument och förutsäga trender baserat på mönster.
LLM-agenter består av
LLM-agenter består vanligtvis av fyra komponenter:
- Agent/hjärna: Den grundläggande språkmodellen som bearbetar och förstår språk.
- Planering: Förmågan att resonera, bryta ner uppgifter och utveckla specifika planer.
- Minne: Håller koll på tidigare interaktioner och lär av dem.
- Verktygsanvändning: Integrerar olika resurser för att utföra uppgifter.
Agent/hjärna
I hjärtat av en LLM-agent finns en språkmodell som bearbetar och förstår språk baserat på stora mängder data som den har tränats på. Du börjar med att ge den en specifik prompt, som vägleder agenten om hur den ska svara, vilka verktyg den ska använda och vilka mål den ska sträva efter. Du kan anpassa agenten med en persona som passar för specifika uppgifter eller interaktioner, vilket förbättrar dess prestanda.
Minne
Minneskomponenten hjälper LLM-agenter att hantera komplexa uppgifter genom att hålla koll på tidigare handlingar. Det finns två huvudtyper av minne:
- Korttidsminne: Fungerar som en anteckningsbok, som håller koll på pågående diskussioner.
- Långtidsminne: Fungerar som en dagbok, som lagrar information från tidigare interaktioner för att lära av mönster och fatta bättre beslut.
Genom att kombinera dessa typer av minne kan agenten erbjuda mer anpassade svar och komma ihåg användarpreferenser över tid, vilket skapar en mer sammanhängande och relevant interaktion.
Planering
Planering möjliggör för LLM-agenter att resonera, bryta ner uppgifter i hanterbara delar och anpassa planer när uppgifter utvecklas. Planering omfattar två huvudstadier:
- Planformulering: Att bryta ner en uppgift i mindre underuppgifter.
- Planreflektion: Att granska och bedöma planens effektivitet, med feedback för att förbättra strategier.
Metoder som Chain of Thought (CoT) och Tree of Thought (ToT) hjälper till i den här nedbrytningsprocessen, vilket möjliggör för agenter att utforska olika vägar för att lösa ett problem.
För att dyka djupare in i världen av AI-agenter, inklusive deras nuvarande förmågor och potential, kan du läsa “Auto-GPT & GPT-Engineer: En djupgående guide till dagens ledande AI-agenter”
Att ställa in miljön
För att bygga vår RAG-agent behöver vi ställa in vår utvecklingsmiljö. Vi kommer att använda Python och flera nyckellibrarier:
- LangChain: För att orkestrera vår LLM och hämtningskomponenter
- Chroma: Som vår vektorlagring för dokumentinbäddningar
- OpenAI:s GPT-modeller: Som vår grundläggande LLM (du kan ersätta detta med en öppen källkodsmodell om du föredrar)
- FastAPI: För att skapa en enkel API för att interagera med vår agent
Låt oss börja med att ställa in vår miljö:
<p># Skapa en ny virtuell miljö python -m venv rag_agent_env source rag_agent_env/bin/activate # På Windows, använd `rag_agent_env\Scripts\activate`</p> <p># Installera nödvändiga paket pip install langchain chromadb openai fastapi uvicorn
Nu, låt oss skapa en ny Python-fil som heter rag_agent.py och importera de nödvändiga biblioteken:
<p>from langchain.embeddings import OpenAIEmbeddings from langchain.vectorstores import Chroma from langchain.text_splitter import CharacterTextSplitter from langchain.llms import OpenAI from langchain.chains import RetrievalQA from langchain.document_loaders import TextLoader import os</p> <p># Ställ in din OpenAI API-nyckel os.environ["OPENAI_API_KEY"] = "din-api-nyckel-här"</p>
Att bygga ett enkelt RAG-system
Nu när vi har vår miljö inställd, låt oss bygga ett grundläggande RAG-system. Vi kommer att börja med att skapa en kunskapsbas från en uppsättning dokument, sedan använda den för att svara på frågor.
Steg 1: Förbered dokumenten
Först behöver vi ladda och förbereda våra dokument. För det här exemplet, låt oss anta att vi har en textfil som heter knowledge_base.txt med några uppgifter om AI och maskinlärning.
<p># Ladda dokumentet loader = TextLoader("knowledge_base.txt") documents = loader.load()</p> <p># Dela dokumenten i bitar text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) texts = text_splitter.split_documents(documents)</p> <p># Skapa inbäddningar embeddings = OpenAIEmbeddings()</p> <p># Skapa en vektorlagring vectorstore = Chroma.from_documents(texts, embeddings)</p>
Steg 2: Skapa en hämtningsbaserad QA-kedja
Nu när vi har vår vektorlagring, kan vi skapa en hämtningsbaserad QA-kedja:
<p># Skapa en hämtningsbaserad QA-kedja qa = RetrievalQA.from_chain_type(llm=OpenAI(), chain_type="stuff", retriever=vectorstore.as_retriever())</p>
Steg 3: Fråga systemet
Vi kan nu fråga vårt RAG-system:
<p>fråga = "Vilka är de viktigaste tillämpningarna av maskinlärning?" resultat = qa.run(fråga) print(resultat)
Steg 4: Skapa en LLM-agent
Medan vårt enkla RAG-system är användbart, är det ganska begränsat. Låt oss förbättra det genom att skapa en LLM-agent som kan utföra mer komplexa uppgifter och resonera om den information den hämtar.
En LLM-agent är ett AI-system som kan använda verktyg och fatta beslut om vilka åtgärder som ska vidtas. Vi kommer att skapa en agent som inte bara kan svara på frågor, utan också utföra webbsökningar och grundläggande beräkningar.
Först, låt oss definiera några verktyg för vår agent:
<p>from langchain.agents import Tool from langchain.tools import DuckDuckGoSearchRun from langchain.tools import BaseTool from langchain.agents import initialize_agent from langchain.agents import AgentType</p> <p># Definiera ett kalkylverktyg class CalculatorTool(BaseTool): name = "Kalkylator" description = "Användbart när du behöver svara på matematiska frågor"</p> <p>def _run(self, fråga: str) try: return str(eval(fråga)) except: return "Jag kunde inte beräkna det. Se till att din inmatning är ett giltigt matematiskt uttryck."</p> <p># Skapa verktygsinstanser sök = DuckDuckGoSearchRun() kalkylator = CalculatorTool()</p> <p># Definiera verktygen verktyg = [Tool(name="Sök", func=sök.run, description="Användbart när du behöver svara på frågor om aktuella händelser"), Tool(name="RAG-QA", func=qa.run, description="Användbart när du behöver svara på frågor om AI och maskinlärning"), Tool(name="Kalkylator", func=kalkylator._run, description="Användbart när du behöver utföra matematiska beräkningar") ]</p> <p># Initiera agenten agent = initialize_agent(verktyg, OpenAI(temperature=0), agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True )</p>
Nu har vi en agent som kan använda vårt RAG-system, utföra webbsökningar och göra beräkningar. Låt oss testa den:
<p>resultat = agent.run("Vad är skillnaden mellan övervakad och oövervakad inlärning? Och vad är 15% av 80?") print(resultat)</p>
Den här agenten demonstrerar en viktig fördel med LLM-agenter: de kan kombinera flera verktyg och resonemangssteg för att svara på komplexa frågor.
Att förbättra agenten med avancerade RAG-tekniker
Medan vårt nuvarande RAG-system fungerar bra, finns det flera avancerade tekniker som vi kan använda för att förbättra dess prestanda:
a) Semantisk sökning med Dense Passage Retrieval (DPR)
I stället för att använda enkel inbäddningsbaserad hämtning, kan vi implementera DPR för mer exakt semantisk sökning:
<p>from transformers import DPRQuestionEncoder, DPRContextEncoder</p> <p>frågekodare = DPRQuestionEncoder.from_pretrained("facebook/dpr-question_encoder-single-nq-base") sammanhangskodare = DPRContextEncoder.from_pretrained("facebook/dpr-ctx_encoder-single-nq-base")</p> <p># Funktion för att koda passager def koda_passager(passager): return sammanhangskodare(passager, max_length=512, return_tensors="pt").pooler_output</p> <p># Funktion för att koda fråga def koda_fråga(fråga): return frågekodare(fråga, max_length=512, return_tensors="pt").pooler_output</p>
b) Frågeexpansion
Vi kan använda frågeexpansion för att förbättra hämtningsprestanda:
<p>from transformers import T5ForConditionalGeneration, T5Tokenizer</p>
<p>modell = T5ForConditionalGeneration.from_pretrained("t5-small")
tokenisatör = T5Tokenizer.from_pretrained("t5-small")</p>
<p>def expandera_fråga(fråga):
inmatningstext = f"expandera fråga: {fråga}"
inmatningsid = tokenisatör.encode(inmatningstext, return_tensors="pt")
utgångar = modell.generate(inmatningsid, max_length=50, num_return_sequences=3)
expanderade_frågor = [tokenisatör.decode(utgång, skip_special_tokens=True) for utgång in utgångar]
return expanderade_frågor</p>
c) Iterativ förfining
Vi kan implementera en iterativ förfiningsprocess där agenten kan ställa följdfrågor för att förtydliga eller expandera sin initiala hämtning:
<p>def iterativ_hämtning(inledande_fråga, max_iterationer=3):
fråga = inledande_fråga
for _ in range(max_iterationer):
resultat = qa.run(fråga)
förtydligande = agent.run(f"Baseras på det här resultatet: '{resultat}', vilken följdfråga bör jag ställa för att få mer specifik information?")
if förtydligande.lower().strip() == "ingen":
break
fråga = förtydligande
return resultat</p>
# Använd det här i din agents process
Att implementera ett multiagent-system
För att hantera mer komplexa uppgifter kan vi implementera ett multiagent-system där olika agenter specialiserar sig på olika områden. Här är ett enkelt exempel:
<p>class SpecialistAgent:
def __init__(self, name, verktyg):
self.name = name
self.agent = initialize_agent(verktyg, OpenAI(temperature=0), agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)</p>
<p>def run(self, fråga):
return self.agent.run(fråga)</p>
<p># Skapa specialistagenter
forskningsagent = SpecialistAgent("Forskning", [Tool(name="RAG-QA", func=qa.run, description="För AI- och ML-frågor")])
matematikagent = SpecialistAgent("Matematik", [Tool(name="Kalkylator", func=kalkylator._run, description="För beräkningar")])
allmänagent = SpecialistAgent("Allmänt", [Tool(name="Sök", func=sök.run, description="För allmänna frågor")])</p>
<p>class Koordinator:
def __init__(self, agenter):
self.agenter = agenter</p>
<p>def run(self, fråga):
# Bestäm vilken agent som ska användas
if "beräkna" in fråga.lower() or any(op in fråga for op in ['+', '-', '*', '/']):
return self.agenter['Matematik'].run(fråga)
elif any(term in fråga.lower() for term in ['ai', 'maskinlärning', 'djupinlärning']):
return self.agenter['Forskning'].run(fråga)
else:
return self.agenter['Allmänt'].run(fråga)</p>
<p>koordinator = Koordinator({'Forskning': forskningsagent, 'Matematik': matematikagent, 'Allmänt': allmänagent})</p>
<p># Testa multiagent-systemet
resultat = koordinator.run("Vad är skillnaden mellan CNN och RNN? Och beräkna 25% av 120.")
print(resultat)</p>
Det här multiagent-systemet möjliggör specialisering och kan hantera en bredare variation av frågor mer effektivt.
Att utvärdera och optimera RAG-agenter
För att säkerställa att vår RAG-agent fungerar bra, behöver vi implementera utvärderingsmetoder och optimeringstekniker:
a) Relevansutvärdering
Vi kan använda metoder som BLEU, ROUGE eller BERTScore för att utvärdera relevansen hos hämtade dokument:
<p>from bert_score import score</p> <p>def utvärdera_relevans(fråga, hämtat_dokument, genererat_svar): P, R, F1 = score([genererat_svar], [hämtat_dokument], lang="sv") return F1.mean().item()</p>
b) Svarskvalitetsutvärdering
Vi kan använda mänsklig utvärdering eller automatiserade metoder för att bedöma svarskvalitet:
<p>from nltk.translate.bleu_score import sentence_bleu</p> <p>def utvärdera_svarskvalitet(referenssvar, genererat_svar): return sentence_bleu([referenssvar.split()], genererat_svar.split())</p> <p># Använd det här för att utvärdera din agents svar
Framtida riktningar och utmaningar
När vi ser framåt mot framtiden för RAG-agenter, finns det flera spännande riktningar och utmaningar:
a) Multi-modal RAG: Att utöka RAG till att omfatta bild-, ljud- och videodata.
b) Federerad RAG: Att implementera RAG över distribuerade, sekretessbevarande kunskapsbaser.
c) Kontinuerligt lärande: Att utveckla metoder för RAG-agenter att uppdatera sina kunskapsbaser och modeller över tid.
d) Etiska överväganden: Att hantera fördomar, rättvishet och transparens i RAG-system.
e) Skalbarhet: Att optimera RAG för stora, realtidsapplikationer.
Slutsats
Att bygga LLM-agenter för RAG från scratch är en komplex men givande process. Vi har täckt grunderna i RAG, implementerat ett enkelt system, skapat en LLM-agent, förbättrat den med avancerade tekniker, utforskat multiagent-system och diskuterat utvärderings- och optimeringstekniker.














