File size: 3,510 Bytes
00c776f 122fef6 00c776f 122fef6 00c776f 122fef6 00c776f 122fef6 00c776f | 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 | # app.py β Entry point for HF Spaces
import os
import gradio as gr
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode, tools_condition
from langgraph.graph.message import add_messages
from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
from langchain_groq import ChatGroq
from langchain_community.tools import DuckDuckGoSearchRun
from langchain_core.tools import tool
import requests
os.environ["GROQ_API_KEY"] = os.getenv("GROQ_API_KEY")
# βββ LLM βββββββββββββββββββββββββββββββββ
llm = ChatGroq(
model="llama-3.1-8b-instant",
max_tokens=300,
temperature=0
)
# βββ Tools βββββββββββββββββββββββββββββββ
@tool
def search(query: str) -> str:
"""Search the web for current information."""
return DuckDuckGoSearchRun().run(query)
@tool
def calculator(first_num: float, second_num: float, operation: str) -> dict:
"""Perform basic arithmetic. Operations: add, sub, mul, div"""
ops = {"add": first_num + second_num, "sub": first_num - second_num,
"mul": first_num * second_num}
if operation == "div":
return {"result": "Division by zero" if second_num == 0 else first_num / second_num}
return {"result": ops.get(operation, f"Unknown operation: {operation}")}
@tool
def get_stock_price(symbol: str) -> dict:
"""Fetch latest stock price for a symbol like AAPL or TSLA."""
url = f"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol={symbol}&apikey={os.getenv('STOCKS_API_KEY')}"
return requests.get(url).json()
tools = [search, calculator, get_stock_price]
llm_with_tools = llm.bind_tools(tools)
# βββ State βββββββββββββββββββββββββββββββ
class ChatState(TypedDict):
messages: Annotated[list[BaseMessage], add_messages]
# βββ Graph βββββββββββββββββββββββββββββββ
def chat_node(state: ChatState):
"""LLM node that may answer or request a tool call."""
messages = state['messages']
response = llm_with_tools.invoke(messages)
return {"messages": [response]}
graph = StateGraph(ChatState)
graph.add_node("chat_node", chat_node)
graph.add_node("tools", ToolNode(tools))
graph.add_edge(START, "chat_node")
graph.add_conditional_edges("chat_node", tools_condition)
graph.add_edge("tools", "chat_node")
agent = graph.compile()
# βββ Gradio UI βββββββββββββββββββββββββββ
def respond(message, history):
# Convert Gradio history β LangChain messages
messages = []
for user_msg, bot_msg in history:
messages.append(HumanMessage(content=user_msg))
if bot_msg:
messages.append(AIMessage(content=bot_msg))
messages.append(HumanMessage(content=message))
result = agent.invoke({"messages": messages})
return result["messages"][-1].content
demo = gr.ChatInterface(
fn=respond,
title="π AI Research Agent",
description="Ask me anything β I can search the web and do calculations!",
examples=[
"What is LangGraph?",
"What's happening in AI news today?",
"Calculate 128 multiplied by 37",
],
cache_examples=False # π₯ ADD THIS
)
if __name__ == "__main__":
demo.launch() |