Team Ai
Apppublic

Ameer1606/PostgresPro-Support

sourceHugging Facemitupdated 4mo agoView on Hugging Face
0likes
agent.py102 linesDownload Raw Back to src
1from langchain_groq import ChatGroq2from langchain_core.messages import SystemMessage, HumanMessage, AIMessage3from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder4from src.config import LLM_MODEL, COMPANY_NAME, COMPANY_PHONE, COMPANY_EMAIL5from src.retriever import PostgresRetriever6from src.tools import create_database_ticket7 8class SupportAgent:9    def __init__(self):10        self.retriever = PostgresRetriever()11        12        # Initialize the Chat Model with Tools13        self.llm = ChatGroq(model=LLM_MODEL, temperature=0.2)14        self.tools = [create_database_ticket]15        self.llm_with_tools = self.llm.bind_tools(self.tools)16        17        # System Prompt definition18        system_instruction = f"""You are a Customer Support AI for {COMPANY_NAME}.19Contact Info: Phone: {COMPANY_PHONE}, Email: {COMPANY_EMAIL}.20 21Your PRIMARY job is to answer PostgreSQL questions using the documentation context provided below.22 23## STEP 1 — ALWAYS TRY TO ANSWER FIRST24Read the context carefully. If the context contains information relevant to the user's question, answer it fully with citations.25Do NOT call any tool if you can answer from context.26 27## CITATION RULES28Every answer drawn from the context MUST cite the source.29Format: "According to the documentation (Source: <filename>, Page: <page_number>)..."30 31## STEP 2 — ONLY WHEN CONTEXT CANNOT ANSWER32If and only if the context truly cannot answer the question, tell the user that, then offer to create a support ticket.33 34## TICKET CREATION RULES — READ CAREFULLY35- NEVER call `create_database_ticket` unless the user has EXPLICITLY provided all four pieces of info in the conversation: their real name, real email address, a ticket title, and a description.36- NEVER invent, guess, or use placeholder values (like "your_email", "User", "N/A", "unknown") for any field.37- If any of those four fields are missing, ask the user for them first. Do NOT call the tool yet.38- Only call `create_database_ticket` after the user has confirmed their actual details.39 40Context to answer from:41{{context}}42"""43        self.prompt = ChatPromptTemplate.from_messages([44            ("system", system_instruction),45            MessagesPlaceholder(variable_name="chat_history"),46            ("user", "{input}"),47            MessagesPlaceholder(variable_name="agent_scratchpad"),48        ])49        50    def run(self, user_input: str, chat_history: list) -> str:51        """Process user input with the current chat history."""52        # Windowed history: keep only last 6 messages (3 interactions)53        windowed_history = chat_history[-6:] if len(chat_history) > 6 else chat_history54 55        # 1. Retrieve Context56        context = self.retriever.get_relevant_context(user_input)57        58        # 2. Format Messages59        messages = self.prompt.format_messages(60            context=context,61            chat_history=windowed_history,62            input=user_input,63            agent_scratchpad=[]64        )65        66        # 3. Call LLM67        response = self.llm_with_tools.invoke(messages)68        69        # 4. Handle Tool Calls70        if response.tool_calls:71            tool_call = response.tool_calls[0]72            if tool_call["name"] == "create_database_ticket":73                args = tool_call["args"]74                75                # Placeholder values that indicate the LLM hallucinated the fields76                PLACEHOLDERS = {77                    "your_email", "user", "n/a", "unknown", "none", "example",78                    "your_name", "your name", "your email", "placeholder",79                    "test@example.com", "user@example.com",80                }81                82                # Required fields check — also catches placeholders83                missing = []84                for field in ("name", "email", "title", "description"):85                    val = args.get(field, "").strip().lower()86                    if not val or val in PLACEHOLDERS:87                        missing.append(field)88                89                if missing:90                    return (91                        f"To create a support ticket I'll need a few details from you. "92                        f"Could you please provide your **{', '.join(missing)}**?"93                    )94                95                # Execute tool96                tool_result = create_database_ticket.invoke(args)97                return f"I've attempted to create the ticket.\n\n{tool_result}"98                99        # 5. Return standard text response100        return response.content101 102