GİRDİ BAŞLIK:
Building a Proper Backend for My LangGraph AI Agent
GİRDİ İÇERİK:
In the first two articles of this series, I built a stateful LangGraph agent that handles a 15-minute booking process and wrapped it up with a Streamlit UI to improve user experience.
The agent handles the entire booking process like a real customer service representative. It’s a LangGraph-based agent that orchestrates the following operations:
Responds to customer queries and understands their needs.
Calculates the price for the service and informs the customer.
Handles the customer’s acceptance or rejection.
Proposes optimized time slots.
Confirms and records the appointment.
The next phase is to build a proper backend, starting with implementing a Postgres database instead of keeping everything in memory. We’re retaining Streamlit as the user interface and replacing the in-memory adapters with PostgreSQL. This will also allow us to have multiple fronts (e.g., WhatsApp, Streamlit) that share the same backend, effectively turning this into a proper product for real business use. The full source code of this project is available on GitHub at customer-service-agent. Feel free to clone the repo and test it yourself.
Mevcut Durum: Hafıza İçi Veritabanı
Şu anda, sistemin “veritabanı” olarak kullandığı yapı, sadece bellekte tutulan Python nesnelerinden oluşuyor. Bu yapının iki temel bileşeni bulunuyor:
1. LangGraph Checkpointer: Bu, LangGraph’ın durumunu her adımda kaydeden bir mekanizmadır. Grafik derlendiğinde, konuşma durumu bellekte saklanır.
2. Python Listesi (Rezervasyonlar): Onaylanmış rezervasyonlar, kilitleme mekanizmasıyla korunan bir Python listesinde tutulur.
Bu yapı, başlangıçtaki testler ve demolar için yeterli olsa da, bazı önemli sınırlamaları beraberinde getiriyor:
Geçicilik: Sistem yeniden başlatıldığında, tüm veriler (konuşma durumları ve rezervasyonlar) kayboluyor.
Yalıtım: Her süreç kendi kopyasına sahip olduğu için, farklı kullanıcıların yaptığı rezervasyonlar birbiriyle senkronize değil. Bu da hatalara yol açabiliyor.
Neden Daha İyi Bir Veritabanına İhtiyacımız Var?
Mevcut sistemin bu sınırlamaları nedeniyle, gerçek bir ürün olarak kullanmak mümkün değil. Örneğin, aynı anda birden fazla kullanıcı rezervasyon yapıyorsa, çakışmalar yaşanabilir veya eski veriler gösterilebilir. Bu da müşteri memnuniyetini olumsuz etkileyebilir.
Bu nedenle, daha güvenilir ve ölçeklenebilir bir çözüm olan PostgreSQL veritabanını kullanmaya karar verdik. PostgreSQL, açık kaynaklı bir ilişkisel veritabanı sistemidir ve rezervasyonlar ile teknik bilgiler için ayrı tablolar oluşturmamızı sağlar.
PostgreSQL Uygulaması: Protokol Tanımı
PostgreSQL’e geçmeden önce, grafik ve motorların belirli bir veritabanına (PostgreSQL veya bellek içi) bağımlı olmaması için bir protokol tanımladık. Bu protokol, `BookingRepository` adında bir arayüz tanımlar ve aşağıdaki metotları içerir:
`technicians`: Teknik bilgileri içeren sözlük.
`list_bookings()`: Mevcut rezervasyonların listesini döndürür.
`create_booking()`: Yeni bir rezervasyonu oluşturur ve veritabanına kaydeder.
Bu sayede, hem PostgreSQL’i kullanırken hem de test amaçlı bellek içi çözümü kullanırken aynı arayüz üzerinden işlem yapabiliriz.
PostgreSQL Uygulaması: Veritabanı Şeması
PostgreSQL kurulumunda, iki ana tablo oluşturulmuştur:
1. technicians: Teknik bilgileri içerir (ID, isim, uzmanlık alanı vb.).
2. bookings: Rezervasyon bilgilerini içerir (rezervasyon ID, müşteri bilgileri, tarih/saat, teknik ID vb.).
Bu tablolar arasındaki ilişkiler sayesinde, rezervasyonların hangi teknik tarafından yapıldığını kolayca belirleyebiliriz.
PostgreSQL Uygulaması: `BookingRepository` Sınıfı
`BookingRepository` sınıfı, veritabanıyla etkileşimi sağlayan temel bileşenlerdir. Bu sınıflar, yukarıda tanımlanan protokolü uygular ve aşağıdaki metotları içerir:
`technicians`: Teknik bilgileri içeren sözlüğü döndürür.
`list_bookings()`: Mevcut rezervasyonların listesini döndürür.
`create_booking()`: Yeni bir rezervasyonu oluşturur ve veritabanına kaydeder.
Uygulama Süreci: `create_persistence()` Metodu
Uygulama sürecinde, `create_persistence()` metodu kullanılarak hangi çözümün kullanılacağına karar verilir. Bu metoda `DATABASE_URL` değişkeni ayarlandığında, hem rezervasyonlar hem de LangGraph durumu PostgreSQL’de saklanır. Aksi takdirde, bellek içi çözümler kullanılır.
Mimari: `AgentState` ve Veritabanı Etkileşimi
Uygulamada, `AgentState` nesnesi, konuşma sırasında kullanılan çalışma belleğini temsil eder. Bu nesne, her adımda güncellenir ve LangGraph tarafından birleştirilir. PostgreSQL kullanıldığında, bu nesnenin durumu checkpointer ile kaydedilir.
Sadece iki bileşen veritabanıyla doğrudan etkileşimde bulunur:
1. `generate_schedule_options_node`: Müsait zaman dilimlerini hesaplamak için `repository.list_bookings()` metodunu kullanarak mevcut rezervasyonları listeler.
2. `confirm_booking_node`: Onaylanan rezervasyonu kaydetmek için `repository.create_booking()` metodunu kullanır.
Diğer bileşenler, sadece `AgentState` nesnesini okur veya günceller.
Örnek Senaryo: Rezervasyon Süreci
1. Müşteri, uygun bir zaman dilimi belirlemek için `generate_schedule_options_node` ile etkileşime girer. Bu aşamada, mevcut rezervasyonlar listelenir ve müsait zaman dilimleri hesaplanır.
2. Müşteri, uygun bir zaman dilimini seçtikten sonra, `select_slot_node` tarafından bu seçim kaydedilir.
3. Müşteri, rezervasyonu onayladığında, `confirm_booking_node` tarafından rezervasyon veritabanına kaydedilir ve müşteriye onay mesajı gönderilir.
Bu süreçte, LangGraph, tüm bilgileri `AgentState` nesnesinde birleştirir ve müşteriye tutarlı bir deneyim sunar.
Sonuç:
Bu makalede, mevcut sistemdeki sınırlamaları ele aldık ve daha güvenilir ve ölçeklenebilir bir çözüm olan PostgreSQL veritabanını nasıl uyguladığımızı anlattım. Bir sonraki adımda, Docker kullanarak bu kurulumu nasıl test edebileceğinizi ve aynı uygulamayı farklı ortamlarda (örneğin, WhatsApp veya Streamlit) nasıl kullanabileceğinizi göstereceğim.
Bu Gelişmeyi Toplulukta Değerlendirin
Haber hakkındaki düşüncelerinizi, donanım deneyimlerinizi ve teknik sorularınızı topluluk üyeleriyle anlık olarak tartışın.
Bir yanıt yazın