LangChain Agent'ın temel fikri, LLM'i otomatik olarak düşünmek, karar vermek ve farklı eylemleri gerçekleştirmek için bir beyin olarak kullanmaktır, sonunda hedef görevlerimizi başarmaktır.
İpucu: Bir geliştirme perspektifinden, bu, önceden çeşitli API'ler geliştirip ardından Ajan'a bir görev vererek, LLM'in görevi tamamlamak için hangi API'yi çağıracağını analiz etmesine izin veriyor.
LangChain Agent'ın çözmeyi amaçladığı sorunu daha iyi anlamak için bir örnek düşünelim.
Örneğin:
"Docker'ın üretim dağıtım çözümü olarak kullanılıp kullanılamayacağını" araştırmak istiyorsak, öncelikle Baidu'da "Docker'a giriş" ararız, arama sonuçlarını gözden geçirir ve ardından "Docker dağıtımının avantajları ve dezavantajları" gibi daha fazla arama yaparız ve sonuçları gözden geçiririz; ve böyle devam ederiz, sonunda bir sonuca varana kadar.
LangChain Agent bu süreci simüle etmeyi amaçlar. Bir dizi aracı (örneğin, Baidu araması, URL içerik çıkarma araçları) önceden paketleyebilirim, ardından Ajan'a "Docker'ın üretim dağıtım çözümü olarak kullanılabilir mi?" gibi bir hedef görev veririm. Ajan daha sonra LLM'i çağırmak için ipuçları oluşturur. Bu görevi yerine getirmek için bir sonraki adım hangi eylemi (yani hangi aracı çağıracağı) gerçekleştirecek. Yapay zeka çağrılacak aracı döndürecek, kod bu aracı yürütecek, ardından araç yürütme sonuçlarını geri götürecek ve bir sonraki adımda hangi aracı çalıştıracağını soracak. Bu süreci tekrarlayarak önceden bahsedilen görev tamamlanacaktır.
İpucu: GPT modelinin piyasaya sürülmesinden bu yana, bu patlayıcı bir yetenek, LLM'in bir beyin gibi hareket etmesine izin veriyor ve daha önce geliştirdiğimiz çeşitli API'leri çağırabiliyor. Bu LLM'in yeteneklerini büyük ölçüde artırıyor. Şu anda bu özellik hala deneysel aşamada ve LLM'e sürekli olarak çağrılacak, bu nedenle oldukça fazla jeton tüketiyor. Bir görevi tamamlamak birkaç dakikada on binlerce jeton harcayabilir. Paranızı kurtarmak istiyorsanız, öncelikle LLM'in basit mantıksal görevleri yerine getirmesini öneririz.
Temel Konseptler
Şimdi ilgili bileşenleri ve kavramları tanıtalım.
Ajan
Bir Ajan, kararlar almak için bizim adımıza hareket eden yardımcımız olarak anlaşılabilir. LangChain Agent'ın altta yatan uygulamasında, bir sonraki eylem (veya API çağrısı) LLM tarafından belirlenir. ReAct modu, yapay zeka karar verme sürecini açıklar. Bu konuda daha fazla bilgi edinmek isteyenler derinlemesine araştırma yapabilir.
LangChain, farklı senaryolar için çeşitli tiplerde Ajan sağlar.
Araçlar
Araçları, LLM'nin yeteneklerini genişletmek için tasarlanmış çeşitli işlevsel API'lerle önceden paketlenmiş olarak daha iyi anlıyorum. LLM, belirli bir görevi tamamlamak için hangi belirli API'nin çağrılacağını belirler.
Araç Setleri
Araç setleri genellikle LLM'ye yalnızca bir veya iki araç değil, daha fazla seçenek sunarak görevleri tamamlarken daha fazla seçenek sağlar.
AgentExecutor
Proxy yürütücüsü, LLM tarafından seçilen aracı (API) çalıştırmaktan sorumludur. Bu çalıştırma için, sözde kod aşağıdaki gibidir:
next_action = agent.get_action(...)
while next_action != AgentFinish:
observation = run(next_action)
next_action = agent.get_action(..., next_action, observation)
return next_action
Yürütme süreci karmaşık olmasa da, yürütücü, esasen şunları içeren birçok detaylı konuyla ilgilenir:
- Ajanın mevcut olmayan bir araç seçtiği durumları ele almak
- Araç hata durumlarını ele almak
- Ajanın, bir araç çağrısı olarak çözümlenemeyen bir çıktı ürettiği durumlar
- Hata ayıklama sorunları.
Hızlı Başlangıç
Bu bölüm, LangChain'in Ajanının temel kullanımını tanıtır.
1. LLM'yi Yükle
Öncelikle, Ajanı kontrol etmek için kullanacağımız dil modelini (LLM) yükleyelim.
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
2. Araçları Tanımla
Sonra, Ajanın çağırması için bazı araçları tanımlayalım. Giriş kelimenin uzunluğunu hesaplamak için çok basit bir Python işlevi yazacağız.
from langchain.agents import tool
@tool
def get_word_length(word: str) -> int:
"""Kelimenin uzunluğunu döndürür."""
return len(word)
get_word_length.invoke("abc")
Not: İşlev yorumları çok önemlidir. LLM'e hangi sorunu çözebileceğini çağırarak anlatırlar.
get_word_length
işlevi, LLM'e bir kelimenin uzunluğunu hesaplayabileceğini söyler.
3
Araçları bir set olarak tanımlayın
tools = [get_word_length]
3. Bir İstekte Bulunun
Şimdi bir istekte bulunalım. OpenAI Function Calling, araç kullanımı için optimize edildiği için mantık veya çıktı formatı hakkında neredeyse hiç talimata ihtiyacımız yok. Sadece iki giriş değişkenine ihtiyacımız var: input
ve agent_scratchpad
. input
, kullanıcının giriş sorusunu temsil eder ve agent_scratchpad
, aracın çağrı talimatları için yer tutucudur ve araç çağrısı komutunu çalıştırırken prompt şablonuna eklenecektir.
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages(
[
(
"sistem",
"Çok güçlü bir asistanssın ama mevcut durumu anlamıyorsun.",
),
("kullanıcı", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
]
)
4. Araçları LLM'ye Bağlama
Ajan, hangi araçları kullanabileceğini nasıl bilecek?
Bu, OpenAI araç çağrısı özelliğine dayanmaktadır (birçok model benzer özellikleri destekler). Modeli tanımlanmış araç çağrı formatı hakkında bilgilendirmemiz yeterlidir.
llm_with_tools = llm.bind_tools(tools)
5. Ajan Oluşturma
Önceki içeriği entegre ettiğimize göre, proxy programını oluşturmaya devam edebiliriz. Son iki pratik yardımcı fonksiyonu içe aktaracağız: biri ara adımları (proxy eylemleri, araç çıktıları) giriş mesajlarına biçimlendirmek için, diğeri ise çıktı mesajlarını proxy eylemlerine/sonlandırmaya dönüştürmek için.
from langchain.agents.format_scratchpad.openai_tools import format_to_openai_tool_messages
from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser
agent = (
{
"input": lambda x: x["input"],
"agent_scratchpad": lambda x: format_to_openai_tool_messages(x["intermediate_steps"]),
}
| prompt
| llm_with_tools
| OpenAIToolsAgentOutputParser()
)
Ajan yürütücüsünü tanımlama
from langchain.agents import AgentExecutor
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
Proxy programının çalıştırılmasını bir örnek üzerinden gösterelim:
list(agent_executor.stream({"input": "'eudca' kelimesinde kaç harf var?"}))
Ajan çıktı günlüğü örneği
> Yeni bir ajan yürütme zincirine giriliyor...
Çağrı: `kelime_uzunluğunu_al` fonksiyonu, `{'word': 'educa'}` parametresiyle çalıştırılıyor.
"educa" kelimesinde 5 harf bulunmaktadır.
> Yürütme zinciri tamamlandı.
Bu örnek üzerinden, proxy programının tamamlanmış sürecini gösterdik.
Ajan'a Hafıza İşlevselliği Ekleme
Eğer ajanın önceki sohbetleri hatırlamasını istiyorsak, aslında oldukça basittir: sadece AI tarafından döndürülen içeriği prompt'a eklememiz ve birlikte AI'ya sunmamız gerekir.
Prompt şablonunu değiştirme
Aşağıda, bir sohbet geçmişi şablon değişkenini içerecek şekilde prompt şablonunu değiştiriyoruz.
from langchain.prompts import MessagesPlaceholder
MEMORY_KEY = "sohbet_geçmişi"
prompt = ChatPromptTemplate.from_messages(
[
(
"sistem",
"Harika bir asistanssın, ama kelimelerin uzunluğunu hesaplama konusunda iyi değilsin.",
),
MessagesPlaceholder(variable_name=MEMORY_KEY),
("kullanıcı", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
]
)
Ajan süreci tanımını değiştirme
Ajan süreci tanımını değiştirerek, prompt şablonuna sohbet geçmişi verisi sağlayacak şekilde ajan süreci tanımını değiştiriyoruz, aşağıdaki kodda chat_history
parametresi işlenmektedir.
agent = (
{
"input": lambda x: x["input"],
"agent_scratchpad": lambda x: format_to_openai_tool_messages(
x["intermediate_steps"]
),
"chat_history": lambda x: x["chat_history"],
}
| prompt
| llm_with_tools
| OpenAIToolsAgentOutputParser()
)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
chat_history = []
input1 = "Kelimenin 'educa' kaç harfi var?"
result = agent_executor.invoke({"input": input1, "chat_history": chat_history})
chat_history.extend(
[
HumanMessage(content=input1),
AIMessage(content=result["output"]),
]
)
agent_executor.invoke({"input": "Bu kelime gerçekten var mı?", "chat_history": chat_history})