Spaces:
Sleeping
Sleeping
#%% | |
### Router | |
from src.index import * | |
from typing import Literal | |
from langchain_core.prompts import ChatPromptTemplate | |
from langchain_core.pydantic_v1 import BaseModel, Field | |
# from langchain_openai import AzureChatOpenAI | |
#%% | |
# Data model | |
class RouteQuery(BaseModel): | |
"""Route a user query to the most relevant datasource.""" | |
datasource: Literal["vectorstore", "web_search"] = Field( | |
..., | |
description="Given a user question choose to route it to web search or a vectorstore.", | |
) | |
# LLM with function call | |
# llm = AzureChatOpenAI(model="gpt-4o-mini", temperature=0.3) | |
structured_llm_router = llm.with_structured_output(RouteQuery) | |
# Prompt | |
system = """You are an expert at routing a user question to a vectorstore or web search. | |
The vectorstore contains documents related to Indian Penal Code and The Indian Constitution. | |
It can answer questions related to Indian Law, IPC and the Constitution. | |
Use vectorstore if the question is a legal query within the scope of IPC, Indian Law and the Indian Constitution. | |
Use web-search if the question is a legal query outside the scope of IPC, Indian Law and the Indian Constitution. | |
Use web-search and your own knowledge if the question requires general legal help. | |
Use web-search if the questions is a legal query that requires latest information.""" | |
route_prompt = ChatPromptTemplate.from_messages( | |
[ | |
("system", system), | |
("human", "{question}"), | |
("human", "{chat_context}"), | |
] | |
) | |
question_router = route_prompt | structured_llm_router | |
# %% | |
### Retrieval Grader | |
# Data model | |
class GradeDocuments(BaseModel): | |
"""Binary score for relevance check on retrieved documents.""" | |
binary_score: str = Field( | |
description="Documents are relevant to the question, 'yes' or 'no'" | |
) | |
# LLM with function call | |
# llm = AzureChatOpenAI(model="gpt-4o-mini", temperature=0.3) | |
structured_llm_grader = llm.with_structured_output(GradeDocuments) | |
# Prompt | |
system = """You are a grader assessing relevance of a retrieved document to a user question. \n | |
If the document contains keyword(s) or is relevant to the user question, grade it as relevant. \n | |
The goal is to filter out erroneous retrievals. \n | |
Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question. | |
Return 'yes' if the document is relevant to the question, otherwise return 'no'. | |
Also return 'yes' if the document may be relevant, and might be useful, otherwise return 'no'.""" | |
grade_prompt = ChatPromptTemplate.from_messages( | |
[ | |
("system", system), | |
("human", "Retrieved document: \n\n {document} \n\n User question: {question} \n\n Chat context: {chat_context}"), | |
] | |
) | |
retrieval_grader = grade_prompt | structured_llm_grader | |
# question = "agent memory" | |
# docs = retriever.invoke(question) | |
# doc_txt = docs[1].page_content | |
# print(retrieval_grader.invoke({"question": question, "document": doc_txt})) | |
#%% | |
from langchain import hub | |
from langchain_core.output_parsers import StrOutputParser | |
# Prompt | |
prompt = hub.pull("rlm/rag-prompt") | |
# LLM | |
# llm = AzureChatOpenAI(model_name="gpt-4o-mini", temperature=0.3) | |
# Post-processing | |
def format_docs(docs): | |
return "\n\n".join(doc.page_content for doc in docs) | |
# Chain | |
rag_chain = prompt | llm | StrOutputParser() | |
# # Run | |
# generation = rag_chain.invoke({"context": docs, "question": question}) | |
# print(generation) | |
#%% | |
### Hallucination Grader | |
# Data model | |
class GradeHallucinations(BaseModel): | |
"""Binary score for hallucination present in generation answer.""" | |
binary_score: str = Field( | |
description="Answer is grounded in the facts, 'yes' or 'no'" | |
) | |
# LLM with function call | |
# llm = AzureChatOpenAI(model="gpt-4o-mini", temperature=0.3) | |
structured_llm_grader = llm.with_structured_output(GradeHallucinations) | |
# Prompt | |
system = """You are a grader assessing whether an LLM generation is grounded in / supported by a set of retrieved facts. \n | |
Give a binary score 'yes' or 'no'. 'Yes' means that the answer is grounded in / supported by the set of facts.""" | |
hallucination_prompt = ChatPromptTemplate.from_messages( | |
[ | |
("system", system), | |
("human", "Set of facts: \n\n {documents} \n\n LLM generation: {generation} \n\n Chat context: {chat_context}"), | |
] | |
) | |
hallucination_grader = hallucination_prompt | structured_llm_grader | |
# hallucination_grader.invoke({"documents": docs, "generation": generation}) | |
#%% | |
### Answer Grader | |
# Data model | |
class GradeAnswer(BaseModel): | |
"""Binary score to assess answer addresses question.""" | |
binary_score: str = Field( | |
description="Answer addresses the question, 'yes' or 'no'" | |
) | |
# LLM with function call | |
# llm = AzureChatOpenAI(model="gpt-4o-mini", temperature=0.3) | |
structured_llm_grader = llm.with_structured_output(GradeAnswer) | |
# Prompt | |
system = """You are a grader assessing whether an answer addresses / resolves a question \n | |
Give a binary score 'yes' or 'no'. Yes' means that the answer resolves the question.""" | |
answer_prompt = ChatPromptTemplate.from_messages( | |
[ | |
("system", system), | |
("human", "User question: \n\n {question} \n\n LLM generation: {generation} \n\n Chat context: {chat_context}"), | |
] | |
) | |
answer_grader = answer_prompt | structured_llm_grader | |
# answer_grader.invoke({"question": question, "generation": generation}) | |
#%% | |
### Question Re-writer | |
# LLM | |
# # llm = AzureChatOpenAI(model="gpt-4o-mini", temperature=0.3) | |
# Prompt | |
system = """You a question re-writer that converts an input question to a better version that is optimized \n | |
for vectorstore retrieval. Look at the input and try to reason about the underlying semantic intent / meaning.""" | |
re_write_prompt = ChatPromptTemplate.from_messages( | |
[ | |
("system", system), | |
( | |
"human", | |
"Here is the initial question: \n\n {question} \n\n Here is the chat context: \n\n {chat_context} \n. Use it to form a better question. Formulate an improved question.", | |
), | |
] | |
) | |
question_rewriter = re_write_prompt | llm | StrOutputParser() | |
# question_rewriter.invoke({"question": question}) | |
class IntentClassifier(BaseModel): | |
"""Classify the intent of the user query.""" | |
intent: Literal["greeting", "legal_query", "follow_up", "off_topic"] = Field( | |
..., | |
description="""Classify the intent of the user query. | |
'greeting' if the user is saying greetings, | |
'legal_query' if the user is asking for information about law, | |
'follow_up' if the user is asking for information related to the previous conversation. If you think the user is referring to a previous conversation, you can classify it as 'follow_up'. | |
'off_topic' if the user is asking for information about anything else.""" | |
) | |
# LLM with function call | |
# llm = AzureChatOpenAI(model="gpt-4o-mini", temperature=0.3) | |
structured_llm_intent_classifier = llm.with_structured_output(IntentClassifier) | |
# Prompt | |
system = """You are an intent classifier that classifies the intent of a user query. \n | |
Give the intent as one of the following: 'greeting', 'legal_query', 'follow_up', 'off_topic'.""" | |
intent_classifier_prompt = ChatPromptTemplate.from_messages( | |
[ | |
("system", system), | |
("human", "Here is the user query: \n\n {question} \n\n Here is the chat context: \n\n {chat_context} \n\n Classify the intent of the user query."), | |
] | |
) | |
intent_classifier = intent_classifier_prompt | structured_llm_intent_classifier | |