Spaces:
Sleeping
Sleeping
retriever implemented
Browse files- app.py +64 -0
- retriever.py +40 -0
- tools.py +0 -0
app.py
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from typing import TypedDict, Annotated
|
3 |
+
from langgraph.graph.message import add_messages
|
4 |
+
from langchain_core.messages import AnyMessage, HumanMessage, AIMessage
|
5 |
+
from langgraph.prebuilt import ToolNode
|
6 |
+
from langgraph.graph import START, StateGraph
|
7 |
+
from langgraph.prebuilt import tools_condition
|
8 |
+
from langchain_huggingface import HuggingFaceEndpoint, ChatHuggingFace
|
9 |
+
|
10 |
+
# Generate the chat interface, including the tools
|
11 |
+
llm = HuggingFaceEndpoint(
|
12 |
+
repo_id="Qwen/Qwen2.5-Coder-32B-Instruct",
|
13 |
+
provider="together",
|
14 |
+
huggingfacehub_api_token=HUGGINGFACEHUB_API_TOKEN,
|
15 |
+
)
|
16 |
+
|
17 |
+
retriever = load_guest_dataset()
|
18 |
+
|
19 |
+
guest_info_tool = Tool(
|
20 |
+
name="guest_info_retriever",
|
21 |
+
func=retriever.retrieve,
|
22 |
+
description="Retrieves detailed information about gala guests based on their name or relation."
|
23 |
+
)
|
24 |
+
|
25 |
+
chat = ChatHuggingFace(llm=llm, verbose=True)
|
26 |
+
tools = [guest_info_tool]
|
27 |
+
chat_with_tools = chat.bind_tools(tools)
|
28 |
+
|
29 |
+
# Generate the AgentState and Agent graph
|
30 |
+
class AgentState(TypedDict):
|
31 |
+
messages: Annotated[list[AnyMessage], add_messages]
|
32 |
+
|
33 |
+
def assistant(state: AgentState):
|
34 |
+
return {
|
35 |
+
"messages": [chat_with_tools.invoke(state["messages"])],
|
36 |
+
}
|
37 |
+
|
38 |
+
## The graph
|
39 |
+
builder = StateGraph(AgentState)
|
40 |
+
|
41 |
+
# Define nodes: these do the work
|
42 |
+
builder.add_node("assistant", assistant)
|
43 |
+
builder.add_node("tools", ToolNode(tools))
|
44 |
+
|
45 |
+
# Define edges: these determine how the control flow moves
|
46 |
+
builder.add_edge(START, "assistant")
|
47 |
+
builder.add_conditional_edges(
|
48 |
+
"assistant",
|
49 |
+
# If the latest message requires a tool, route to tools
|
50 |
+
# Otherwise, provide a direct response
|
51 |
+
tools_condition,
|
52 |
+
"tools",
|
53 |
+
)
|
54 |
+
builder.add_edge("tools", "assistant")
|
55 |
+
alfred = builder.compile()
|
56 |
+
|
57 |
+
def call_agent_ui(prompt):
|
58 |
+
situation = "This is a fictional situation. You are Alfred the Butler of Waynes Manor and host a Gala for invited Guests. All Guests are completely ficional. Information about those guests can be found in a database. Only give information which is based on the databse. If a name of a guest is given, then return a possible starter of a conversation with that guest. If the name is not known, then say that you do not know that guest. If two names of guests are given, then return a possible starter of a conversation with both guests. If the name is not known, then say that you do not know that guest. If the name is not known, then say that you do not know that guest."
|
59 |
+
messages = [HumanMessage(content=f"{situation} {prompt}")]
|
60 |
+
response = alfred.invoke({"messages": messages})
|
61 |
+
return response['messages'][-1].content
|
62 |
+
|
63 |
+
iface = gr.Interface(fn=call_agent_ui, inputs="text", outputs="text")
|
64 |
+
iface.launch()
|
retriever.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain_community.retrievers import BM25Retriever
|
2 |
+
from langchain.tools import Tool
|
3 |
+
|
4 |
+
import datasets
|
5 |
+
from langchain.docstore.document import Document
|
6 |
+
|
7 |
+
class GuestInfoRetriever:
|
8 |
+
"""A class to retrieve information about gala guests."""
|
9 |
+
|
10 |
+
def __init__(self, docs):
|
11 |
+
self.docs = docs
|
12 |
+
self.dataset = BM25Retriever.from_documents(docs)
|
13 |
+
|
14 |
+
def retrieve(self, query: str):
|
15 |
+
"""Retrieves detailed information about gala guests based on their name or relation."""
|
16 |
+
results = self.dataset.invoke(query)
|
17 |
+
if results:
|
18 |
+
return "\n\n".join([doc.page_content for doc in results[:3]])
|
19 |
+
else:
|
20 |
+
return "No matching guest information found."
|
21 |
+
|
22 |
+
# Load the dataset
|
23 |
+
def load_guest_dataset():
|
24 |
+
guest_dataset = datasets.load_dataset("agents-course/unit3-invitees", split="train")
|
25 |
+
# Convert dataset entries into Document objects
|
26 |
+
docs = [
|
27 |
+
Document(
|
28 |
+
page_content="\n".join([
|
29 |
+
f"Name: {guest['name']}",
|
30 |
+
f"Relation: {guest['relation']}",
|
31 |
+
f"Description: {guest['description']}",
|
32 |
+
f"Email: {guest['email']}"
|
33 |
+
]),
|
34 |
+
metadata={"name": guest["name"]}
|
35 |
+
)
|
36 |
+
for guest in guest_dataset
|
37 |
+
]
|
38 |
+
|
39 |
+
return GuestInfoRetriever(docs)
|
40 |
+
|
tools.py
ADDED
File without changes
|