Llamaindex ile RAG Ajanları Oluşturma

Cahit Barkin Ozer
10 min readMay 31, 2024

--

Deeplearning.ai’ın “Building Agentic RAG with Llamaindex” kursunun Türkçe özetidir.

For English:

Verileriniz üzerinde akıl yürütme ve karar verme yeteneğine sahip araştırma ajanları oluşturmanıza yardımcı olan bir çerçeve olan Llamaindex ile RAG ajanları oluşturmayı öğreneceğiz.

Örneğin, girdinin alaka düzeyine göre bir dizi araştırma makalesinden bir parçanın çıkarılması, birden fazla işlem adımı gerektiren karmaşık bir işlemdir. Standart RAG’taki ardışık düzen, basit soruların cevabını barındıran kısa belgeler için iyidir. Bu kursu alarak, özerk araştırma ajanları oluşturarak belgelerinizle sohbet etmeyi bir sonraki seviyeye taşıyacaksınız.

İlk olarak, routing ile , istekleri birden fazla ajana yönlendirmek için karar almayı ekliyoruz. Bir sonraki adım, ajanların seçilen ajana yönelik bir arayüz oluşturduğu ve aynı zamanda o ajan için doğru argümanları ürettiği ajanın kullanımıdır. Ve son olarak, ajan kullanımıyla ilgili çok adımlı akıl yürütme uyguluyoruz. Bu süreçte hafızayı korumak için bir dizi ajanla çok adımlı akıl yürütme gerçekleştirmek için LLM’i kullanacağız.

Yönlendirici Sorgu Motoru (Router Query Engine)

Bir sorgu verildiğinde, bir yönlendirici, bir sorguyu yürütmek için çeşitli sorgu motorlarından birini seçecektir. Tek bir belge üzerinde hem soru cevaplamayı hem de özetlemeyi gerçekleştirebilecek basit bir yönlendirici oluşturalım.

from helper import get_openai_api_key
OPENAI_API_KEY = get_openai_api_key()

import nest_asyncio
nest_asyncio.apply()

Verinin yüklenmesi

Bu pdf’i indirmek için gerekli kod aşağıdadır:

!wget “https://openreview.net/pdf?id=VtmBAGCN7o" -O metagpt.pdf

from llama_index.core import SimpleDirectoryReader

# load documents
documents = SimpleDirectoryReader(input_files=["metagpt.pdf"]).load_data()

LLM ve yerleştirme modeli tanımlayalım

from llama_index.core.node_parser import SentenceSplitter

splitter = SentenceSplitter(chunk_size=1024)
nodes = splitter.get_nodes_from_documents(documents)

from llama_index.core import Settings
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding

Settings.llm = OpenAI(model="gpt-3.5-turbo")
Settings.embed_model = OpenAIEmbedding(model="text-embedding-ada-002")

Aynı Veri Üzerinden Özet Dizini (Summary Index) ve Vektör Dizinini (Vector Index) Tanımlama

from llama_index.core import SummaryIndex, VectorStoreIndex

summary_index = SummaryIndex(nodes)
vector_index = VectorStoreIndex(nodes)

Sorgu Motorlarını (Query Engines) Tanımlayın ve Meta Verileri Ayarlayın

summary_query_engine = summary_index.as_query_engine(
response_mode="tree_summarize",
use_async=True,
)
vector_query_engine = vector_index.as_query_engine()

from llama_index.core.tools import QueryEngineTool

summary_tool = QueryEngineTool.from_defaults(
query_engine=summary_query_engine,
description=(
"Useful for summarization questions related to MetaGPT"
),
)

vector_tool = QueryEngineTool.from_defaults(
query_engine=vector_query_engine,
description=(
"Useful for retrieving specific context from the MetaGPT paper."
),
)

Seçiciler (Selectors)

Birkaç seçici mevcuttur:

  • LLM seçicileri, ayrıştırılan bir JSON’un çıktısını almak için LLM’i kullanır ve karşılık gelen dizinler sorgulanır.
  • Pydantic seçiciler, ham JSON’u ayrıştırmak yerine Pydantic seçim nesneleri üretmek için OpenAI işlev çağırma (function calling) API’sini kullanır.

Yönlendirici Sorgu Motorunu (Router Query Engine) Tanımlayalım

from llama_index.core.query_engine.router_query_engine import RouterQueryEngine
from llama_index.core.selectors import LLMSingleSelector


query_engine = RouterQueryEngine(
selector=LLMSingleSelector.from_defaults(),
query_engine_tools=[
summary_tool,
vector_tool,
],
verbose=True
)

response = query_engine.query("What is the summary of the document?")
print(str(response))
print(len(response.source_nodes)) # 34

response = query_engine.query(
"How do agents share information with other agents?"
)
print(str(response))

Her şeyi bir araya getirmek

from utils import get_router_query_engine
query_engine = get_router_query_engine("metagpt.pdf")

response = query_engine.query("Tell me about the ablation study results?")
print(str(response))

Araç Çağırma (Tool Calling)

LLM yalnızca yürütülecek bir işlevi seçmek için değil, aynı zamanda işlevden geçecek bir argüman çıkarmak için de nasıl kullanılır bunu öğreneceğiz.

Araç çağırma, LLM’lerin, araç çağırmanın yalnızca uygun ajanın seçilmesine yardımcı olmakla kalmayıp aynı zamanda uygulama için gerekli argümanları da çıkardığı dinamik bir arayüz aracılığıyla dış ortamlarla etkileşime girmesini sağlar. Standart RAG’de LLM’ler esas olarak yalnızca bilginin sentezi için kullanılır. Araç çağırma, RAG işlem hattının üstüne bir sorgu anlama katmanı ekleyerek kullanıcıların karmaşık sorgular sormasına ve daha kesin sonuçlar almasına olanak tanır.

from helper import get_openai_api_key
OPENAI_API_KEY = get_openai_api_key()
import nest_asyncio
nest_asyncio.apply()

Basit bir araç tanımlayalım

from llama_index.core.tools import FunctionTool

def add(x: int, y: int) -> int:
"""Adds two integers together."""
return x + y

def mystery(x: int, y: int) -> int:
"""Mystery function that operates on top of two numbers."""
return (x + y) * (x + y)


add_tool = FunctionTool.from_defaults(fn=add)
mystery_tool = FunctionTool.from_defaults(fn=mystery)

from llama_index.llms.openai import OpenAI

llm = OpenAI(model="gpt-3.5-turbo")
response = llm.predict_and_call(
[add_tool, mystery_tool],
"Tell me the output of the mystery function on 2 and 9",
verbose=True
)
print(str(response))

Otomatik Alma Aracı (Auto-Retrieval Tool) Tanımlama

Verilerin yüklenmesi

!wget “https://openreview.net/pdf?id=VtmBAGCN7o" -O metagpt.pdf

from llama_index.core import SimpleDirectoryReader
# load documents
documents = SimpleDirectoryReader(input_files=["metagpt.pdf"]).load_data()

from llama_index.core.node_parser import SentenceSplitter
splitter = SentenceSplitter(chunk_size=1024)
nodes = splitter.get_nodes_from_documents(documents)

print(nodes[0].get_content(metadata_mode="all"))
from llama_index.core import VectorStoreIndex

vector_index = VectorStoreIndex(nodes)
query_engine = vector_index.as_query_engine(similarity_top_k=2)

from llama_index.core.vector_stores import MetadataFilters

query_engine = vector_index.as_query_engine(
similarity_top_k=2,
filters=MetadataFilters.from_dicts(
[
{"key": "page_label", "value": "2"}
]
)
)

response = query_engine.query(
"What are some high-level results of MetaGPT?",
)

print(str(response))
for n in response.source_nodes:
print(n.metadata)

Veri Erişimini Geliştirme

Meta veri filtrelerini bir alma aracı işlevine entegre etmeyi öğrenelim. Bu işlev, bir sorgu string’ini ve sayfa numarası gibi isteğe bağlı meta veri filtrelerini kabul ederek daha kesin bir alma sağlar. LLM, kullanıcının sorgusuna dayalı olarak ilgili meta veri filtrelerini (sayfa numaraları gibi) akıllıca çıkarabilir. Bölüm kimlikleri, üstbilgiler veya altbilgiler gibi farklı türde meta veri filtreleri tanımlayabilirsiniz.

Otomatik Alma Aracını Tanımlayalım

from typing import List
from llama_index.core.vector_stores import FilterCondition


def vector_query(
query: str,
page_numbers: List[str]
) -> str:
"""Perform a vector search over an index.

query (str): the string query to be embedded.
page_numbers (List[str]): Filter by set of pages. Leave BLANK if we want to perform a vector search
over all pages. Otherwise, filter by the set of specified pages.

"""

metadata_dicts = [
{"key": "page_label", "value": p} for p in page_numbers
]

query_engine = vector_index.as_query_engine(
similarity_top_k=2,
filters=MetadataFilters.from_dicts(
metadata_dicts,
condition=FilterCondition.OR
)
)
response = query_engine.query(query)
return response

vector_query_tool = FunctionTool.from_defaults(
name="vector_tool",
fn=vector_query
)

llm = OpenAI(model="gpt-3.5-turbo", temperature=0)
response = llm.predict_and_call(
[vector_query_tool],
"What are the high-level results of MetaGPT as described on page 2?",
verbose=True
)
for n in response.source_nodes:
print(n.metadata)

Başka araçlar ekleme

from llama_index.core import SummaryIndex
from llama_index.core.tools import QueryEngineTool

summary_index = SummaryIndex(nodes)
summary_query_engine = summary_index.as_query_engine(
response_mode="tree_summarize",
use_async=True,
)
summary_tool = QueryEngineTool.from_defaults(
name="summary_tool",
query_engine=summary_query_engine,
description=(
"Useful if you want to get a summary of MetaGPT"
),
)

response = llm.predict_and_call(
[vector_query_tool, summary_tool],
"What are the MetaGPT comparisons with ChatDev described on page 8?",
verbose=True
)
for n in response.source_nodes:
print(n.metadata)

response = llm.predict_and_call(
[vector_query_tool, summary_tool],
"What is a summary of the paper?",
verbose=True
)

Bir Ajan Muhakeme Döngüsü (Agent Reasoning Loop) Oluşturma

Bu derste birden fazla adım gerektiren kullanıcı sorularıyla nasıl başa çıkacağımızı öğreneceğiz.

from helper import get_openai_api_key
OPENAI_API_KEY = get_openai_api_key()

import nest_asyncio
nest_asyncio.apply()

!wget "https://openreview.net/pdf?id=VtmBAGCN7o" -O metagpt.pdf

Sorgu Araçlarını Kurma

from utils import get_doc_tools

vector_tool, summary_tool = get_doc_tools("metagpt.pdf", "metagpt")

Kurulum İşlevi Çağrı Aracısı

Llamaindex ajanlarının AgentWorker ve AgentRunner adında birlikte çalışan 2 bileşeni vardır. AgentWorker, tanımlanmış araçları (bu durumda vektör ve özet araçları) ve bir LLM’yi kullanarak görevlerin akıl yürütmesini ve yürütülmesini gerçekleştirir. AgentRunner, düzenlemeyi yapan bir aracıdır. AgentRunner, görev_id’sinden TaskState’e ve konuşma belleğine bir eşleme olan AgentState’e sahiptir. TaskState, Görevler, tamamlanan adımlar ve bir adım kuyruğundan oluşur.

from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-3.5-turbo", temperature=0)

from llama_index.core.agent import FunctionCallingAgentWorker
from llama_index.core.agent import AgentRunner

agent_worker = FunctionCallingAgentWorker.from_tools(
[vector_tool, summary_tool],
llm=llm,
verbose=True
)
agent = AgentRunner(agent_worker)

response = agent.query(
"Tell me about the agent roles in MetaGPT, "
"and then how they communicate with each other."
)
print(response.source_nodes[0].get_content(metadata_mode="all"))

Tam Aracı Muhakeme Döngüsü (Full Agent Reasoning Loop)

Bellek modülleri özelleştirilebilir. Bellek, varsayılan olarak düz bir öğe listesidir.

response = agent.chat(
"Tell me about the evaluation datasets used."
)
response = agent.chat("Tell me the results over one of the above datasets.")

Ajan Kontrolü (Agent Control)

Hata ayıklamak ve sonucu yönlendirmek için ajanın eylem akışını kontrol edebiliriz.

Temel faydalar:

  • Görev Oluşturma ve Yürütmenin Ayrılması: Kullanıcılar, görev yürütmeyi ihtiyaçlarına göre planlama esnekliği kazanırlar.
  • Gelişmiş Hata Ayıklama: Yürütme sürecinin her adımına ilişkin daha derin bilgiler sunarak sorun giderme yetenekleri geliştirilir.
  • Yönlendirilebilirlik: Kullanıcıların ara adımları doğrudan değiştirmesine ve gelişmiş kontrol için insan geri bildirimini birleştirmesine olanak tanır.

Alt Seviye (Lower Level): Hata Ayıklama ve Kontrol

agent_worker = FunctionCallingAgentWorker.from_tools(
[vector_tool, summary_tool],
llm=llm,
verbose=True
)
agent = AgentRunner(agent_worker)

task = agent.create_task(
"Tell me about the agent roles in MetaGPT, "
"and then how they communicate with each other."
)

step_output = agent.run_step(task.task_id)
completed_steps = agent.get_completed_steps(task.task_id)
print(f"Num completed for task {task.task_id}: {len(completed_steps)}")
print(completed_steps[0].output.sources[0].raw_output)
upcoming_steps = agent.get_upcoming_steps(task.task_id)
print(f"Num upcoming steps for task {task.task_id}: {len(upcoming_steps)}")
upcoming_steps[0]
step_output = agent.run_step(
task.task_id, input="What about how agents share information?"
)
step_output = agent.run_step(task.task_id)
print(step_output.is_last) # True or False by if it is the last step or not
response = agent.finalize_response(task.task_id)
print(str(response))

Çoklu Belge Ajanı Oluşturma

Tek bir belge üzerinde akıl yürütebilen ve hafızayı korurken karmaşık soruları yanıtlayabilen bir ajan oluşturduk. Bu bölümde, bu ajanı birden fazla belgeyi ve artan karmaşıklık derecelerini yönetecek şekilde nasıl genişleteceğimizi öğreneceğiz. Önce 3 belgeyle başlayacağız ve daha sonra 11 belgeye geçeceğiz.

from helper import get_openai_api_key
OPENAI_API_KEY = get_openai_api_key()

import nest_asyncio
nest_asyncio.apply()

3 makale üzerinden bir ajan oluşturun

Bu bölümde dilediğiniz soruyu sorabilir veya 3 belgenin birleşiminden oluşan özetler alabilirsiniz.

Metagpt belgesi sorulduğunda eylem akışı
urls = [
"https://openreview.net/pdf?id=VtmBAGCN7o",
"https://openreview.net/pdf?id=6PmJoRfdaK",
"https://openreview.net/pdf?id=hSyW5go0v8",
]

papers = [
"metagpt.pdf",
"longlora.pdf",
"selfrag.pdf",
]

from utils import get_doc_tools # helper function that automatically builds both vector and summary index tools
from pathlib import Path

paper_to_tools_dict = {}
for paper in papers:
print(f"Getting tools for paper: {paper}")
vector_tool, summary_tool = get_doc_tools(paper, Path(paper).stem)
paper_to_tools_dict[paper] = [vector_tool, summary_tool]

initial_tools = [t for paper in papers for t in paper_to_tools_dict[paper]]

from llama_index.llms.openai import OpenAI

llm = OpenAI(model="gpt-3.5-turbo")

len(initial_tools) # 6

from llama_index.core.agent import FunctionCallingAgentWorker
from llama_index.core.agent import AgentRunner

agent_worker = FunctionCallingAgentWorker.from_tools(
initial_tools,
llm=llm,
verbose=True
)
agent = AgentRunner(agent_worker)

response = agent.query(
"Tell me about the evaluation dataset used in LongLoRA, "
"and then tell me about the evaluation results"
)
response = agent.query("Give me a summary of both Self-RAG and LongLoRA")
print(str(response))

11 makale üzerinden bir ajan oluşturun

2 belgenin özeti
# Downloading 11 ICLR papers
urls = [
"https://openreview.net/pdf?id=VtmBAGCN7o",
"https://openreview.net/pdf?id=6PmJoRfdaK",
"https://openreview.net/pdf?id=LzPWWPAdY4",
"https://openreview.net/pdf?id=VTF8yNQM66",
"https://openreview.net/pdf?id=hSyW5go0v8",
"https://openreview.net/pdf?id=9WD9KwssyT",
"https://openreview.net/pdf?id=yV6fD7LYkF",
"https://openreview.net/pdf?id=hnrB5YHoYu",
"https://openreview.net/pdf?id=WbWtOYIzIK",
"https://openreview.net/pdf?id=c5pwL0Soay",
"https://openreview.net/pdf?id=TpD2aG1h0D"
]

papers = [
"metagpt.pdf",
"longlora.pdf",
"loftq.pdf",
"swebench.pdf",
"selfrag.pdf",
"zipformer.pdf",
"values.pdf",
"finetune_fair_diffusion.pdf",
"knowledge_card.pdf",
"metra.pdf",
"vr_mcl.pdf"
]
# To download these papers, below is the needed code:

for url, paper in zip(urls, papers):
!wget "{url}" -O "{paper}"
from utils import get_doc_tools
from pathlib import Path

paper_to_tools_dict = {}
for paper in papers:
print(f"Getting tools for paper: {paper}")
vector_tool, summary_tool = get_doc_tools(paper, Path(paper).stem)
paper_to_tools_dict[paper] = [vector_tool, summary_tool]

Ajanı Araç Almayla Genişletme (Extending the Agent with Tool Retrieval)

all_tools = [t for paper in papers for t in paper_to_tools_dict[paper]]

# define an "object" index and retriever over these tools
from llama_index.core import VectorStoreIndex
from llama_index.core.objects import ObjectIndex

obj_index = ObjectIndex.from_objects(
all_tools,
index_cls=VectorStoreIndex,
)

obj_retriever = obj_index.as_retriever(similarity_top_k=3)

tools = obj_retriever.retrieve(
"Tell me about the eval dataset used in MetaGPT and SWE-Bench"
)

tools[1].metadata

İsteğe göre en benzer 3 araç alınır. İsteğe bağlı olarak sistem istemini de tanımlayabilirsiniz.

from llama_index.core.agent import FunctionCallingAgentWorker
from llama_index.core.agent import AgentRunner

agent_worker = FunctionCallingAgentWorker.from_tools(
tool_retriever=obj_retriever,
llm=llm,
system_prompt=""" \
You are an agent designed to answer queries over a set of given papers.
Please always use the tools provided to answer a question. Do not rely on prior knowledge.\

""",
verbose=True
)
agent = AgentRunner(agent_worker)

response = agent.query(
"Tell me about the evaluation dataset used "
"in MetaGPT and compare it against SWE-Bench"
)
print(str(response))
response = agent.query(
"Compare and contrast the LoRA papers (LongLoRA, LoftQ). "
"Analyze the approach in each paper first. "
)

Daha fazlası için aşağıdaki kaynakları kontrol edin:

Kaynak

[1] Deeplearning.ai, (2024), Building Agentic Rag with Llamaindex:

[https://learn.deeplearning.ai/courses/building-agentic-rag-with-llamaindex]

--

--

Cahit Barkin Ozer
Cahit Barkin Ozer

Written by Cahit Barkin Ozer

Üretken YZ başta olmak üzere teknoloji alanındaki yenilikleri öğrenip sizlerle paylaşıyorum. Youtube Kanalım: https://www.youtube.com/@cbarkinozer

No responses yet