agent_1 / app.py
CananD's picture
Upload app.py
0872fe3 verified
import streamlit as st
import openai
import re
from duckduckgo_search import DDGS
# --- Araçların Tanımlanması ---
def search_tool(query: str):
"""A web search tool that uses DuckDuckGo to find information."""
st.write(f"🔎 Web'de aranıyor: `{query}`")
try:
with DDGS() as ddgs:
results = [r for r in ddgs.text(query, max_results=5)]
return "\n".join(results) if results else "Aramada sonuç bulunamadı."
except Exception as e:
return f"Arama sırasında bir hata oluştu: {e}"
def calculator_tool(expression: str):
"""A calculator tool that evaluates a mathematical expression."""
st.write(f"🧮 Hesaplama yapılıyor: `{expression}`")
try:
# Güvenlik için sadece güvenli karakterlere izin ver
if not re.match(r"^[0-9+\-*/.() \t]+$", expression):
return "Geçersiz karakterler içerdiği için hesaplama yapılamadı."
result = eval(expression)
return f"Sonuç: {result}"
except Exception as e:
return f"Hesaplama hatası: {e}"
# --- LLM (Büyük Dil Modeli) İstek Fonksiyonu ---
def call_llm(prompt, api_key):
"""Calls the OpenAI API to get the agent's next thought and action."""
openai.api_key = api_key
try:
response = openai.chat.completions.create(
model="gpt-4o", # veya "gpt-3.5-turbo"
messages=[{"role": "user", "content": prompt}],
temperature=0.0,
max_tokens=500,
)
return response.choices[0].message.content
except Exception as e:
st.error(f"OpenAI API çağrısı sırasında hata: {e}")
return None
# --- Ana Ajan Döngüsü ---
def run_agent_loop(goal, api_key):
"""Runs the main ReAct (Reason-Act) agent loop."""
# Ajanın nasıl çalışacağını açıklayan ana prompt (talimat)
system_prompt_template = f"""
Sen, bir amaca ulaşmak için adım adım düşünen ve araçları kullanan bir AI ajanısın.
Her adımda, amacına yönelik bir 'Düşünce' ve bu düşünceyi hayata geçirecek bir 'Eylem' üretmelisin.
Kullanabileceğin araçlar şunlardır:
1. `search(sorgu)`: İnternette arama yapmak için kullanılır. Örneğin: `search(Türkiye'nin başkenti)`
2. `calculator(ifade)`: Matematiksel bir ifadeyi hesaplamak için kullanılır. Örneğin: `calculator(100 * (3 + 5))`
3. `finish(cevap)`: Görevi tamamladığında ve nihai cevabı bulduğunda kullanılır. Örneğin: `finish(Ankara, Türkiye'nin başkentidir.)`
Süreç şu şekilde işler:
1. Amacı analiz edersin.
2. Bir 'Düşünce' oluşturursun.
3. Bir 'Eylem' seçersin.
4. Ben sana 'Gözlem' olarak eylemin sonucunu veririm.
5. Amaca ulaşana kadar 2-4 adımlarını tekrarlarsın.
Amacımız: "{goal}"
Şimdi, ilk Düşünce ve Eylemini yaz.
"""
history = [system_prompt_template]
max_steps = 10
for step in range(max_steps):
st.write("---")
st.info(f"🚀 Adım {step + 1}")
prompt = "\n".join(history)
with st.spinner("Ajan düşünüyor..."):
response = call_llm(prompt, api_key)
if not response:
st.error("Ajan bir yanıt üretemedi. Lütfen API anahtarınızı kontrol edin veya tekrar deneyin.")
break
# LLM'in ürettiği Düşünce ve Eylemi ayıkla
try:
thought = re.search(r"Düşünce: (.*?)\n", response, re.DOTALL).group(1).strip()
action_full = re.search(r"Eylem: (.*?)$", response, re.DOTALL).group(1).strip()
except AttributeError as e:
st.error("Ajan geçerli bir 'Düşünce' veya 'Eylem' formatı üretmedi.")
st.write(response) # Hata mesajı ve yanıtı tam olarak görmek için
break
with st.expander("🤖 Ajanın Düşünce Süreci", expanded=True):
st.markdown(f"**Düşünce:** {thought}")
st.markdown(f"**Eylem:** `{action_full}`")
# Eylemi formatına göre ayıklama
action_name_match = re.match(r"(\w+)\((.*)\)", action_full)
if not action_name_match:
st.error(f"Geçersiz eylem formatı: {action_full}")
break
action_name = action_name_match.group(1)
action_input = action_name_match.group(2).strip(' "')
# Eylemi gerçekleştir ve gözlemi al
observation = ""
if action_name == "search":
observation = search_tool(action_input)
elif action_name == "calculator":
observation = calculator_tool(action_input)
elif action_name == "finish":
st.success(f"✅ Ajan görevi tamamladı!")
st.balloons()
st.markdown("### Nihai Cevap:")
st.write(action_input)
break
else:
observation = f"Bilinmeyen eylem: {action_name}. Lütfen `search`, `calculator` veya `finish` kullanın."
st.warning(f"**Gözlem:**\n{observation}")
# Geçmişi güncelle
history.append(response)
history.append(f"Gözlem: {observation}")
else:
st.error("Ajan maksimum adım sayısına ulaştı ama görevi tamamlayamadı.")
# --- Streamlit Arayüzü ---
st.set_page_config(page_title="AI Agent App", page_icon="🤖")
st.title("🤖 AI Agent Uygulaması")
st.markdown("""
Bu uygulama, bir amaca ulaşmak için **ReAct (Reason + Act)** mantığıyla çalışan bir AI ajanıdır.
Ajan, hedefe ulaşmak için **düşünür**, **araçlar kullanır** (web araması, hesap makinesi) ve sonuçları **gözlemler**.
""")
st.sidebar.header("Yapılandırma")
api_key = st.sidebar.text_input("OpenAI API Anahtarınız", type="password", help="API anahtarınız asla saklanmaz.")
st.header("Ajanın Amacını Belirleyin")
goal = st.text_input(
"Amaç:",
placeholder="Örnek: 'Matrix filminin başrol oyuncusunun bugünkü yaşı kaçtır ve bu yaşın karekökü nedir?'"
)
if st.button("Ajanı Başlat", disabled=(not api_key or not goal)):
if api_key and goal:
run_agent_loop(goal, api_key)
else:
st.warning("Lütfen OpenAI API anahtarınızı ve bir amaç girin.")