File size: 5,443 Bytes
80654a3
 
 
 
 
 
 
 
 
 
 
 
7b7d3f1
80654a3
 
047bb2e
80654a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169fb9d
80654a3
 
 
 
 
 
169fb9d
50cc36f
 
169fb9d
50cc36f
 
 
 
 
 
 
 
 
169fb9d
 
50cc36f
 
b966ce1
 
169fb9d
80654a3
 
50cc36f
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import os, datetime, math, numexpr, logging, requests, uuid
import gradio as gr

from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_google_genai import GoogleGenerativeAIEmbeddings
from langchain_core.documents import Document
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains import create_retrieval_chain
from langchain_core.tools import StructuredTool
from langchain_core.messages import SystemMessage, HumanMessage
from langchain.prompts import PromptTemplate, HumanMessagePromptTemplate, ChatPromptTemplate, SystemMessagePromptTemplate
from langchain_community.vectorstores import FAISS

# === SETUP ===
GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")

# === LLM ===
llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash")

# === TOOLS ===
def dani_drinks() -> str:
    """Dani's favorite drinks info on beers, wine and water."""
    return (
    "Dani's favourite drinks:\n"
    "Beers: Peroni (better if 33cl), Moretti, Ichnusa (unfiltered)\n"
    "Wine: Red fruity, White cold only, No Rosè\n"
    "Water: Normal or sparkling, only cold\n"
    )

def calculator(expression: str) -> str:
    """Math calculations."""
    local_dict = {"pi": math.pi, "e": math.e}
    result = str(numexpr.evaluate(expression.strip(), local_dict=local_dict))
    return result

# Nuovo Weather Tool
def weather_tool(location: str) -> str:
    """Return current weather for the given city name using Open‑Meteo APIs."""
    # 1. Geocoding: city → lat, lon
    geocode = requests.get(
        "https://geocoding-api.open-meteo.com/v1/search",
        params={"name": location, "count": 1}
    )
    geo_json = geocode.json()
    if not geo_json.get("results"):
        return f"Non ho trovato la città '{location}'. Riprova."

    first = geo_json["results"][0]
    lat = first["latitude"]
    lon = first["longitude"]
    name = first.get("name")
    country = first.get("country", "")
    
    # 2. Current weather
    weather_resp = requests.get(
        "https://api.open-meteo.com/v1/forecast",
        params={
            "latitude": lat,
            "longitude": lon,
            "current_weather": True,
            "timezone": "auto"
        }
    )
    w = weather_resp.json().get("current_weather")
    if not w:
        return f"Meteo non disponibile per {location}."

    temp = w.get("temperature")
    wind = w.get("windspeed")
    return (f"Meteo attuale a {name}, {country}: {temp}°C, vento {wind} km/h")

# === RETRIEVAL TOOL VIA FAISS ===
# create mock docs and embed
docs = [
    Document(page_content="Milan was founded in 1900."),
    Document(page_content="Inter was founded in 1950."),
    Document(page_content="Juve was founded in 1920."),
    Document(page_content="Torino was founded in 1910."),
]
embeddings = GoogleGenerativeAIEmbeddings(model="models/text-embedding-004")
vector_db = FAISS.from_documents(docs, embeddings)
retriever = vector_db.as_retriever()

rag_prompt = PromptTemplate.from_template(
    "Answer the questions using ONLY the documents.\nQuestion: {input}\n\nDocuments:\n{context}"
)

doc_chain = create_stuff_documents_chain(llm, rag_prompt)
rag_chain = create_retrieval_chain(retriever, doc_chain)

def retrieval_tool(query: str) -> str:
    """Answer questions about italian soccer teams"""
    result = rag_chain.invoke(
        {"input": query},
    )
    return result["answer"]
    
tools = [
    StructuredTool.from_function(dani_drinks),
    StructuredTool.from_function(calculator),
    StructuredTool.from_function(weather_tool),
    StructuredTool.from_function(retrieval_tool)
]

# === AGENT ===
system_prompt = SystemMessagePromptTemplate.from_template(
    "You are DaniBot, an agent that can answer math questions, tell info about Dani's favorite drinks and tell the weather in a city."
    "You can also answer questions about italian soccer teams "
    "Dani is your boss. Use the tools if needed. Answer with an Italian accent! "
    "You can also answer general base knowledge questions if you know the answer"
    "If the user seems wanting to quit, thank him/her and say 'SUCA!'"
)

human_prompt = HumanMessagePromptTemplate.from_template("{input}\n{agent_scratchpad}")
chat_prompt = ChatPromptTemplate.from_messages([system_prompt, human_prompt])

# === AGENT ===
raw_agent = create_tool_calling_agent(llm, tools, chat_prompt)

agent_executor = AgentExecutor(
    agent=raw_agent,
    tools=tools,
    verbose=False
)

# === GRADIO INTERFACCIA + window ===
def chat_fn(message, history):
    session_id = str(uuid.uuid4())
    result = agent_executor.invoke(
        {"input": message},
        config={"configurable": {"session_id": session_id}}
    )
    return result["output"]

with gr.Blocks() as demo:
    gr.Markdown(
        """
        # DaniBot 🤖

        Questo chatbot può rispondere sui drinks di Dani, ma anche a domande di matematica, informazioni sulle squadre di calcio italiane,
        il meteo, e altro ancora. Usa dei tools integrati per darti risposte più accurate.

        Scrivi un messaggio per iniziare la chat!
        Scrivi 'q' o 'quit' per terminare la chat!
        """
    )
    chatbot = gr.ChatInterface(
    	fn=chat_fn,
    	examples=["Quando è stata fondata la Juventus?"],
    	title="DaniBot - ask me something!",
    	type="messages"
    )

if __name__ == "__main__":
    demo.launch()