File size: 4,585 Bytes
dff38d3
 
 
48a1360
dff38d3
 
 
 
 
 
 
 
48a1360
dff38d3
133f029
dff38d3
 
 
 
 
 
 
 
 
 
48a1360
dff38d3
 
 
 
 
48a1360
dff38d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
01babb7
dff38d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
01babb7
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
import os
import requests
import gradio as gr

# --- CORRECTED LANGCHAIN IMPORTS ---
# create_react_agent and AgentExecutor are now imported directly from langchain.agents
from langchain.agents import AgentExecutor, create_react_agent
from langchain.tools import Tool
# We need to import the specific ReAct prompt template from the hub
from langchain import hub 
from langchain_google_genai import ChatGoogleGenerativeAI
from typing import List, Dict # Added for Gradio ChatInterface typing

# --- Configuration and Environment Setup ---

# IMPORTANT: Do NOT hardcode your API key.
# Define GEMINI_API_KEY as a Space Secret in your Hugging Face Space Settings.
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")

if not GEMINI_API_KEY:
    # This message helps the user set up their Hugging Face Space correctly
    print("WARNING: GEMINI_API_KEY environment variable not set. Running without API key.")
    # We will raise a value error later during LLM initialization if it's actually needed.

# Initialize Gemini LLM
try:
    llm = ChatGoogleGenerativeAI(
        model="gemini-2.5-flash",
        temperature=0.3,
        google_api_key=GEMINI_API_KEY
    )
except Exception as e:
    # Graceful exit if API key is missing during initialization
    raise RuntimeError(
        "Could not initialize ChatGoogleGenerativeAI. "
        "Ensure GEMINI_API_KEY is set as a Space Secret."
    ) from e

# --- Tool Definition ---

def get_crypto_price(symbol: str) -> str:
    """Fetches the current price of a cryptocurrency symbol."""
    try:
        # Use lowercase symbol for CoinGecko API lookup
        lookup_symbol = symbol.lower()
        url = f"https://api.coingecko.com/api/v3/simple/price?ids={lookup_symbol}&vs_currencies=usd"
        res = requests.get(url).json()
        
        # Check if the symbol exists in the response
        price = res.get(lookup_symbol, {}).get('usd')
        
        if price:
            return f"💰 The current price of {symbol.capitalize()} is ${price:,.2f}"
        else:
            # Check for common partial matches as suggestions
            if not res and len(lookup_symbol) > 3:
                 return f"❌ Could not find price for symbol '{symbol}'. Try the full name (e.g., 'bitcoin', 'ethereum')."
            return f"❌ Could not find price for symbol '{symbol}'."
            
    except Exception as e:
        return f"⚠️ Error fetching price: {str(e)}"

# Create a Tool for the Agent
crypto_tool = Tool(
    name="Crypto Price Checker",
    func=get_crypto_price,
    description="Fetches the current cryptocurrency price using CoinGecko. Use this tool ONLY when the user asks for a specific crypto price (e.g., 'bitcoin', 'ethereum')."
)

# List of tools
tools = [crypto_tool]

# --- Agent Initialization (CORRECTED) ---

# 1. CORRECTED PROMPT: Pull the standard ReAct prompt from LangChain Hub.
# This prompt is guaranteed to have the required '{tools}' and '{tool_names}' variables.
prompt = hub.pull("hwchase17/react")

# 2. Create the Agent
# This uses the corrected 'create_react_agent' import
agent = create_react_agent(llm, tools, prompt)

# 3. Create the Agent Executor
# This uses the corrected 'AgentExecutor' import
agent_executor = AgentExecutor(
    agent=agent, 
    tools=tools, 
    verbose=True,
    handle_parsing_errors=True # Good practice for ReAct agents
)

# --- Gradio Interface Function ---

# Added 'history' for ChatInterface compatibility
def run_agent(user_query: str, history: List[List[str]]) -> str:
    """The main function called by Gradio to run the agent."""
    if not user_query:
        return "Please enter a question for the agent."

    try:
        # Use the AgentExecutor's invoke method
        # The input must be a dictionary
        response: Dict = agent_executor.invoke({"input": user_query})
        
        # Extract the final answer text
        return response.get("output", "Agent could not find a clear answer.")
        
    except Exception as e:
        # Catch and report any runtime errors gracefully
        return f"An error occurred while running the agent: {str(e)}"

# --- Gradio App Setup (Using ChatInterface for better UX) ---

gr.ChatInterface(
    fn=run_agent,
    title="💰 Gemini Crypto Price Agent (ReAct Pattern)",
    description="Ask the agent to check the current price of cryptocurrencies (e.g., bitcoin, ethereum). This agent uses the modern LangChain ReAct pattern (v0.1.0+).",
    examples=[
        ["What is the current price of Bitcoin?"],
        ["How much is Ethereum?"],
        ["What about solana?"]
    ]
).launch()