Download chains.py from Pavan2k4/rag: direct link, hf CLI and curl.
- Browser
- Download file 9.85 kB
-
https://huggingface.co/spaces/Pavan2k4/rag/resolve/main/chains.py
- Command line
-
hf download hf://spaces/Pavan2k4/rag/chains.py
-
curl -L -o chains.py https://huggingface.co/spaces/Pavan2k4/rag/resolve/main/chains.py
9.85 kB
| """All prompts utilized by the RAG pipeline""" | |
| from langchain_core.prompts import ChatPromptTemplate, PromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder | |
| from langchain_core.output_parsers import StrOutputParser | |
| from langchain_openai import ChatOpenAI | |
| from pydantic import BaseModel, Field | |
| from langchain_google_genai import ChatGoogleGenerativeAI | |
| import os | |
| from tools import json_to_table, goal_feasibility, save_data, rag_tool | |
| from langchain.agents import initialize_agent, Tool | |
| from langchain.agents import AgentType | |
| from langgraph.prebuilt import create_react_agent | |
| from langchain.tools import Tool | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| gemini = ChatGoogleGenerativeAI(model = 'gemini-2.0-flash') | |
| llm = ChatOpenAI( | |
| model='gpt-4.1-nano', | |
| api_key=os.environ.get('OPEN_AI_KEY'), | |
| temperature=0.2 | |
| ) | |
| # Schema for grading documents | |
| class GradeDocuments(BaseModel): | |
| binary_score: str = Field(description="Documents are relevant to the question, 'yes' or 'no'") | |
| structured_llm_grader = llm.with_structured_output(GradeDocuments) | |
| system = """You are a grader assessing relevance of a retrieved document to a user question. | |
| If the document contains keyword(s) or semantic meaning related to the question, grade it as relevant. | |
| Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question.""" | |
| grade_prompt = ChatPromptTemplate.from_messages([ | |
| ("system", system), | |
| ("human", "Retrieved document: \n\n {data} \n\n User question: {query}") | |
| ]) | |
| retrieval_grader = grade_prompt | structured_llm_grader | |
| prompt = PromptTemplate( | |
| template=''' | |
| You are a SEBI-Registered Investment Advisor (RIA) specializing in Indian financial markets and client relationship management. | |
| Your task is to understand and respond to the user's financial query using the following inputs: | |
| - Query: {query} | |
| - Documents: {data} | |
| - User Profile: {user_data} | |
| - Savings Allocations: {allocations} | |
| Instructions: | |
| 1. Understand the User's Intent: Carefully interpret what the user is asking about their investments. | |
| 2. Analyze Allocations: Evaluate the savings allocation data to understand the user's current financial posture. | |
| 3. Personalized Response: | |
| - If detailed user profile and allocation data are available, prioritize your response based on this data. | |
| - If profile or allocation data is sparse, rely more heavily on the query context. | |
| 4. Use Supporting Documents: Extract relevant insights from the provided documents ({data}) to support your answer. | |
| 5. When Unsure: If the documents or data do not contain the necessary information, say "I don't know" rather than guessing. | |
| Always aim to give a response that is: | |
| - Data-informed | |
| - Client-centric | |
| - Aligned with Indian financial regulations and norms | |
| ''', | |
| input_variables=['query', 'data', 'user_data', 'allocations'] | |
| ) | |
| rag_chain = prompt | gemini | StrOutputParser() | |
| # Prompt | |
| system_rewrite = """You a question re-writer that converts an input question to a better version that is optimized \n | |
| for web search. Look at the input and try to reason about the underlying semantic intent / meaning.""" | |
| re_write_prompt = ChatPromptTemplate.from_messages( | |
| [ | |
| ("system", system_rewrite), | |
| ( | |
| "human", | |
| "Here is the initial question: \n\n {query} \n Formulate an improved question.", | |
| ), | |
| ] | |
| ) | |
| question_rewriter = re_write_prompt | llm | StrOutputParser() | |
| from pydantic import BaseModel, Field, RootModel | |
| from typing import Dict | |
| from langchain_core.output_parsers import JsonOutputParser | |
| # Define the Pydantic model using RootModel | |
| class CategoryProbabilities(RootModel): | |
| """Probabilities for different knowledge base categories.""" | |
| root: Dict[str, float] = Field(description="Dictionary mapping category names to probability scores") | |
| system_classifier = """You are a query classifier that determines the most relevant knowledge bases (KBs) for a given user query. | |
| Analyze the semantic meaning and intent of the query and assign probability scores (between 0 and 1) to each KB. | |
| Ensure the probabilities sum to 1 and output a JSON dictionary with category names as keys and probabilities as values. | |
| """ | |
| classification_prompt = ChatPromptTemplate.from_messages( | |
| [ | |
| ("system", system_classifier), | |
| ( | |
| "human", | |
| "Here is the user query: \n\n {query} \n\n Assign probability scores to each of the following KBs:\n" | |
| "{categories}\n\nReturn a JSON object with category names as keys and probability scores as values." | |
| ), | |
| ] | |
| ) | |
| # Create a JSON output parser | |
| json_parser = JsonOutputParser(pydantic_object=CategoryProbabilities) | |
| # Create the chain with the structured output parser | |
| query_classifier = classification_prompt | llm | json_parser | |
| #query_classifier = classification_prompt | llm | StrOutputParser() | |
| """ | |
| name: str | |
| position: Dict[str, int] | |
| riskiness: int | |
| illiquidity: int | |
| amount: float | |
| currency: str = "inr" | |
| percentage: float | |
| explanation: Dict[str, str] | |
| assets: List[AssetAllocation] | |
| """ | |
| #-------------------------------------------------------------------------------------- | |
| tools = [ | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "json_to_table", | |
| "description": "Convert JSON data to a markdown table. Use when user asks to visualise or tabulate structured data.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "arguments": { | |
| "type": "object", | |
| "properties": { | |
| "json_data": { | |
| "type": "object", | |
| "description": "The JSON data to convert to a table" | |
| } | |
| }, | |
| "required": ["json_data"] | |
| } | |
| }, | |
| "required": ["arguments"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "rag_tool", | |
| "description": "Lets the agent use RAG system as a tool", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "arguments": { | |
| "type": "object", | |
| "properties": { | |
| "query": { | |
| "type": "string", | |
| "description": "The query to search for in the RAG system" | |
| } | |
| }, | |
| "required": ["query"] | |
| } | |
| }, | |
| "required": ["arguments"] | |
| } | |
| } | |
| } | |
| ] | |
| template = '''You are a SEBI-Registered Investment Advisor (RIA) specializing in Indian financial markets and client relationship management. | |
| Your task is to understand and respond to the user's financial query using the following inputs: | |
| - Query: {query} | |
| - User Profile: {user_data} | |
| - Savings Allocations: {allocations} | |
| - Chat History: {chat_history} | |
| - π Retrieved Context (optional): {retrieved_context} | |
| Instructions: | |
| 1. **Understand the User's Intent**: Carefully interpret what the user is asking about their investments. If a user input contradicts previously stated preferences or profile attributes (e.g., low risk appetite or crypto aversion), ask a clarifying question before proceeding. Do not update allocations or goals unless the user confirms the change explicitly. | |
| 2. **Analyze Allocations**: Evaluate the savings allocation data to understand the user's current financial posture. | |
| 3. **Use Retrieved Context**: If any contextual information is provided in `retrieved_context`, leverage it to improve your response quality and relevance. | |
| 4. **Always Update Information**: If the user shares any new demographic, financial, or preference-related data, update the user profile accordingly. If they request changes in their allocations, ensure the changes are applied **proportionally** and that the total allocation always sums to 100%. | |
| 5. **IMPORTANT: When displaying or updating allocations, you MUST format the data as a Markdown table and always display allocations as a table only** using the following columns: | |
| - Asset Class | |
| - Type | |
| - Label | |
| - Old Amount (βΉ) | |
| - Change (βΉ) | |
| - New Amount (βΉ) | |
| - Justification | |
| 7. **Maintain Conversational Memory**: Ensure updates are passed to memory using the specified `updates` structure. | |
| 8. **Tool Use Policy**: | |
| - β Use `rag_tool` for retrieving **external financial knowledge or regulation** context when necessary. | |
| --- | |
| ### π― Response Style Guide: | |
| - π Keep it under 300 words. | |
| - π Friendly tone: be warm and helpful. | |
| - π Structured: use bullet points, short paragraphs, and headers. | |
| - π Visually clear: break sections clearly. | |
| - π Use emojis to guide attention and convey tone. | |
| - π― Be direct and focused on the user's request. | |
| --- | |
| ### π If There Are Allocation Changes: | |
| You **must** display a Markdown table as per the format above. Then, return memory update instructions using this JSON structure: | |
| ```json | |
| {{ | |
| "updates": {{ | |
| "user_data": {{ ... }}, // Include only changed fields | |
| "allocations": {{...}} // Include only changed rows | |
| }} | |
| }} | |
| ''' | |
| # Create the prompt template | |
| simple_prompt = ChatPromptTemplate.from_messages([ | |
| SystemMessagePromptTemplate.from_template(template=template), | |
| MessagesPlaceholder(variable_name="chat_history", optional=True), | |
| HumanMessagePromptTemplate.from_template("User Query: {query}"), | |
| HumanMessagePromptTemplate.from_template("Current User Profile:\n{user_data}"), | |
| HumanMessagePromptTemplate.from_template("Current Allocations:\n{allocations}"), | |
| HumanMessagePromptTemplate.from_template("π Retrieved Context (if any):\n{retrieved_context}"), | |
| ]) | |
| # Create the chain with direct tool binding | |
| llm = ChatOpenAI( | |
| temperature=0.1, | |
| model="gpt-4.1-nano", | |
| ) | |
| llm_with_tools = llm.bind_tools(tools) | |
| simple_chain = simple_prompt | llm_with_tools | |