junaid17 commited on
Commit
b35a113
·
verified ·
1 Parent(s): 1a33d5d

Update chatbot_advisor.py

Browse files
Files changed (1) hide show
  1. chatbot_advisor.py +172 -97
chatbot_advisor.py CHANGED
@@ -1,97 +1,172 @@
1
- from langgraph.graph import StateGraph, START, END
2
- from typing import TypedDict,Annotated
3
- from langchain_core.messages import HumanMessage, BaseMessage, AIMessage, SystemMessage
4
- from langchain_openai import ChatOpenAI
5
- from langgraph.checkpoint.memory import MemorySaver
6
- from dotenv import load_dotenv
7
- from langgraph.graph.message import add_messages
8
- load_dotenv()
9
-
10
- class ChatState(TypedDict):
11
- messages : Annotated[list[BaseMessage], add_messages]
12
-
13
- llm = ChatOpenAI(model='gpt-4.1-nano', streaming=True)
14
-
15
- SYSTEM_MESSAGE = SystemMessage(
16
- content=(
17
- "You are RiskGuard AI, an intelligent credit risk and financial guidance assistant. "
18
- "Your role is to help users understand their credit standing, loan eligibility, and financial risk profile "
19
- "based on the information provided to you. "
20
-
21
- "Your responses should be:\n"
22
- "- Clear, concise, and easy to understand (avoid technical jargon unless needed)\n"
23
- "- Professional and non-judgmental in tone\n"
24
- "- Supportive, encouraging, and solution-focused\n"
25
- "- Insightful, offering actionable steps the user can take to improve\n"
26
- "- Aligned with responsible financial communication (no promises, guarantees, or legal statements)\n\n"
27
-
28
- "When answering:\n"
29
- "- Reference relevant financial data if provided\n"
30
- "- Offer practical recommendations that feel personalized\n"
31
- "- Keep responses conversational, modern, and human-like, similar to a digital bank assistant or financial coach\n\n"
32
-
33
- "If the user asks about next steps, provide helpful financial strategies such as improving repayment history, "
34
- "reducing utilization, maintaining fewer inquiries, or improving documentation.\n\n"
35
-
36
- "If you do not have enough information to answer accurately, ask a clarifying question.\n\n"
37
-
38
- "Never provide legal, tax, or investment guarantees.\n\n"
39
-
40
- "Your priority is to help the user feel informed, supported, and confident in managing their credit journey."
41
- )
42
- )
43
-
44
-
45
- def chat_node(state : ChatState):
46
- user_query = state['messages']
47
- query = [SYSTEM_MESSAGE]+user_query
48
- response = llm.invoke(query)
49
- return {'messages': [response]}
50
-
51
- checkpointer = MemorySaver()
52
- graph = StateGraph(ChatState)
53
- graph.add_node("chat_node", chat_node)
54
- graph.add_edge(START, 'chat_node')
55
- graph.add_edge('chat_node', END)
56
-
57
- financial_advisor_chatbot = graph.compile(checkpointer=checkpointer)
58
-
59
- thread_id='1'
60
- config = {'configurable' : {'thread_id' : thread_id}}
61
-
62
- def format_chat_input(probability, credit_score, rating, advisor_reply, user_message):
63
- return f"""
64
- Below is the most recent loan evaluation details. Use them when responding.
65
-
66
- CREDIT ANALYSIS
67
- ---------------
68
- Credit Score: {credit_score}
69
- Default Probability: {probability:.2%}
70
- • Rating: {rating}
71
-
72
- AI ADVISOR SUMMARY
73
- ------------------
74
- {advisor_reply}
75
-
76
- USER QUESTION
77
- -------------
78
- {user_message}
79
-
80
- Respond as RiskGuard AI in a clear, concise and helpful tone.
81
- """
82
-
83
- def ask_chatbot(probability, credit_score, rating, advisor_reply, user_message, thread_id):
84
- formatted_msg = format_chat_input(probability, credit_score, rating, advisor_reply, user_message)
85
-
86
- initial_state = {
87
- "messages": [HumanMessage(content=formatted_msg)]
88
- }
89
-
90
- config = {"configurable": {"thread_id": thread_id}}
91
-
92
- response = financial_advisor_chatbot.invoke(initial_state, config=config)
93
- return response["messages"][-1].content
94
-
95
-
96
-
97
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langgraph.graph import StateGraph, START, END
2
+ from typing import TypedDict, Annotated
3
+ from langchain_core.messages import HumanMessage, BaseMessage, AIMessage, SystemMessage
4
+ from langchain_openai import ChatOpenAI
5
+ from langgraph.checkpoint.memory import MemorySaver
6
+ from langgraph.graph.message import add_messages
7
+ from langgraph.prebuilt import ToolNode, tools_condition
8
+ from langchain_community.tools.tavily_search import TavilySearchResults
9
+ from langchain_core.tools import tool
10
+ from dotenv import load_dotenv
11
+
12
+ load_dotenv()
13
+
14
+ # =====================================================
15
+ # STATE
16
+ # =====================================================
17
+ class ChatState(TypedDict):
18
+ messages: Annotated[list[BaseMessage], add_messages]
19
+
20
+
21
+ # =====================================================
22
+ # TOOL DEFINITIONS
23
+ # =====================================================
24
+
25
+ @tool
26
+ def tavily_search(query: str) -> dict:
27
+ """
28
+ Perform a web search using Tavily.
29
+ Use this when up-to-date or factual information is required.
30
+ """
31
+ try:
32
+ search = TavilySearchResults(max_results=5)
33
+ results = search.run(query)
34
+ return {"query": query, "results": results}
35
+ except Exception as e:
36
+ return {"error": str(e)}
37
+
38
+
39
+ tools = [tavily_search]
40
+
41
+
42
+ # =====================================================
43
+ # LLM CONFIGURATION
44
+ # =====================================================
45
+ llm = ChatOpenAI(
46
+ model="gpt-4.1-nano",
47
+ streaming=True
48
+ ).bind_tools(tools)
49
+
50
+
51
+ # =====================================================
52
+ # SYSTEM PROMPT (MINIMALLY ENHANCED)
53
+ # =====================================================
54
+ SYSTEM_MESSAGE = SystemMessage(
55
+ content=(
56
+ "You are RiskGuard AI, an intelligent credit risk and financial guidance assistant.\n\n"
57
+
58
+ "You are assisting a highly technical developer who is building a production-grade "
59
+ "AI-powered financial assistant. Your responses should be accurate, structured, "
60
+ "and implementation-aware when necessary.\n\n"
61
+
62
+ "Your role is to help users understand their credit standing, loan eligibility, and "
63
+ "financial risk profile based on the information provided.\n\n"
64
+
65
+ "Your responses should be:\n"
66
+ "- Clear, concise, and easy to understand (avoid unnecessary jargon)\n"
67
+ "- Professional, calm, and non-judgmental\n"
68
+ "- Supportive and solution-oriented\n"
69
+ "- Practical and actionable\n\n"
70
+
71
+ "When answering:\n"
72
+ "- Reference relevant financial data if provided\n"
73
+ "- Offer realistic, responsible recommendations\n"
74
+ "- Ask clarifying questions if information is missing\n\n"
75
+
76
+ "If external or real-time information is required, use available tools.\n\n"
77
+
78
+ "Never provide legal, tax, or investment guarantees.\n\n"
79
+
80
+ "Your goal is to help the user feel informed, confident, and in control of their financial decisions."
81
+ )
82
+ )
83
+
84
+
85
+ # =====================================================
86
+ # CHAT NODE
87
+ # =====================================================
88
+ def chat_node(state: ChatState):
89
+ messages = [SYSTEM_MESSAGE] + state["messages"]
90
+ response = llm.invoke(messages)
91
+ return {"messages": [response]}
92
+
93
+
94
+ # =====================================================
95
+ # GRAPH SETUP
96
+ # =====================================================
97
+ checkpointer = MemorySaver()
98
+
99
+ graph = StateGraph(ChatState)
100
+
101
+ graph.add_node("chat_node", chat_node)
102
+ graph.add_node("tools", ToolNode(tools))
103
+
104
+ # Routing logic
105
+ graph.add_edge(START, "chat_node")
106
+ graph.add_conditional_edges("chat_node", tools_condition)
107
+ graph.add_edge("tools", "chat_node")
108
+ graph.add_edge("chat_node", END)
109
+
110
+ financial_advisor_chatbot = graph.compile(checkpointer=checkpointer)
111
+
112
+
113
+ # =====================================================
114
+ # INPUT FORMATTER
115
+ # =====================================================
116
+ def format_chat_input(probability, credit_score, rating, advisor_reply, user_message):
117
+ return f"""
118
+ CREDIT ANALYSIS
119
+ ---------------
120
+ Credit Score: {credit_score}
121
+ Default Probability: {probability:.2%}
122
+ Rating: {rating}
123
+
124
+ AI ADVISOR SUMMARY:
125
+ {advisor_reply}
126
+
127
+ USER MESSAGE:
128
+ {user_message}
129
+ """
130
+
131
+
132
+ # =====================================================
133
+ # NORMAL RESPONSE (NON-STREAMING)
134
+ # =====================================================
135
+ def ask_chatbot(probability, credit_score, rating, advisor_reply, user_message, thread_id):
136
+
137
+ formatted = format_chat_input(
138
+ probability,
139
+ credit_score,
140
+ rating,
141
+ advisor_reply,
142
+ user_message
143
+ )
144
+
145
+ state = {"messages": [HumanMessage(content=formatted)]}
146
+ config = {"configurable": {"thread_id": thread_id}}
147
+
148
+ result = financial_advisor_chatbot.invoke(state, config=config)
149
+ return result["messages"][-1].content
150
+
151
+
152
+ # =====================================================
153
+ # STREAMING RESPONSE
154
+ # =====================================================
155
+ def ask_chatbot_stream(probability, credit_score, rating, advisor_reply, user_message, thread_id):
156
+
157
+ formatted = format_chat_input(
158
+ probability,
159
+ credit_score,
160
+ rating,
161
+ advisor_reply,
162
+ user_message
163
+ )
164
+
165
+ state = {"messages": [HumanMessage(content=formatted)]}
166
+ config = {"configurable": {"thread_id": thread_id}}
167
+
168
+ for event in financial_advisor_chatbot.stream(state, config=config):
169
+ if "messages" in event:
170
+ msg = event["messages"][-1]
171
+ if isinstance(msg, AIMessage) and msg.content:
172
+ yield msg.content