from langchain_core.messages import SystemMessage, HumanMessage from typing import List, Dict, Any import time import requests import gradio as gr from data import debug_print,all_card_names,all_card_lookup,eligibility_lookup,df from nodes.intent import get_pretty_state_string from langgraph_pipeline import run_langgraph_pipeline,utility_app #Gradio UI with the fucntion calls to invoke the graphs and pass the user inputs custom_css=""" #compare_output_markdown, #full_compare_output_markdown, #top_card_markdown { min-height: 100px; border: 1px solid #e0e0e0; padding: 10px; overflow-y: auto; } #left_column_box, #right_column_box { padding: 16px !important; /* Adds 16px of space INSIDE the bordered box */ } """ with gr.Blocks(title="Agentic Credit Card Recommender", css=custom_css, theme=gr.themes.Soft()) as demo: gr.Markdown(""" # Credit Card Recommender Discover and receive personalized recommendations for credit cards based on your needs and preferences """) with gr.Tab("Get Recommendations"): with gr.Row(): query_input = gr.Textbox( label="What kind of card are you looking for?", placeholder="Best cards for online shopping with fuel benefits", elem_id="query-textbox", scale=2 ) preferences = gr.Dropdown( choices=["Cashback", "Travel", "Fuel", "Airport Lounge access", "Railways", "Dining", "Online Spends", "Grocery"], multiselect=True, label="Select Preferred Card Categories", scale=1 ) with gr.Accordion("Eligibility & Fee Filters", open=False): with gr.Row(): income = gr.Slider(minimum=1, maximum=60, step=1, label="Annual Income (LPA)") cibil = gr.Slider(minimum=300, maximum=900, step=10, label="CIBIL Score") age = gr.Slider(minimum=18, maximum=75, step=1, label="Age") with gr.Row(): with gr.Group(): gr.Markdown("
Preferred Joining Fee (₹)
") with gr.Row(): min_joining_fee = gr.Number(label="Min", value=0) max_joining_fee = gr.Number(label="Max", value=150000) with gr.Group(): gr.Markdown("Preferred Annual Fee (₹)
") with gr.Row(): min_annual_fee = gr.Number(label="Min", value=0) max_annual_fee = gr.Number(label="Max", value=150000) with gr.Row(): use_eligibility = gr.Checkbox(label="Apply Eligibility Filter", value=False) fd_checkbox = gr.Checkbox(label="Beginner / Student", value=False) cobrand_checkbox = gr.Checkbox(label="Include Co-branded Cards", value=True) run_button = gr.Button("Recommend Cards", variant='primary') top_card_recommendation = gr.Markdown(value="", elem_id="top_card_markdown") with gr.Row(visible=True) as results_container: with gr.Column(): with gr.Group(elem_id="left_column_box"): recommendation_heading = gr.Markdown("### Top-Ranked Cards") card_table_markdown = gr.Markdown() with gr.Column(): with gr.Group(elem_id="right_column_box"): card_links_heading = gr.Markdown("### 🔗 Issuer Links") card_links_html = gr.HTML() with gr.Column(visible=False) as chat_container: with gr.Accordion("💬 Ask Follow-up Questions", open=True): chatbox = gr.Chatbot(type="messages", label="Chat") followup_input = gr.Textbox(label="Enter Your question", placeholder="Compare the lounge access benefits of card X and card Y") followup_submit = gr.Button("Submit", variant="primary") with gr.Tab("Compare Cards"): with gr.Column(visible=False) as compare_recommended_cards_container: gr.Markdown("## Compare Recommended Cards") compare_checkboxes = gr.CheckboxGroup(choices=[], label="Select 2 or more cards to compare", info="Pick from the recommended list to see a comparison.") compare_btn = gr.Button("Compare Selected Cards", variant='primary') compare_output = gr.Markdown(value="", elem_id="compare_output_markdown") gr.Markdown("---") gr.Markdown("## Compare Any Cards") full_compare_dropdown = gr.Dropdown(choices=all_card_names, multiselect=True, label="Select 2 or more cards", info="Compare any cards from the entire database.") full_compare_btn = gr.Button("Compare Selected Cards", variant='primary') full_compare_output = gr.Markdown(value="", elem_id="full_compare_output_markdown") def format_to_markdown(top_card_out, top_card_description_out): debug_print("UI", f"Formatting top card output to markdown") if not top_card_out and top_card_description_out: message_block = "\n".join(f"- {desc}" for desc in top_card_description_out if desc) return f"### Note\n\n{message_block}\n\n" top_card_recommendation = f"### Best card: {top_card_out}\n\n" if top_card_description_out: for desc in top_card_description_out: if isinstance(desc, str): desc = desc.strip() if desc: top_card_recommendation += f"- {desc}\n" return top_card_recommendation def format_rows_to_markdown_table(card_rows): """Converts a list of card data into a markdown table string.""" if not card_rows: return "" markdown_table = "| Card Name | Joining Fee | Annual Fee |\n" markdown_table += "|---|---|---|\n" for row in card_rows: name = row[0] joining_fee = row[1] annual_fee = row[2] markdown_table += f"| {name} | {joining_fee} | {annual_fee} |\n" return markdown_table #main function that invokes the graph async def recommend(query, preferences, fd_intent, include_cobranded, income, cibil, age, min_joining_fee, max_joining_fee, min_annual_fee, max_annual_fee, use_eligibility): debug_print("UI", f"recommend called with query: '{query}'") debug_print("UI", f"Preferences: {preferences}") debug_print("UI", f"FD intent: {fd_intent}, Include cobranded: {include_cobranded}") global chat_history chat_history = [] global messages messages = [] preferences_text="" if preferences: preferences_text = "User selected preferences: " + ", ".join(preferences) + "." query = query.strip() if query else "" if not query: error_message = "Please enter a valid query." debug_print("UI", f"recommend function error: {error_message}") return error_message, gr.update(visible=True), gr.update(value=None), gr.update(visible=False), gr.update(visible=False), gr.update(value=None), gr.update(visible=False), [], {}, "", gr.update(visible=False),{} try: debug_print("UI", f"Calling run_langgraph_pipeline") top_card_out, top_card_description_out, card_rows_out, card_names_out, card_lookup_out,card_links = await run_langgraph_pipeline( query, preferences_text, query_intent=fd_intent, include_cobranded=include_cobranded, use_eligibility=use_eligibility, income=income, cibil=cibil, age=age, min_joining_fee=min_joining_fee, max_joining_fee=max_joining_fee, min_annual_fee=min_annual_fee, max_annual_fee=max_annual_fee ) debug_print("UI", f"Pipeline returned {len(card_rows_out)} card rows") recommendation_visible = bool(top_card_out) or bool(top_card_description_out) df_visible = bool(card_rows_out) chat_container_visible = gr.update(visible=True if card_rows_out else False) top_card_md = format_to_markdown(top_card_out, top_card_description_out) card_table_md = format_rows_to_markdown_table(card_rows_out) debug_print("UI", f"recommend function completed successfully") initial_context = { "query": query, "top_cards": card_names_out[:5], "recommendation_summary": top_card_md } card_links_section = "