Spaces:
Sleeping
Sleeping
| 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 Agentic 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("API 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.") | |