|
|
from data import debug_print,eligibility_lookup,llm1 |
|
|
from nodes.intent import get_pretty_state_string,CreditCardState |
|
|
from langchain_core.messages import SystemMessage, HumanMessage |
|
|
|
|
|
|
|
|
async def compare_node_fn(state: CreditCardState) -> CreditCardState: |
|
|
debug_print("NODE", f"Entering compare_node_fn with state:\n {get_pretty_state_string(state)}\n") |
|
|
|
|
|
selected_cards = state.get("selected_cards", []) |
|
|
card_lookup = state.get("card_lookup", {}) |
|
|
|
|
|
debug_print("COMPARE_NODE", f"Selected cards: {selected_cards}") |
|
|
debug_print("COMPARE_NODE", f"Card lookup keys: {list(card_lookup.keys())}") |
|
|
if not selected_cards or len(selected_cards) < 2: |
|
|
debug_print("COMPARE_NODE", "Not enough cards selected for comparison") |
|
|
state["comparison_result"] = "Please select at least two cards to compare." |
|
|
return state |
|
|
|
|
|
comparison_details = [] |
|
|
for name in selected_cards: |
|
|
eligibility_info = eligibility_lookup.get(name, "No eligibility or fee information available.") |
|
|
desc = card_lookup.get(name, "No description available.") |
|
|
full_desc = f"{desc}\n\nEligibility & Fees:\n{eligibility_info}" |
|
|
comparison_details.append(f"{name}: {full_desc}") |
|
|
debug_print("COMPARE_NODE", f"Added card '{name}' with description length: {len(desc)}") |
|
|
|
|
|
use_table_format = len(selected_cards) <= 3 |
|
|
|
|
|
|
|
|
if use_table_format: |
|
|
header_row = "| Feature | " + " | ".join(selected_cards) + " |" |
|
|
separator_row = "|---|" + "---|" * len(selected_cards) |
|
|
|
|
|
benefits_structure = "| Benefits | " + " | ".join(["[3-4 key benefits]<br>[as concise bullet points]"] * len(selected_cards)) + " |" |
|
|
fees_structure = "| Fees & Eligibility | " + " | ".join(["[Key fees & eligibility as bullet points]"] * len(selected_cards)) + " |" |
|
|
limitations_structure = "| Limitations | " + " | ".join(["[List any limitations as bullet points]"] * len(selected_cards)) + " |" |
|
|
ideal_user_structure = "| Ideal User | " + " | ".join(["[A single short sentence]"] * len(selected_cards)) + " |" |
|
|
|
|
|
dynamic_table_blueprint = ( |
|
|
f"{header_row}\n" |
|
|
f"{separator_row}\n" |
|
|
f"{benefits_structure}\n" |
|
|
f"{fees_structure}\n" |
|
|
f"{limitations_structure}\n" |
|
|
f"{ideal_user_structure}\n" |
|
|
) |
|
|
|
|
|
comparison_prompt = ( |
|
|
"Compare the following credit cards using the exact and complete **markdown table** structure provided below.\n\n" |
|
|
f"{dynamic_table_blueprint}\n" |
|
|
"Instructions:\n" |
|
|
"1. **STRICTLY adhere to the table structure.**\n" |
|
|
"2. **DO NOT GUESS OR HALLUCINATE.** Use only the card data provided below.\n" |
|
|
"3. For `Benefits`, extract and list **ONLY** the 3-4 most important benefits. Keep each bullet point very short.\n" |
|
|
"4. For `Fees & Eligibility`, list the key fees (joining/annual) and income/age as separate concise bullet points.\n" |
|
|
"5. For `Limitations`, extract only the top 1-2 limitations. If none are listed, write 'None listed in the provided data.'.\n" |
|
|
"6. For `Ideal User`, provide a single sentence describing the best fit for the card.\n" |
|
|
"7. After the table, give a brief, one-sentence recommendation.\n" |
|
|
"8. Use `<br>` for line breaks inside table cells. Do not use newline characters (`\\n`) or extra `|` inside any cell.\n\n" |
|
|
"CARD DATA:\n\n" |
|
|
+ "\n\n".join(comparison_details) |
|
|
) |
|
|
else: |
|
|
comparison_prompt = ( |
|
|
"Compare the following credit cards based on their benefits, fees, eligibility, and ideal use cases.\n\n" |
|
|
"Instructions:\n" |
|
|
"1. **STRICTLY** use only the card data provided below. Do NOT guess, assume, or hallucinate any information.\n" |
|
|
"2. Keep the output short, structured, and highly readable.\n" |
|
|
"3. Use markdown format with clear section headers like 'Comparison' and 'Recommendation'.\n" |
|
|
"4. Use a concise list of bullet points for each card's benefits, fees, and limitations.\n" |
|
|
"5. Conclude with a recommendation on which card suits which type of user.\n\n" |
|
|
"CARD DATA:\n\n" |
|
|
+ "\n\n".join(comparison_details) |
|
|
) |
|
|
|
|
|
debug_print("COMPARE_NODE", "Calling Llama for comparison") |
|
|
|
|
|
try: |
|
|
messages = [ |
|
|
SystemMessage(content="You are an expert in comparing credit card products."), |
|
|
HumanMessage(content=comparison_prompt) |
|
|
] |
|
|
|
|
|
response_obj = await llm1.ainvoke( |
|
|
messages, |
|
|
config={"max_tokens": 2048, "temperature": 0.0} |
|
|
) |
|
|
response_content = response_obj.content |
|
|
debug_print("COMPARE_NODE", f"Response received with length: {len(response_content)}") |
|
|
print(response_content) |
|
|
state["comparison_result"] = response_content |
|
|
|
|
|
except Exception as e: |
|
|
debug_print("ERROR", f"Error during comparison: {e}") |
|
|
state["comparison_result"] = "An error occurred while comparing the cards. Please try again." |
|
|
|
|
|
return state |