AGI

Bygning af LLM-agenter til RAG fra bunden og udover: En omfattende vejledning

mm
Building LLM Agents for RAG from Scratch and Beyond: A Comprehensive Guide

LLM’er som GPT-3, GPT-4 og deres open-source-modstykke kæmper ofte med at hente opdateret information og kan nogen gange generere hallucinationer eller forkert information.

Retrieval-Augmented Generation (RAG) er en teknik, der kombinerer kraften fra LLM’er med ekstern videnhenting. RAG giver os mulighed for at grundlægge LLM-svar i faktuelle, opdaterede oplysninger, hvilket betydeligt forbedrer nøjagtigheden og pålideligheden af AI-genereret indhold.

I denne blogpost vil vi udforske, hvordan vi kan bygge LLM-agenter til RAG fra bunden, dykke dybt ind i arkitekturen, implementationsdetaljer og avancerede teknikker. Vi vil dække alt fra RAG’s grundlæggende principper til at skabe sofistikerede agenter, der kan udføre komplekse opgaver og tænke kritisk.

Før vi dykker ned i at bygge vores LLM-agent, lad os forstå, hvad RAG er, og hvorfor det er vigtigt.

RAG, eller Retrieval-Augmented Generation, er en hybridtilgang, der kombinerer informationshenting med tekstgenerering. I et RAG-system:

  • En forespørgsel bruges til at hente relevante dokumenter fra en videnbase.
  • Disse dokumenter føres herefter ind i en sprogmodel sammen med den oprindelige forespørgsel.
  • Modellen genererer et svar baseret på både forespørgslen og den hentede information.
RAG

RAG

Denne tilgang har flere fordele:

  • Forbedret nøjagtighed: Ved at grundlægge svar i hentet information, reducerer RAG hallucinationer og forbedrer faktuelle nøjagtighed.
  • Opdateret information: Videnbasen kan opdateres regelmæssigt, hvilket giver systemet adgang til aktuel information.
  • Gennemsigtighed: Systemet kan give kilder for sin information, hvilket øger tillid og giver mulighed for faktatjek.

Forståelse af LLM-agenter

 

Når du står over for et problem med ingen let løsning, skal du ofte følge flere skridt, tænke omhyggeligt og huske, hvad du allerede har prøvet. LLM-agenter er designet til netop disse situationer i sprogmodelapplikationer. De kombinerer omfattende dataanalyse, strategisk planlægning, datahenting og evnen til at lære af tidligere handlinger for at løse komplekse problemer.

Hvad er LLM-agenter?

LLM-agenter er avancerede AI-systemer designet til at skabe kompleks tekst, der kræver sekventiel tænkning. De kan tænke forud, huske tidligere samtaler og bruge forskellige værktøjer til at tilpasse deres svar efter situationen og den nødvendige stil.

Overvej en spørgsmål i det juridiske felt, såsom: “Hvad er de potentielle juridiske konsekvenser af en bestemt type kontraktbrud i Californien?” En grundlæggende LLM med en RAG-system kan hente den nødvendige information fra juridiske databaser.

Til en mere detaljeret scenario: “I lyset af nye databeskyttelseslove, hvilke juridiske udfordringer står virksomheder over for, og hvordan har domstolene behandlet disse spørgsmål?” Dette spørgsmål graver dybere end blot at se oplysninger op. Det handler om at forstå nye regler, deres indvirkning på forskellige virksomheder og domstolens svar. En LLM-agent ville bryde denne opgave ned i underopgaver, såsom at hente de seneste love, analysere historiske sager, sammenfatte juridiske dokumenter og forudsige tendenser baseret på mønstre.

Komponenter af LLM-agenter

LLM-agenter består generelt af fire komponenter:

  1. Agent/Hjerne: Den centrale sprogmodel, der behandler og forstår sprog.
  2. Planlægning: Evnen til at tænke, bryde opgaver ned og udvikle specifikke planer.
  3. Hukommelse: Bevarer optegnelser over tidligere interaktioner og lærer af dem.
  4. Værktøjsbrug: Integrerer forskellige ressourcer for at udføre opgaver.

Agent/Hjerne

I centrum af en LLM-agent er en sprogmodel, der behandler og forstår sprog baseret på store mængder data, den er trænet på. Du starter med at give den en specifik prompt, der vejleder agenten om, hvordan den skal svare, hvilke værktøjer den skal bruge og hvilke mål den skal stræbe efter. Du kan tilpasse agenten med en persona, der er egnet til bestemte opgaver eller interaktioner, hvilket forbedrer dens præstation.

Hukommelse

Hukommelseskomponenten hjælper LLM-agenter med at håndtere komplekse opgaver ved at bevarer optegnelser over tidligere handlinger. Der er to hovedtyper af hukommelse:

  • Korttids-hukommelse: Fungerer som en notesblok, der holder styr på pågående diskussioner.
  • Langtids-hukommelse: Fungerer som en dagbog, der gemmer information fra tidligere interaktioner for at lære mønstre og træffe bedre beslutninger.

Ved at kombinere disse typer af hukommelse kan agenten tilbyde mere tilpassede svar og huske brugerpræferencer over tid, hvilket skaber en mere forbundet og relevant interaktion.

Planlægning

Planlægning giver LLM-agenter evnen til at tænke, bryde opgaver ned i håndterbare dele og tilpasse planer, efterhånden som opgaverne udvikler sig. Planlægning indebærer to hovedfaser:

  • Planformulering: At bryde en opgave ned i mindre underopgaver.
  • Planreflektion: At gennemgå og vurderere planens effektivitet, inkorporere feedback for at finjustere strategier.

Metoder som Chain of Thought (CoT) og Tree of Thought (ToT) hjælper i denne nedbrydningsproces, hvilket giver agenterne mulighed for at udforske forskellige stier for at løse et problem.

For at dykke dybere ind i verden af AI-agenter, inklusive deres nuværende kapaciteter og potentiale, overvej at læse “Auto-GPT & GPT-Engineer: En dybdegående vejledning til i dag førende AI-agenter”

Opsætning af Miljøet

For at bygge vores RAG-agent skal vi opsætte vores udviklingsmiljø. Vi vil bruge Python og flere nøglebiblioteker:

  • LangChain: Til at orkestrere vores LLM- og hentingskomponenter
  • Chroma: Som vores vektorlager til dokument-embeddings
  • OpenAI’s GPT-modeller: Som vores basis-LLM (du kan erstatte dette med en open-source-model, hvis du foretrækker)
  • FastAPI: Til at skabe en simpel API til at interagere med vores agent

Lad os starte med at opsætte vores miljø:


# Opret et nyt virtuelt miljø
python -m venv rag_agent_env
source rag_agent_env/bin/activate # På Windows, brug `rag_agent_env\Scripts\activate`

# Installer nødvendige pakker
pip install langchain chromadb openai fastapi uvicorn

Nu lad os oprette en ny Python-fil kaldet rag_agent.py og importere de nødvendige biblioteker:


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

# Angiv din OpenAI-API-nøgle
os.environ["OPENAI_API_KEY"] = "din-api-nøgle-her"

Bygning af et Simpelt RAG-System

Nu, hvor vi har opsat vores miljø, lad os bygge et grundlæggende RAG-system. Vi starter med at oprette en videnbase fra en samling dokumenter, derefter bruger vi denne til at besvare forespørgsler.

Trin 1: Forbered Dokumenterne

Først skal vi indlæse og forberede vores dokumenter. I dette eksempel antager vi, at vi har en tekstfil kaldet knowledge_base.txt med nogen information om AI og maskinlæring.


# Indlæs dokumentet
loader = TextLoader("knowledge_base.txt")
dokumenter = loader.load()

# Split dokumenterne i stykker
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
tekster = text_splitter.split_documents(dokumenter)

# Opret embeddings
embeddings = OpenAIEmbeddings()

# Opret et vektorlager
vectorstore = Chroma.from_documents(tekster, embeddings)

Trin 2: Opret en Hentingsbaseret QA-Kæde

Nu, hvor vi har vores vektorlager, kan vi oprette en hentingsbaseret QA-kæde:


# Opret en hentingsbaseret QA-kæde
qa = RetrievalQA.from_chain_type(llm=OpenAI(), chain_type="stuff", retriever=vectorstore.as_retriever())

Trin 3: Spørg Systemet

Vi kan nu spørgge vores RAG-system:


forespørgsel = "Hvad er de vigtigste anvendelser af maskinlæring?"
resultat = qa.run(forespørgsel)
print(resultat)

Trin 4: Oprettelse af en LLM-Agent

Selvom vores simple RAG-system er nyttigt, er det ret begrænset. Lad os forbedre det ved at oprette en LLM-agent, der kan udføre mere komplekse opgaver og tænke over den information, den henter.

En LLM-agent er et AI-system, der kan bruge værktøjer og træffe beslutninger om, hvilke handlinger der skal udføres. Vi vil oprette en agent, der ikke kun kan besvare spørgsmål, men også udføre web-søgninger og grundlæggende beregninger.

Først skal vi definere nogle værktøjer til vores agent:


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

# Definer et regneark-værktøj
class CalculatorTool(BaseTool):
name = "Calculator"
description = "Nyttig til når du skal besvare spørgsmål om matematik"

def _run(self, forespørgsel: str)
try:
return str(eval(forespørgsel))
except:
return "Jeg kunne ikke beregne det. Venligst sikr, at din input er et gyldigt matematisk udtryk."

# Opret værktøjsinstanser
søgning = DuckDuckGoSearchRun()
regneark = CalculatorTool()

# Definer værktøjerne
værktøjer = [Tool(name="Søgning", func=søgning.run, description="Nyttig til når du skal besvare spørgsmål om aktuelle begivenheder"),
Tool(name="RAG-QA", func=qa.run, description="Nyttig til når du skal besvare spørgsmål om AI og maskinlæring"),
Tool(name="Calculator", func=regneark._run, description="Nyttig til når du skal udføre matematiske beregninger")
]

# Initialiser agenten
agent = initialize_agent(værktøjer, OpenAI(temperature=0), agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)

Nu har vi en agent, der kan bruge vores RAG-system, udføre web-søgninger og udføre beregninger. Lad os teste den:


resultat = agent.run("Hvad er forskellen på overvåget og uovervåget læring? Og hvad er 15% af 80?")
print(resultat)

Denne agent demonstrerer en nøgleforskel mellem LLM-agenter: de kan kombinere flere værktøjer og tænkningstrin for at besvare komplekse spørgsmål.

Forbedring af Agenten med Avancerede RAG-Teknikker

Selvom vores nuværende RAG-system fungerer godt, er der flere avancerede teknikker, vi kan bruge til at forbedre dets præstation:

a) Semantisk Søgning med Dense Passage Retrieval (DPR)

I stedet for at bruge enkel embedding-baseret henting kan vi implementere DPR til mere præcis semantisk søgning:


from transformers import DPRQuestionEncoder, DPRContextEncoder

question_encoder = DPRQuestionEncoder.from_pretrained("facebook/dpr-question_encoder-single-nq-base")
context_encoder = DPRContextEncoder.from_pretrained("facebook/dpr-ctx_encoder-single-nq-base")

# Funktion til at kodificere passager
def encode_passages(passages):
return context_encoder(passages, max_length=512, return_tensors="pt").pooler_output

# Funktion til at kodificere forespørgsel
def encode_query(query):
return question_encoder(query, max_length=512, return_tensors="pt").pooler_output

b) Forespørgselsudvidelse

Vi kan bruge forespørgselsudvidelse til at forbedre hentingspræstation:


from transformers import T5ForConditionalGeneration, T5Tokenizer

model = T5ForConditionalGeneration.from_pretrained("t5-small")
tokenizer = T5Tokenizer.from_pretrained("t5-small")

def expand_query(query):
input_text = f"expand query: {query}"
input_ids = tokenizer.encode(input_text, return_tensors="pt")
outputs = model.generate(input_ids, max_length=50, num_return_sequences=3)
expanded_queries = [tokenizer.decode(output, skip_special_tokens=True) for output in outputs]
return expanded_queries

c) Iterativ Forbedring

Vi kan implementere en iterativ forbedringsproces, hvor agenten kan stille følgespørgsmål for at klargøre eller udvide sin oprindelige henting:


def iterative_retrieval(initial_query, max_iterations=3):
query = initial_query
for _ in range(max_iterations):
result = qa.run(query)
clarification = agent.run(f"Basert på dette resultat: '{result}', hvilket følgespørgsmål skal jeg stille for at få mere specifik information?")
if clarification.lower().strip() == "none":
break
query = clarification
return result

# Brug dette i din agents proces

Implementering af et Multi-Agent-System

For at håndtere mere komplekse opgaver kan vi implementere et multi-agent-system, hvor forskellige agenter specialiserer sig i forskellige områder. Her er et simpelt eksempel:


class SpecialistAgent:
def __init__(self, name, tools):
self.name = name
self.agent = initialize_agent(tools, OpenAI(temperature=0), agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)

def run(self, query):
return self.agent.run(query)

# Opret specialagenter
research_agent = SpecialistAgent("Research", [Tool(name="RAG-QA", func=qa.run, description="Til AI- og maskinlærings-spørgsmål")])
math_agent = SpecialistAgent("Math", [Tool(name="Calculator", func=regneark._run, description="Til beregninger")])
general_agent = SpecialistAgent("General", [Tool(name="Søgning", func=søgning.run, description="Til generelle forespørgsler")])

class Coordinator:
def __init__(self, agents):
self.agents = agents

def run(self, query):
# Bestem, hvilken agent der skal bruges
if "calculate" in query.lower() or any(op in query for op in ['+', '-', '*', '/']):
return self.agents['Math'].run(query)
elif any(term in query.lower() for term in ['ai', 'maskinlæring', 'dyb læring']):
return self.agents['Research'].run(query)
else:
return self.agents['General'].run(query)

coordinator = Coordinator({'Research': research_agent, 'Math': math_agent, 'General': general_agent})

# Test multi-agent-systemet
resultat = coordinator.run("Hvad er forskellen på CNN og RNN? Og beregn 25% af 120.")
print(resultat)

Dette multi-agent-system giver mulighed for specialisering og kan håndtere en bredere vifte af forespørgsler mere effektivt.

Evaluering og Optimering af RAG-Agenter

For at sikre, at vores RAG-agent fungerer godt, skal vi implementere evalueringsskemaer og optimeringsteknikker:

a) Relevans-Evaluering

Vi kan bruge mål som BLEU, ROUGE eller BERTScore til at evaluere relevansen af hentede dokumenter:


from bert_score import score

def evaluate_relevance(query, retrieved_doc, generated_answer):
P, R, F1 = score([generated_answer], [retrieved_doc], lang="en")
return F1.mean().item()

b) Svar-Kvalitets-Evaluering

Vi kan bruge menneskeevaluering eller automatiserede mål til at vurderere svar-kvalitet:


from nltk.translate.bleu_score import sentence_bleu

def evaluate_answer_quality(reference_answer, generated_answer):
return sentence_bleu([reference_answer.split()], generated_answer.split())

# Brug dette til at evaluere din agents svar

Fremtidige Retninger og Udfordringer

Da vi ser frem til fremtiden for RAG-agenter, opstår flere spændende retninger og udfordringer:

a) Multi-modal RAG: At udvide RAG til at omfatte billed-, lyd- og video-data.

b) Federeret RAG: At implementere RAG på tværs af distribuerede, privatlivsbeskyttende videnbaser.

c) Fortløbende Læring: At udvikle metoder til, at RAG-agenter kan opdatere deres videnbaser og modeller over tid.

d) Etiske Overvejelser: At håndtere bias, lighed og gennemsigtighed i RAG-systemer.

e) Skalbarhed: At optimere RAG til store, virkningsfulde og hurtige anvendelser.

Konklusion

At bygge LLM-agenter til RAG fra bunden er en kompleks, men belønning proces. Vi har dækket RAG’s grundlæggende principper, implementeret et simpelt system, skabt en LLM-agent, forbedret den med avancerede teknikker, udforsket multi-agent-systemer og diskuteret evaluering og optimeringsteknikker.

Jeg har brugt de sidste fem Är pÄ at dykke ned i den fascinerende verden af Machine Learning og Deep Learning. Min passion og ekspertise har fÞrt til, at jeg har bidraget til over 50 forskellige software-udviklingsprojekter, med sÊrlig fokus pÄ AI/ML. Min vedvarende nysgerrighed har ogsÄ fÞrt mig i retning af Natural Language Processing, et felt jeg er ivrig efter at udforske yderligere.