Spaces:
Sleeping
Sleeping
File size: 9,207 Bytes
cd0c4bd |
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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# LangGraph è un framework che consente di creare applicazioni pronte per la produzione offrendo strumenti di controllo sul flusso del proprio agente.
# LangGraph è un framework sviluppato da LangChain per gestire il flusso di controllo delle applicazioni che integrano un LLM.
# https://www.langchain.com/
# LangChain fornisce un'interfaccia standard per interagire con modelli e altri componenti, utile per il recupero, le chiamate LLM e le chiamate agli strumenti.
# Le classi di LangChain possono essere utilizzate in LangGraph, ma non è obbligatorio.
# Quando usare LangGraph? Quando si progettano applicazioni di intelligenza artificiale, ci si trova di fronte a un compromesso fondamentale tra controllo e libertà:
# 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.
# Tuttavia, questo comportamento può renderli meno prevedibili e meno controllabili di un normale agente che lavora con JSON!
# LangGraph è all'altro estremo dello spettro, ed è utile quando hai bisogno di "controllo" sull'esecuzione del tuo agente.
# 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.
# Come funziona LangGraph?
# 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).
# Edges : definiscono le possibili transizioni tra i passaggi.
# 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.
# Building Blocks of LangGraph
# Per creare applicazioni con LangGraph, è necessario comprenderne i componenti principali. Esploriamo gli elementi fondamentali che compongono un'applicazione LangGraph.
#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.
# 1. State Lo stato è il concetto centrale di LangGraph. Rappresenta tutte le informazioni che fluiscono attraverso l'applicazione.
# 2. Nodes I nodi sono funzioni Python. Ogni nodo: Accetta lo stato come input Esegue un'operazione Restituisce aggiornamenti allo stato
# 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
# 3. Edges collegano i nodi e definiscono i possibili percorsi attraverso il grafico
# 4. StateGraph è il contenitore che contiene l'intero flusso di lavoro dell'agente:
# Esempio: https://huggingface.co/agents-course/notebooks/blob/main/unit2/langgraph/mail_sorting.ipynb
# pip install langgraph langchain_openai
import datasets
from langchain.docstore.document import Document
from langchain_community.retrievers import BM25Retriever
from langchain.tools import Tool
from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages
from langchain_core.messages import AnyMessage, HumanMessage, AIMessage
from langgraph.prebuilt import ToolNode
from langgraph.graph import START, StateGraph
from langgraph.prebuilt import tools_condition
#from langchain_huggingface import HuggingFaceEndpoint, ChatHuggingFace
from langchain_huggingface import HuggingFaceEndpoint
from langchain_community.tools import DuckDuckGoSearchRun
import gradio as gr
import os
#######################################
## Give Your Agent Access to the Web ##
#######################################
search_tool = DuckDuckGoSearchRun()
# results = search_tool.invoke("Who's the current President of France?")
# print(results)
##########################################
## Step 1: Load and Prepare the Dataset ##
##########################################
# Per prima cosa, dobbiamo trasformare i dati grezzi dei nostri ospiti in un formato ottimizzato per il recupero.
# 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.
# Load the dataset
guest_dataset = datasets.load_dataset("agents-course/unit3-invitees", split="train")
# Convert dataset entries into Document objects
docs = [
Document(
page_content="\n".join([
f"Name: {guest['name']}",
f"Relation: {guest['relation']}",
f"Description: {guest['description']}",
f"Email: {guest['email']}"
]),
metadata={"name": guest["name"]}
)
for guest in guest_dataset
]
# Nel codice sopra: Carichiamo il dataset Convertiamo ogni voce ospite in un oggetto Documento con contenuto formattato Memorizziamo gli oggetti Documento in un elenco
# Ciò significa che tutti i nostri dati sono prontamente disponibili e possiamo iniziare a configurare il recupero.
##########################################
## Step 2: Create the Retriever Tool ##
##########################################
# Ora creiamo uno strumento personalizzato che Alfred potrà utilizzare per cercare le informazioni sui nostri ospiti.
# Utilizzeremo BM25Retriever dal modulo langchain_community.retrievers per creare uno strumento di recupero.
# 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.
bm25_retriever = BM25Retriever.from_documents(docs)
def extract_text(query: str) -> str:
"""Retrieves detailed information about gala guests based on their name or relation."""
results = bm25_retriever.invoke(query)
if results:
return "\n\n".join([doc.page_content for doc in results[:3]])
else:
return "No matching guest information found."
guest_info_tool = Tool(
name="guest_info_retriever",
func=extract_text,
description="Retrieves detailed information about gala guests based on their name or relation."
)
# Analizziamo questo strumento passo dopo passo.
# Il nome e la descrizione aiutano l'agente a capire quando e come utilizzare questo strumento.
# I decoratori di tipo definiscono i parametri che lo strumento si aspetta (in questo caso, una query di ricerca).
# Utilizziamo BM25Retriever, un potente algoritmo di recupero del testo che non richiede incorporamenti.
# Il metodo elabora la query e restituisce le informazioni più rilevanti sull'ospite.
############################################
## Step 2: Integrate the Tool with Alfred ##
############################################
# Infine, mettiamo insieme il tutto creando il nostro agente e dotandolo del nostro strumento personalizzato:
# Generate the chat interface, including the tools
llm = HuggingFaceEndpoint(
repo_id="Qwen/Qwen2.5-Coder-32B-Instruct",
huggingfacehub_api_token=os.getenv("HF_TOKEN"),
)
#chat = ChatHuggingFace(llm=llm, verbose=True)
#tools = [guest_info_tool,search_tool]
tools = [search_tool]
#chat_with_tools = chat.bind_tools(tools)
# Generate the AgentState and Agent graph
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
# def assistant(state: AgentState):
# return {
# "messages": [chat_with_tools.invoke(state["messages"])],
# }
def assistant(state: AgentState):
# Prendi l'ultimo messaggio umano
human_msg = [msg for msg in state["messages"] if isinstance(msg, HumanMessage)][-1]
# Chiama il modello LLM direttamente con il testo
response_text = llm.invoke(human_msg.content)
# Crea una risposta AIMessage
ai_message = HumanMessage(content=response_text) # o AIMessage se preferisci
return {
"messages": state["messages"] + [ai_message]
}
## The graph
builder = StateGraph(AgentState)
# Define nodes: these do the work
builder.add_node("assistant", assistant)
builder.add_node("tools", ToolNode(tools))
# Define edges: these determine how the control flow moves
builder.add_edge(START, "assistant")
builder.add_conditional_edges(
"assistant",
# If the latest message requires a tool, route to tools
# Otherwise, provide a direct response
tools_condition,
)
builder.add_edge("tools", "assistant")
alfred = builder.compile()
# Funzione Gradio
def run_agent(input_text):
try:
response = alfred.invoke({"messages": input_text})
return response['messages'][-1].content
except Exception as e:
return f"Errore: {str(e)}"
iface = gr.Interface(
fn=run_agent,
inputs="text",
outputs="text",
title="Wikipedia AI Agent",
description="Scrivi un argomento, l'agente recupera un riassunto da Wikipedia e lo spiega usando un LLM."
)
iface.launch()
# messages = [HumanMessage(content="Tell me about our guest named 'Lady Ada Lovelace'.")]
# response = alfred.invoke({"messages": messages})
# print("🎩 Alfred's Response:")
# print(response['messages'][-1].content) |