Spaces:
Sleeping
Sleeping
File size: 4,938 Bytes
9319e6f 78e2723 2f2bdcf 004a8b0 0c3e951 9319e6f 78e2723 9319e6f 78e2723 9319e6f 78e2723 9319e6f 78e2723 9319e6f 78e2723 9319e6f 78e2723 9319e6f 004a8b0 9319e6f 004a8b0 9319e6f 004a8b0 7f6547d 9319e6f 77bac94 2f2bdcf 77bac94 2f2bdcf 9319e6f |
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 |
from typing import List, TypedDict, Annotated, Optional, Dict, Union
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage, AnyMessage
from langgraph.graph.message import add_messages
from langchain_community.vectorstores import SupabaseVectorStore
from supabase.client import create_client
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_huggingface import HuggingFaceEmbeddings, ChatHuggingFace, HuggingFaceEndpoint
from serpapi import GoogleSearch
from dotenv import load_dotenv
import os
load_dotenv()
class AgentState(TypedDict):
"""Agent state to be passed to the tool."""
messages: Annotated[List[AnyMessage], add_messages]
def add(a: Union[float , int], b: Union[float , int]) -> Union[float , int]:
"""Add two numbers."""
return a + b
def subtract(a: Union[float , int], b: Union[float , int]) -> Union[float , int]:
"""Subtract two numbers."""
return a - b
def multiply(a: Union[float , int], b: Union[float , int]) -> Union[float , int]:
"""Multiply two numbers."""
return a * b
def divide(a: Union[float , int], b: Union[float , int]) -> Union[float , int , None]:
"""Divide two numbers."""
if b == 0:
return None
return a / b
def web_search(query: str) -> str:
"""Perform a web search using SerpAPI."""
params = {
"engine": "google",
"q": query,
"api_key": os.getenv("SERPAPI_KEY"),
"num": 5
}
search = GoogleSearch(params)
results = search.get_dict()["organic_results"]
context = "\n---\n".join([
"Title: " + result['title'] + "\nLink: " + result['link'] + "\nSnippet: " + result.get('snippet', 'No snippet available')
for result in results if 'title' in result and 'link' in result
]
)
return context if context else "No results found."
# llm = ChatHuggingFace(llm = HuggingFaceEndpoint(
# repo_id = "meta-llama/Llama-2-7b-chat-hf",
# temperature=0,
# huggingfacehub_api_token=os.environ.get("HUGGING_FACE_API_KEY")))
tools = [add, subtract, divide, web_search]
llm =ChatGoogleGenerativeAI(model = "gemini-2.0-flash")
llm_with_tools = llm.bind_tools(tools)
def retriever(state: AgentState) -> Dict:
"""
Retrieve the answer fom vector database instead of searching if we found a user query similar to which is already found in the dataset
"""
supabase_url = os.environ.get("SUPABASE_URL")
supabase_key = os.environ.get("SUPABASE_KEY")
supabase = create_client(supabase_url, supabase_key)
embeddings = HuggingFaceEmbeddings(model_name = "sentence-transformers/all-mpnet-base-v2")
vector_store = SupabaseVectorStore(
embedding=embeddings,
client=supabase,
table_name="documents",
query_name="match_documents",
)
docs = vector_store.similarity_search(query = state["messages"][-1].content, k = 1)
humanmessage = HumanMessage(content = f"Here are some of the questions and answers relevant to user query \n\n {docs[0].page_content}")
return {"messages":[humanmessage]}
def assistant(state: AgentState) -> Dict:
system_message = """
You are a helpful assistant tasked with answering questions using a set of tools.
Now, I will ask you a question. Report your thoughts, and finish your answer with the following template:
FINAL ANSWER: [YOUR FINAL ANSWER].
YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.
Your answer should only start with "FINAL ANSWER: ", then follows with the answer.
"""
tools_description = """
You have the following tools available to perform actions
websearch(query: str) -> str:
Args:
query: Search query
Returns:
A string containing 5 relevant search results
add(a: Union[float , int], b: Union[float , int]) -> Union[float , int]:
Add two numbers
subtract(a: Union[float , int], b: Union[float , int]) -> Union[float , int]:
Subtract two numbers
multiply(a: Union[float , int], b: Union[float , int]) -> Union[float , int]:
Multiply two numbers
divide(a: Union[float , int], b: Union[float , int]) -> Union[float , int , None]:
Divide two numbers
"""
sys_msg = SystemMessage(content=system_message + tools_description)
return {"messages": [llm_with_tools.invoke([sys_msg] + state["messages"])]} |