""" Kripto & Doviz Tool-Calling Asistani ------------------------------------ Kullanici dogal dille soru sorar; model CoinGecko API'sini tool calling ile kullanarak yanit uretir. Arka planda cagrilan her tool ve donen veri kullaniciya adim adim gosterilir. """ import os import json import spaces import gradio as gr from huggingface_hub import InferenceClient from tools import TOOLS, TOOL_FUNCS # --- Model --- MODEL_ID = "Qwen/Qwen2.5-72B-Instruct" client = InferenceClient(model=MODEL_ID, token=os.environ.get("HF_TOKEN")) SYSTEM_PROMPT = ( "Sen kripto para ve doviz konusunda yardimci bir asistansin. " "Kullanicinin sorusunu yanitlamak icin sana verilen araclari (tool) kullan. " "Guncel fiyat ya da donusum gerektiginde mutlaka ilgili araci cagir; tahmin etme. " "Birden fazla bilgi gerekiyorsa gereken tum araclari cagir. " "Sonucu Turkce, kisa ve net bir cumleyle acikla." ) MAX_TURNS = 5 @spaces.GPU def tool_calling_yanit(user_msg, history): """ Model ile cok turlu tool-calling dongusu yurutur. history: [(kullanici, bot), ...] seklinde (gradio ChatInterface klasik format). Doner: string yanit (arka plan adimlariyla birlikte). """ messages = [{"role": "system", "content": SYSTEM_PROMPT}] for h in (history or []): # Gradio surumune gore history iki formatta gelebilir: # 1) {"role": "...", "content": "..."} (yeni "messages" formati) # 2) (kullanici, bot) ikilisi (eski "tuples" formati) if isinstance(h, dict): rol = h.get("role") icerik = h.get("content") if rol in ("user", "assistant") and icerik: messages.append({"role": rol, "content": icerik}) elif isinstance(h, (list, tuple)) and len(h) == 2: kullanici, bot = h if kullanici: messages.append({"role": "user", "content": kullanici}) if bot: messages.append({"role": "assistant", "content": bot}) messages.append({"role": "user", "content": user_msg}) adimlar = [] for turn in range(1, MAX_TURNS + 1): try: resp = client.chat_completion( messages=messages, tools=TOOLS, tool_choice="auto", temperature=0.2, max_tokens=700, ) except Exception as e: return f"Model cagrisinda hata olustu: {e}" msg = resp.choices[0].message tool_calls = getattr(msg, "tool_calls", None) if not tool_calls: final = msg.content or "" if adimlar: arka = "\n".join(adimlar) return f"{final}\n\n---\n**Arka planda yapilan islemler:**\n```\n{arka}\n```" return final messages.append({ "role": "assistant", "content": msg.content or "", "tool_calls": [ { "id": tc.id, "type": "function", "function": {"name": tc.function.name, "arguments": tc.function.arguments}, } for tc in tool_calls ], }) adimlar.append(f"[Turn {turn}] Arac Cagrilari:") for tc in tool_calls: fname = tc.function.name try: fargs = json.loads(tc.function.arguments) if isinstance(tc.function.arguments, str) else tc.function.arguments except Exception: fargs = {} arg_str = ", ".join(f"{k}={v!r}" for k, v in fargs.items()) adimlar.append(f" -> {fname}({arg_str})") func = TOOL_FUNCS.get(fname) if func is None: result = {"error": f"Bilinmeyen arac: {fname}"} else: try: result = func(**fargs) except Exception as e: result = {"error": str(e)} adimlar.append(f" <- {json.dumps(result, ensure_ascii=False)}") messages.append({ "role": "tool", "tool_call_id": tc.id, "name": fname, "content": json.dumps(result, ensure_ascii=False), }) adimlar.append("") return "Islem cok fazla adim gerektirdi, tamamlanamadi. Lutfen soruyu sadelestirin." ORNEKLER = [ "Bitcoin su an kac dolar?", "1 Ethereum kac TL eder?", "Bitcoin mi daha pahali Ethereum mi?", "500 dolar kac bitcoin eder?", "5000 TL ile kac Ethereum alabilirim?", ] demo = gr.ChatInterface( fn=tool_calling_yanit, title="Kripto & Doviz Tool-Calling Asistani", description=( "Dogal dille kripto/doviz sorusu sorun. Model, CoinGecko API'sini " "tool calling ile kullanarak yanit verir ve arka planda cagirdigi " "araclari adim adim gosterir." ), examples=ORNEKLER, ) if __name__ == "__main__": demo.launch()