Spaces:
Sleeping
Sleeping
File size: 8,451 Bytes
3a94433 e05ea71 3a94433 e05ea71 3a94433 e05ea71 3a94433 e05ea71 3a94433 |
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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
import os
import gradio as gr
from huggingface_hub import InferenceClient
from langchain_openai import ChatOpenAI
from crewai_tools import PDFSearchTool
from langchain_community.tools.tavily_search import TavilySearchResults
from crewai_tools import tool
from crewai import Crew, Task, Agent
from google.colab import userdata
from sentence_transformers import SentenceTransformer
os.environ['GROQ_API_KEY'] = userdata.get('GROQ_API_KEY')
os.environ['TAVILY_API_KEY'] = userdata.get('TAVILY_API_KEY')
client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
llm = ChatOpenAI(
openai_api_base="https://api.groq.com/openai/v1",
openai_api_key=os.environ['GROQ_API_KEY'],
model_name="llama3-70b-8192",
temperature=0.1,
max_tokens=1000
)
rag_tool = PDFSearchTool(pdf='finance.pdf',
config=dict(
llm=dict(
provider="groq",
config=dict(
model="llama3-8b-8192",
),
),
embedder=dict(
provider="huggingface",
config=dict(
model="BAAI/bge-small-en-v1.5",
),
),
)
)
web_search_tool = TavilySearchResults(k=3)
@tool
def router_tool(question):
"""Router Function"""
return 'web_search'
Router_Agent = Agent(
role='Router',
goal='Route user question to a vectorstore or web search',
backstory=(
"You are an expert at routing a user question to a vectorstore or web search."
"Use the vectorstore for questions on concept related to Retrieval-Augmented Generation."
"You do not need to be stringent with the keywords in the question related to these topics. Otherwise, use web-search."
),
verbose=True,
allow_delegation=False,
llm=llm,
)
Retriever_Agent = Agent(
role="Retriever",
goal="Use the information retrieved from the vectorstore to answer the question",
backstory=(
"You are an assistant for question-answering tasks."
"Use the information present in the retrieved context to answer the question."
"You have to provide a clear concise answer."
),
verbose=True,
allow_delegation=False,
llm=llm,
)
Grader_agent = Agent(
role='Answer Grader',
goal='Filter out erroneous retrievals',
backstory=(
"You are a grader assessing relevance of a retrieved document to a user question."
"If the document contains keywords related to the user question, grade it as relevant."
"It does not need to be a stringent test.You have to make sure that the answer is relevant to the question."
),
verbose=True,
allow_delegation=False,
llm=llm,
)
hallucination_grader = Agent(
role="Hallucination Grader",
goal="Filter out hallucination",
backstory=(
"You are a hallucination grader assessing whether an answer is grounded in / supported by a set of facts."
"Make sure you meticulously review the answer and check if the response provided is in alignment with the question asked"
),
verbose=True,
allow_delegation=False,
llm=llm,
)
answer_grader = Agent(
role="Answer Grader",
goal="Filter out hallucination from the answer.",
backstory=(
"You are a grader assessing whether an answer is useful to resolve a question."
"Make sure you meticulously review the answer and check if it makes sense for the question asked"
"If the answer is relevant generate a clear and concise response."
"If the answer generated is not relevant then perform a websearch using 'web_search_tool'"
),
verbose=True,
allow_delegation=False,
llm=llm,
)
router_task = Task(
description=("Analyse the keywords in the question {question}"
"Based on the keywords decide whether it is eligible for a vectorstore search or a web search."
"Return a single word 'vectorstore' if it is eligible for vectorstore search."
"Return a single word 'websearch' if it is eligible for web search."
"Do not provide any other preamble or explanation."
),
expected_output=("Give a binary choice 'websearch' or 'vectorstore' based on the question"
"Do not provide any other preamble or explanation."),
agent=Router_Agent,
tools=[router_tool],
)
retriever_task = Task(
description=("Based on the response from the router task extract information for the question {question} with the help of the respective tool."
"Use the web_search_tool to retrieve information from the web in case the router task output is 'websearch'."
"Use the rag_tool to retrieve information from the vectorstore in case the router task output is 'vectorstore'."
),
expected_output=("You should analyse the output of the 'router_task'"
"If the response is 'websearch' then use the web_search_tool to retrieve information from the web."
"If the response is 'vectorstore' then use the rag_tool to retrieve information from the vectorstore."
"Return a clear and concise text as response."),
agent=Retriever_Agent,
context=[router_task],
)
grader_task = Task(
description=("Based on the response from the retriever task for the question {question} evaluate whether the retrieved content is relevant to the question."
),
expected_output=("Binary score 'yes' or 'no' score to indicate whether the document is relevant to the question"
"You must answer 'yes' if the response from the 'retriever_task' is in alignment with the question asked."
"You must answer 'no' if the response from the 'retriever_task' is not in alignment with the question asked."
"Do not provide any preamble or explanations except for 'yes' or 'no'."),
agent=Grader_agent,
context=[retriever_task],
)
hallucination_task = Task(
description=("Based on the response from the grader task for the question {question} evaluate whether the answer is grounded in / supported by a set of facts."),
expected_output=("Binary score 'yes' or 'no' score to indicate whether the answer is sync with the question asked"
"Respond 'yes' if the answer is useful and contains fact about the question asked."
"Respond 'no' if the answer is not useful and does not contains fact about the question asked."
"Do not provide any preamble or explanations except for 'yes' or 'no'."),
agent=hallucination_grader,
context=[grader_task],
)
answer_task = Task(
description=("Based on the response from the hallucination task for the question {question} evaluate whether the answer is useful to resolve the question."
"If the answer is 'yes' return a clear and concise answer."
"If the answer is 'no' then perform a 'websearch' and return the response"),
expected_output=("Return a clear and concise response if the response from 'hallucination_task' is 'yes'."
"Perform a web search using 'web_search_tool' and return a clear and concise response only if the response from 'hallucination_task' is 'no'."
"Otherwise respond as 'Sorry! unable to find a valid response'."),
context=[hallucination_task],
agent=answer_grader,
)
rag_crew = Crew(
agents=[Router_Agent, Retriever_Agent, Grader_agent, hallucination_grader, answer_grader],
tasks=[router_task, retriever_task, grader_task, hallucination_task, answer_task],
verbose=True,
)
def respond(
message,
history: list[tuple[str, str]],
system_message,
max_tokens,
temperature,
top_p,
):
messages = [{"role": "system", "content": system_message}]
for val in history:
if val[0]:
messages.append({"role": "user", "content": val[0]})
if val[1]:
messages.append({"role": "assistant", "content": val[1]})
messages.append({"role": "user", "content": message})
response = ""
inputs = {"question": message}
result = rag_crew.kickoff(inputs=inputs)
for message in client.chat_completion(
messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
):
token = message.choices[0].delta.content
response += token
yield response
demo = gr.ChatInterface(
respond,
additional_inputs=[
gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
gr.S
|