this is our enhansed chat agent code
class EnhancedChatAgent:
    def __init__(self, client, is_azure):
        self.client = client
        self.is_azure = is_azure
        self.question_types = {
            'tariff_impact': 'Analyzing tariff rate changes and their financial impacts',
            'timeline': 'Identifying implementation timelines and deadlines',
            'geopolitical': 'Evaluating geopolitical factors affecting trade policies',
            'comparison': 'Comparing policies across different regions',
            'compliance': 'Checking regulatory compliance requirements',
            'general': 'General analysis on the Question asked by user',
            'greetings': 'Greetings and general inquiries',
        }

    def classify_question(self, question):
        prompt = f"""
Classify this question into one of these categories: {list(self.question_types.keys())}.
Return only the category name.

Question: {question}
"""
        if self.is_azure:
            messages = [
                {"role": "system", "content": "Expert question classifier for Macy's analysis"},
                {"role": "user", "content": prompt},
            ]
            response = self.client.generate(messages=messages, temperature=0)
            return response.choices[0].message.content.strip().lower()
        else:
            return self.client.generate("Expert question classifier for Macy's analysis", prompt).strip().lower()

    def generate_answer(self, question, files_context):
        q_type = self.classify_question(question)

        if q_type == 'greetings':
            greeting_prompt = f"""
You are an senior assistant responding ONLY to greetings from Macy's executive staff. Reply with a polite greeting message only. No additional information but respond properly for every question do not use any other source.

Greeting input:
{question}

Your reply:
"""
            if self.is_azure:
                messages = [
                    {"role": "system", "content": "Assistant specialized in greeting responses."},
                    {"role": "user", "content": greeting_prompt}
                ]
                response = self.client.generate(messages=messages, temperature=0)
                return response.choices[0].message.content.strip(), q_type
            else:
                return self.client.generate("Assistant specialized in greeting responses.", greeting_prompt), q_type

        analysis_approach = self.question_types.get(q_type, "General analysis")

        base_prompt = f"""
You are a senior analyst answering questions for Macy's executive team. Follow these steps:

1. {analysis_approach}
2. Cross-reference all relevant documents
3. Identify numerical data and timelines
4. Assess impacts on retail operations
5. Formulate executive-level recommendations
6. If user asks about a single document and multiple selected, answer from only that one.
7. If user asks about multiple documents, synthesize across all.
8. Greetings get polite greeting responses only.

Current question type: {q_type.upper()}

Question: {question}

Relevant documents:
{files_context}

Provide a structured response with:
- Clear headings
- Bullet points for key findings
- Bolded key figures and dates
- Separate recommendations section

If information conflicts between documents, note explicitly.
"""
        if self.is_azure:
            messages = [
                {"role": "system", "content": "Senior analyst synthesizing information from multiple documents"},
                {"role": "user", "content": base_prompt},
            ]
            response = self.client.generate(messages=messages, temperature=0)
            return response.choices[0].message.content.strip(), q_type
        else:
            return self.client.generate("Senior analyst synthesizing information from multiple documents", base_prompt), q_type


this is my main.py

import streamlit as st
from io import BytesIO
from datetime import datetime

from utils.pdf_utils import extract_text
from clients.azure_client import AzureClient
from clients.gemini_client import GeminiClient

from agents.tariff_agent import TariffTradeAgent
from agents.sales_agent import SalesAgent
from agents.supply_chain_agent import SupplyChainAgent
from agents.overall_agent import OverallAgent
from agents.enhanced_chat_agent import EnhancedChatAgent

def analyze_documents(mode, agent, processed_files, sess):
    for filename, file_bytes in sess['uploaded_files'].items():
        if filename not in processed_files:
            try:
                file_obj = BytesIO(file_bytes)
                file_obj.name = filename
                text = extract_text(file_obj)
                if text:
                    topics = agent.analyze_document(text)
                    processed_files[filename] = {
                        "text": text,
                        "topics": topics,
                        "context": text,
                    }
                    st.toast(f"✅ Processed {filename}")
                else:
                    st.error(f"❌ Failed to extract text for {filename}")
            except Exception as e:
                st.error(f"Error processing {filename}: {str(e)}")

    with st.spinner(f"Generating consolidated summary for {mode}..."):
        summary = agent.generate_consolidated_summary_from_topics(processed_files)
        if mode == "overall":
            sess['consolidated_summary_overall'] = summary
        elif mode == "tariff":
            sess['consolidated_summary_tariff'] = summary
        elif mode == "sales":
            sess['consolidated_summary_sales'] = summary
        elif mode == "supplychain":
            sess['consolidated_summary_supplychain'] = summary

    sess['last_analysis_mode'] = mode
    sess['active_file'] = None
    sess['active_topic'] = None
    st.success(f"Analysis and summary generated for {mode}.")

def main():
    st.set_page_config(page_title="Macy's Document Analysis Pro", layout="wide")
    st.title("📄 Macy's Document Analysis & Chat Tool")

    # Mode selection (Azure or Gemini)
    provider_select = st.radio("Select AI Provider", ["Azure GPT", "Google Gemini"])

    # Session Initialization
    if "session" not in st.session_state:
        st.session_state.session = {
            'uploaded_files': {},
            'processed_files_overall': {},
            'processed_files_tariff': {},
            'processed_files_sales': {},
            'processed_files_supplychain': {},
            'active_file': None,
            'active_topic': None,
            'topic_details_cache': {},
            'chat_history': [],
            'consolidated_summary_overall': None,
            'consolidated_summary_tariff': None,
            'consolidated_summary_sales': None,
            'consolidated_summary_supplychain': None,
            'last_analysis_mode': None
        }

    if "client" not in st.session_state or st.session_state.get("provider") != provider_select:
        # Initialize clients and agents based on selection
        if provider_select == "Azure GPT":
            st.session_state.client = AzureClient()
            is_azure = True
        else:
            st.session_state.client = GeminiClient()
            is_azure = False

        # Setup agents
        st.session_state.agent_overall = OverallAgent(st.session_state.client, is_azure)
        st.session_state.agent_tariff = TariffTradeAgent(st.session_state.client, is_azure)
        st.session_state.agent_sales = SalesAgent(st.session_state.client, is_azure)
        st.session_state.agent_supplychain = SupplyChainAgent(st.session_state.client, is_azure)
        st.session_state.chat_agent = EnhancedChatAgent(st.session_state.client, is_azure)
        st.session_state.provider = provider_select

    sess = st.session_state.session

    # --- File Upload Section ---
    st.subheader("1. Upload Documents")
    uploaded_files = st.file_uploader(
        "Upload Macy's earnings transcript PDFs",
        type=["pdf"],
        accept_multiple_files=True,
        key="file_uploader",
    )
    if uploaded_files:
        new_files_added = False
        for file in uploaded_files:
            if file.name not in sess['uploaded_files']:
                sess['uploaded_files'][file.name] = file.getvalue()
                new_files_added = True

        # Automatically trigger overall analysis on new uploads
        if new_files_added:
            analyze_documents(
                mode="overall",
                agent=st.session_state.agent_overall,
                processed_files=sess['processed_files_overall'],
                sess=sess
            )

    # --- Analysis Buttons Section ---
    st.subheader("2. Analyze Documents")
    col0, col1, col2, col3 = st.columns(4)
    analyze_overall = col0.button("📑 Overall Summary")
    analyze_tariff = col1.button("🔍 Analyze Tariffs & Trade")
    analyze_sales = col2.button("📈 Analyze Sales & Consumer Behavior")
    analyze_supplychain = col3.button("🚚 Analyze Supply Chain & Logistics")

    mode = None
    agent = None
    processed_files = None

    if analyze_overall or analyze_tariff or analyze_sales or analyze_supplychain:
        if not sess['uploaded_files']:
            st.error("Please upload documents before analyzing.")
            st.stop()

        if analyze_overall:
            mode = "overall"
            agent = st.session_state.agent_overall
            processed_files = sess['processed_files_overall']
        elif analyze_tariff:
            mode = "tariff"
            agent = st.session_state.agent_tariff
            processed_files = sess['processed_files_tariff']
        elif analyze_sales:
            mode = "sales"
            agent = st.session_state.agent_sales
            processed_files = sess['processed_files_sales']
        elif analyze_supplychain:
            mode = "supplychain"
            agent = st.session_state.agent_supplychain
            processed_files = sess['processed_files_supplychain']

        analyze_documents(mode, agent, processed_files, sess)

    # --- Show consolidated summary and topics ---
    last_mode = sess['last_analysis_mode']
    if last_mode is None:
        st.info("Select an analysis type above to get started.")
        return

    if last_mode == "overall":
        processed_files = sess['processed_files_overall']
        consolidated_summary = sess['consolidated_summary_overall']
        sidebar_header = "Overall Topics"
        main_header = "🌟 Consolidated Executive Summary"
        agent = st.session_state.agent_overall
    elif last_mode == "tariff":
        processed_files = sess['processed_files_tariff']
        consolidated_summary = sess['consolidated_summary_tariff']
        sidebar_header = "Tariff Topics"
        main_header = "🌟 Consolidated Tariff & Trade Summary"
        agent = st.session_state.agent_tariff
    elif last_mode == "sales":
        processed_files = sess['processed_files_sales']
        consolidated_summary = sess['consolidated_summary_sales']
        sidebar_header = "Sales Topics"
        main_header = "🌟 Consolidated Sales & Consumer Behavior Summary"
        agent = st.session_state.agent_sales
    else:  # supplychain
        processed_files = sess['processed_files_supplychain']
        consolidated_summary = sess['consolidated_summary_supplychain']
        sidebar_header = "Supply Chain Topics"
        main_header = "🌟 Consolidated Supply Chain & Logistics Summary"
        agent = st.session_state.agent_supplychain

    # --- Display Topics in Sidebar ---
    st.sidebar.header(sidebar_header)

    if last_mode == "overall":
        # Aggregate topics across all documents
        topics_by_file = {}
        for filename, filedata in processed_files.items():
            for topic in filedata["topics"]:
                topics_by_file.setdefault(topic['name'], []).append({
                    'file': filename,
                    'score': topic['score']
                })

        # Display aggregated topics
        for topic_name, occurrences in sorted(topics_by_file.items(),
                                           key=lambda x: max(x[1], key=lambda y: y['score'])['score'],
                                           reverse=True):
            total_score = sum(occ['score'] for occ in occurrences)
            file_count = len(occurrences)
            btn_label = f"{topic_name} (📈 {total_score:.1f} | 📑 {file_count})"

            if st.sidebar.button(
                btn_label,
                key=f"overall_topic_{topic_name}",
                use_container_width=True,
            ):
                sess['active_topic'] = topic_name
                sess['active_file'] = None  # Clear active file when selecting topic cross-doc
    else:
        # Original per-file topic display
        for filename, filedata in processed_files.items():
            expanded = (filename == sess['active_file'])
            with st.sidebar.expander(f"📄 {filename}", expanded=expanded):
                topics = sorted(filedata["topics"], key=lambda t: t["score"], reverse=True)
                for topic in topics:
                    is_selected = (
                        sess['active_file'] == filename and sess['active_topic'] == topic['name']
                    )
                    style = "primary" if is_selected else "secondary"

                    if st.button(
                        f"• {topic['name']} (Score: {topic['score']})",
                        key=f"{last_mode}_topic_{filename}_{topic['name']}",
                        type=style,
                        use_container_width=True,
                    ):
                        sess['active_file'] = filename
                        sess['active_topic'] = topic['name']

    # --- DETAILED TOPIC ANALYSIS ---
    st.subheader("Detailed Topic Analysis")
    if last_mode == "overall" and sess['active_topic']:
        # Cross-document topic analysis
        st.subheader(f"Cross-Document Analysis: {sess['active_topic']}")

        # Collect all relevant mentions
        mentions = []
        for filename, filedata in processed_files.items():
            for topic in filedata["topics"]:
                if topic['name'] == sess['active_topic']:
                    mentions.append({
                        'file': filename,
                        'summary': topic.get('summary', ''),
                        'score': topic['score'],
                        'context': filedata['context']
                    })

        # Display prevalence metrics
        with st.expander("📊 Topic Prevalence Across Documents"):
            cols = st.columns(3)
            cols[0].metric("Total Documents", len(mentions))
            avg_relevance = (sum(m['score'] for m in mentions)/len(mentions)) if mentions else 0
            cols[1].metric("Average Relevance", f"{avg_relevance:.1f}")
            cols[2].metric("First Mentioned", mentions[0]['file'] if mentions else "N/A")

        # Generate deep analysis
        if mentions:
            combined_context = "\n\n".join(
                f"=== {m['file']} ===\n{m['context']}"
                for m in mentions
            )
            key_cache = (last_mode, sess['active_topic'])
            if key_cache in sess['topic_details_cache']:
                st.markdown(sess['topic_details_cache'][key_cache])
            else:
                placeholder = st.empty()
                collected_text = ""

                try:
                    for chunk in agent.generate_topic_detail(combined_context, sess['active_topic']):
                        if chunk:
                            collected_text = chunk
                            if "▌" in collected_text:
                                # Streaming in progress
                                placeholder.markdown(collected_text)
                            else:
                                # Final chunk
                                placeholder.markdown(collected_text)
                                sess['topic_details_cache'][key_cache] = collected_text
                except Exception as e:
                    st.error(f"Error generating analysis: {str(e)}")
                    sess['topic_details_cache'][key_cache] = f"Error: {str(e)}"
        else:
            st.warning("No document mentions found for this topic")

    elif sess['active_file'] and sess['active_topic']:
        # Original single-document analysis
        key_cache = (last_mode, sess['active_file'], sess['active_topic'])
        if key_cache in sess['topic_details_cache']:
            st.markdown(sess['topic_details_cache'][key_cache])
        else:
            placeholder = st.empty()
            collected_text = ""

            try:
                for chunk in agent.generate_topic_detail(
                    processed_files[sess['active_file']]['context'],
                    sess['active_topic'],
                ):
                    if chunk:
                        collected_text = chunk
                        if "▌" in collected_text:
                            placeholder.markdown(collected_text)
                        else:
                            placeholder.markdown(collected_text)
                            sess['topic_details_cache'][key_cache] = collected_text
            except Exception as e:
                st.error(f"Error showing topic detail: {str(e)}")
                sess['topic_details_cache'][key_cache] = f"Error: {str(e)}"
    else:
        st.info("Select a file and topic from the sidebar to view detailed analysis.")

    st.markdown("---")

    # --- CONSOLIDATED SUMMARY ---
    st.header(main_header)
    if consolidated_summary:
        st.markdown(consolidated_summary)
    else:
        st.info(f"No consolidated summary available for {last_mode.capitalize()} yet.")

    st.divider()

    # --- Advanced Chat: Tariff & Trade Policies ---
    st.subheader("💬 Advanced Document Analysis (Tariff & Trade)")
    tariff_files = list(sess['processed_files_tariff'].keys())
    selected_files = st.multiselect("Select documents for question answering:", tariff_files)

    for msg in sess['chat_history']:
        with st.chat_message(msg["role"]):
            st.markdown(msg["content"])

    question = st.chat_input("Ask a question about tariffs and trade policies")
    if question:
        if not selected_files:
            st.error("Select one or more documents for context before asking a question.")
            st.stop()

        sess['chat_history'].append({
            "role": "user",
            "content": question,
            "timestamp": datetime.utcnow().isoformat(),
        })

        if len(selected_files) == 1:
            context = sess['processed_files_tariff'][selected_files[0]]['context']
        else:
            context = "\n\n".join([
                f"=== Document: {fname} ===\n{sess['processed_files_tariff'][fname]['context']}"
                for fname in selected_files
            ])

        try:
            answer, q_type = st.session_state.chat_agent.generate_answer(question, context)
            sess['chat_history'].append({
                "role": "assistant",
                "content": answer,
                "timestamp": datetime.utcnow().isoformat(),
                "analysis_type": q_type
            })
            st.chat_message("assistant").markdown(answer)
        except Exception as e:
            st.error(f"Error during chat: {str(e)}")
            sess['chat_history'].append({
                "role": "assistant",
                "content": f"Error: {str(e)}",
                "timestamp": datetime.utcnow().isoformat(),
            })

    if st.button("🔄 Reset Session", type="secondary"):
        preserved_keys = [
            "client", "agent_overall", "agent_tariff",
            "agent_sales", "agent_supplychain", "chat_agent", "provider"
        ]
        preserved = {k: st.session_state[k] for k in preserved_keys if k in st.session_state}
        st.session_state.clear()
        st.session_state.update(preserved)
        st.session_state.session = {
            'uploaded_files': {},
            'processed_files_overall': {},
            'processed_files_tariff': {},
            'processed_files_sales': {},
            'processed_files_supplychain': {},
            'active_file': None,
            'active_topic': None,
            'topic_details_cache': {},
            'chat_history': [],
            'consolidated_summary_overall': None,
            'consolidated_summary_tariff': None,
            'consolidated_summary_sales': None,
            'consolidated_summary_supplychain': None,
            'last_analysis_mode': None,
        }
        st.rerun()

if __name__ == "__main__":
    main()


i wan to make my chat responses as streamline so make it only do not change anything else