| import streamlit as st |
| import openai |
| import re |
| from duckduckgo_search import DDGS |
|
|
|
|
|
|
| |
|
|
| 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: |
| |
| 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}" |
|
|
| |
|
|
| 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", |
| 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 |
|
|
| |
|
|
| def run_agent_loop(goal, api_key): |
| """Runs the main ReAct (Reason-Act) agent loop.""" |
| |
| |
| 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 |
|
|
| |
| 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) |
| break |
| |
| with st.expander("🤖 Ajanın Düşünce Süreci", expanded=True): |
| st.markdown(f"**Düşünce:** {thought}") |
| st.markdown(f"**Eylem:** `{action_full}`") |
|
|
| |
| 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(' "') |
|
|
| |
| 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}") |
| |
| |
| 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ı.") |
|
|
|
|
| |
|
|
| 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.") |
|
|