sminichiello commited on
Commit
cd0c4bd
·
verified ·
1 Parent(s): 1e77490

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +187 -0
app.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # LangGraph è un framework che consente di creare applicazioni pronte per la produzione offrendo strumenti di controllo sul flusso del proprio agente.
2
+ # LangGraph è un framework sviluppato da LangChain per gestire il flusso di controllo delle applicazioni che integrano un LLM.
3
+ # https://www.langchain.com/
4
+ # LangChain fornisce un'interfaccia standard per interagire con modelli e altri componenti, utile per il recupero, le chiamate LLM e le chiamate agli strumenti.
5
+ # Le classi di LangChain possono essere utilizzate in LangGraph, ma non è obbligatorio.
6
+
7
+ # Quando usare LangGraph? Quando si progettano applicazioni di intelligenza artificiale, ci si trova di fronte a un compromesso fondamentale tra controllo e libertà:
8
+ # Gli agenti, come quelli che si possono trovare in smolagents, sono molto liberi. Possono richiamare più strumenti in un'unica fase di azione, creare i propri strumenti, ecc.
9
+ # Tuttavia, questo comportamento può renderli meno prevedibili e meno controllabili di un normale agente che lavora con JSON!
10
+ # LangGraph è all'altro estremo dello spettro, ed è utile quando hai bisogno di "controllo" sull'esecuzione del tuo agente.
11
+ # In parole povere, se la tua applicazione prevede una serie di passaggi che devono essere orchestrati in un modo specifico, con decisioni prese a ogni punto di congiunzione, LangGraph fornisce la struttura di cui hai bisogno.
12
+
13
+ # Come funziona LangGraph?
14
+ # Nodes : I nodi rappresentano singole fasi di elaborazione (come la chiamata di un LLM, l'utilizzo di uno strumento o la presa di una decisione).
15
+ # Edges : definiscono le possibili transizioni tra i passaggi.
16
+ # State : È definito e gestito dall'utente e trasmesso tra i nodi durante l'esecuzione. Quando decidiamo quale nodo indirizzare successivamente, questo è lo stato attuale che prendiamo in considerazione.
17
+
18
+ # Building Blocks of LangGraph
19
+ # Per creare applicazioni con LangGraph, è necessario comprenderne i componenti principali. Esploriamo gli elementi fondamentali che compongono un'applicazione LangGraph.
20
+ #Un'applicazione in LangGraph inizia da un punto di ingresso e, a seconda dell'esecuzione, il flusso può passare a una funzione o all'altra fino a raggiungere la FINE.
21
+ # 1. State Lo stato è il concetto centrale di LangGraph. Rappresenta tutte le informazioni che fluiscono attraverso l'applicazione.
22
+ # 2. Nodes I nodi sono funzioni Python. Ogni nodo: Accetta lo stato come input Esegue un'operazione Restituisce aggiornamenti allo stato
23
+ # Ad esempio, i nodi possono contenere: Chiamate LLM: generare testo o prendere decisioni Chiamate strumenti: interagire con sistemi esterni Logica condizionale: determinare i passaggi successivi Intervento umano: ottenere input dagli utenti
24
+ # 3. Edges collegano i nodi e definiscono i possibili percorsi attraverso il grafico
25
+ # 4. StateGraph è il contenitore che contiene l'intero flusso di lavoro dell'agente:
26
+
27
+ # Esempio: https://huggingface.co/agents-course/notebooks/blob/main/unit2/langgraph/mail_sorting.ipynb
28
+
29
+ # pip install langgraph langchain_openai
30
+
31
+ import datasets
32
+ from langchain.docstore.document import Document
33
+ from langchain_community.retrievers import BM25Retriever
34
+ from langchain.tools import Tool
35
+ from typing import TypedDict, Annotated
36
+ from langgraph.graph.message import add_messages
37
+ from langchain_core.messages import AnyMessage, HumanMessage, AIMessage
38
+ from langgraph.prebuilt import ToolNode
39
+ from langgraph.graph import START, StateGraph
40
+ from langgraph.prebuilt import tools_condition
41
+ #from langchain_huggingface import HuggingFaceEndpoint, ChatHuggingFace
42
+ from langchain_huggingface import HuggingFaceEndpoint
43
+ from langchain_community.tools import DuckDuckGoSearchRun
44
+ import gradio as gr
45
+ import os
46
+
47
+ #######################################
48
+ ## Give Your Agent Access to the Web ##
49
+ #######################################
50
+
51
+ search_tool = DuckDuckGoSearchRun()
52
+ # results = search_tool.invoke("Who's the current President of France?")
53
+ # print(results)
54
+
55
+ ##########################################
56
+ ## Step 1: Load and Prepare the Dataset ##
57
+ ##########################################
58
+ # Per prima cosa, dobbiamo trasformare i dati grezzi dei nostri ospiti in un formato ottimizzato per il recupero.
59
+ # Utilizzeremo la libreria di set di dati Hugging Face per caricare il set di dati e convertirlo in un elenco di oggetti Document dal modulo langchain.docstore.document.
60
+
61
+ # Load the dataset
62
+ guest_dataset = datasets.load_dataset("agents-course/unit3-invitees", split="train")
63
+
64
+ # Convert dataset entries into Document objects
65
+ docs = [
66
+ Document(
67
+ page_content="\n".join([
68
+ f"Name: {guest['name']}",
69
+ f"Relation: {guest['relation']}",
70
+ f"Description: {guest['description']}",
71
+ f"Email: {guest['email']}"
72
+ ]),
73
+ metadata={"name": guest["name"]}
74
+ )
75
+ for guest in guest_dataset
76
+ ]
77
+
78
+ # Nel codice sopra: Carichiamo il dataset Convertiamo ogni voce ospite in un oggetto Documento con contenuto formattato Memorizziamo gli oggetti Documento in un elenco
79
+ # Ciò significa che tutti i nostri dati sono prontamente disponibili e possiamo iniziare a configurare il recupero.
80
+
81
+ ##########################################
82
+ ## Step 2: Create the Retriever Tool ##
83
+ ##########################################
84
+ # Ora creiamo uno strumento personalizzato che Alfred potrà utilizzare per cercare le informazioni sui nostri ospiti.
85
+ # Utilizzeremo BM25Retriever dal modulo langchain_community.retrievers per creare uno strumento di recupero.
86
+ # BM25Retriever è un ottimo punto di partenza per il recupero, ma per una ricerca semantica più avanzata, potresti prendere in considerazione l'utilizzo di retriever basati sull'incorporamento come quelli di sentence-transformers.
87
+
88
+ bm25_retriever = BM25Retriever.from_documents(docs)
89
+
90
+ def extract_text(query: str) -> str:
91
+ """Retrieves detailed information about gala guests based on their name or relation."""
92
+ results = bm25_retriever.invoke(query)
93
+ if results:
94
+ return "\n\n".join([doc.page_content for doc in results[:3]])
95
+ else:
96
+ return "No matching guest information found."
97
+
98
+ guest_info_tool = Tool(
99
+ name="guest_info_retriever",
100
+ func=extract_text,
101
+ description="Retrieves detailed information about gala guests based on their name or relation."
102
+ )
103
+
104
+ # Analizziamo questo strumento passo dopo passo.
105
+ # Il nome e la descrizione aiutano l'agente a capire quando e come utilizzare questo strumento.
106
+ # I decoratori di tipo definiscono i parametri che lo strumento si aspetta (in questo caso, una query di ricerca).
107
+ # Utilizziamo BM25Retriever, un potente algoritmo di recupero del testo che non richiede incorporamenti.
108
+ # Il metodo elabora la query e restituisce le informazioni più rilevanti sull'ospite.
109
+
110
+ ############################################
111
+ ## Step 2: Integrate the Tool with Alfred ##
112
+ ############################################
113
+
114
+ # Infine, mettiamo insieme il tutto creando il nostro agente e dotandolo del nostro strumento personalizzato:
115
+
116
+ # Generate the chat interface, including the tools
117
+ llm = HuggingFaceEndpoint(
118
+ repo_id="Qwen/Qwen2.5-Coder-32B-Instruct",
119
+ huggingfacehub_api_token=os.getenv("HF_TOKEN"),
120
+ )
121
+
122
+ #chat = ChatHuggingFace(llm=llm, verbose=True)
123
+ #tools = [guest_info_tool,search_tool]
124
+ tools = [search_tool]
125
+ #chat_with_tools = chat.bind_tools(tools)
126
+
127
+ # Generate the AgentState and Agent graph
128
+ class AgentState(TypedDict):
129
+ messages: Annotated[list[AnyMessage], add_messages]
130
+
131
+ # def assistant(state: AgentState):
132
+ # return {
133
+ # "messages": [chat_with_tools.invoke(state["messages"])],
134
+ # }
135
+
136
+ def assistant(state: AgentState):
137
+ # Prendi l'ultimo messaggio umano
138
+ human_msg = [msg for msg in state["messages"] if isinstance(msg, HumanMessage)][-1]
139
+ # Chiama il modello LLM direttamente con il testo
140
+ response_text = llm.invoke(human_msg.content)
141
+ # Crea una risposta AIMessage
142
+ ai_message = HumanMessage(content=response_text) # o AIMessage se preferisci
143
+ return {
144
+ "messages": state["messages"] + [ai_message]
145
+ }
146
+
147
+ ## The graph
148
+ builder = StateGraph(AgentState)
149
+
150
+ # Define nodes: these do the work
151
+ builder.add_node("assistant", assistant)
152
+ builder.add_node("tools", ToolNode(tools))
153
+
154
+ # Define edges: these determine how the control flow moves
155
+ builder.add_edge(START, "assistant")
156
+ builder.add_conditional_edges(
157
+ "assistant",
158
+ # If the latest message requires a tool, route to tools
159
+ # Otherwise, provide a direct response
160
+ tools_condition,
161
+ )
162
+ builder.add_edge("tools", "assistant")
163
+ alfred = builder.compile()
164
+
165
+ # Funzione Gradio
166
+ def run_agent(input_text):
167
+ try:
168
+ response = alfred.invoke({"messages": input_text})
169
+ return response['messages'][-1].content
170
+ except Exception as e:
171
+ return f"Errore: {str(e)}"
172
+
173
+ iface = gr.Interface(
174
+ fn=run_agent,
175
+ inputs="text",
176
+ outputs="text",
177
+ title="Wikipedia AI Agent",
178
+ description="Scrivi un argomento, l'agente recupera un riassunto da Wikipedia e lo spiega usando un LLM."
179
+ )
180
+
181
+ iface.launch()
182
+
183
+ # messages = [HumanMessage(content="Tell me about our guest named 'Lady Ada Lovelace'.")]
184
+ # response = alfred.invoke({"messages": messages})
185
+
186
+ # print("🎩 Alfred's Response:")
187
+ # print(response['messages'][-1].content)