File size: 6,223 Bytes
0872fe3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
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.")
|