suratan.boon commited on
Commit
0957e29
Β·
1 Parent(s): 08c673e

update/dashboard

Browse files
src/chatbot/app_interface.py CHANGED
@@ -89,11 +89,6 @@ def update_form_information_handler(form_information):
89
  expense_justification_input = form_information.get("Expense Description", None)
90
  expense_justification_input = None if expense_justification_input == "None" else expense_justification_input
91
 
92
- # form_amount_input = form_information.get("Total Payment Amount", None)
93
- # if form_information is not None:
94
- # form_amount_input = float(form_amount_input)
95
- # form_account_input = form_information.get("Payer's Name", None)
96
- # seller_phone_number_input
97
  return seller_name_input, seller_address_input, seller_phone_number_input, buyer_name_input, buyer_address_input, transaction_date_input, total_payment_amount_input, expense_justification_input
98
 
99
  _chat_prefill = [
@@ -122,82 +117,87 @@ def chat_handler(message, history):
122
  raise e
123
 
124
  # Update form information after processing
125
- form_information = get_form_info()
126
  update_form_information_handler(form_information)
127
 
128
- return response
129
 
130
  # Create the Gradio app with tabs
131
- with gr.Blocks() as app:
132
- form_information = gr.State(form_info)
133
-
134
- # Reset button at the top
135
- new_btn = gr.Button("ΰΉ€ΰΈ£ΰΈ΄ΰΉˆΰΈ‘ΰΉƒΰΈ«ΰΈ‘ΰΉˆ", variant="primary")
136
-
137
- with gr.Tabs():
138
- # Chat tab using ChatInterface
139
- with gr.Tab("ΰΉΰΈŠΰΈ—"):
140
- chat_interface = gr.ChatInterface(
141
- fn=chat_handler,
142
- type="messages",
143
- chatbot=gr.Chatbot(value=_chat_prefill, type="messages", label="กΰΈ₯ΰΉˆΰΈ­ΰΈ‡ΰΈ‚ΰΉ‰ΰΈ­ΰΈ„ΰΈ§ΰΈ²ΰΈ‘"),
144
- multimodal=True, # Enable image uploads
145
- submit_btn="ΰΈͺΰΉˆΰΈ‡ΰΈ‚ΰΉ‰ΰΈ­ΰΈ„ΰΈ§ΰΈ²ΰΈ‘",
146
- autofocus=True,
147
- examples=None
148
- )
149
-
150
- # Function to reset the chat and generate a new session ID
151
- def reset_chat():
152
- global CURRENT_SESSION_ID
153
- CURRENT_SESSION_ID = generate_session_id()
154
- logger.info(f"Chat reset with new session ID: {CURRENT_SESSION_ID}")
155
- # Reset form info
156
- form_info.clear()
157
- # Return the initial chat message
158
- return _chat_prefill
159
-
160
- new_btn.click(fn=reset_chat, inputs=[], outputs=chat_interface.chatbot_value)
161
-
162
- # Form tab (unchanged)
163
- with gr.Tab("ฟอร์ฑ"):
164
- gr.Markdown("**ΰΈŠΰΈ·ΰΉˆΰΈ­ΰΈœΰΈΉΰΉ‰ΰΈ‚ΰΈ²ΰΈ’**")
165
- seller_name_input = gr.Textbox(value = ast.literal_eval(form_info["Seller Name"]), label="", container=False)
166
-
167
- gr.Markdown("**ΰΈ—ΰΈ΅ΰΉˆΰΈ­ΰΈ’ΰΈΉΰΉˆΰΈœΰΈΉΰΉ‰ΰΈ‚ΰΈ²ΰΈ’**")
168
- seller_address_input = gr.Textbox(value = ast.literal_eval(form_info["Seller Address"]), label="", container=False)
169
-
170
- gr.Markdown("**ΰΉ€ΰΈšΰΈ­ΰΈ£ΰΉŒΰΉ‚ΰΈ—ΰΈ£ΰΈ¨ΰΈ±ΰΈžΰΈ—ΰΉŒΰΈœΰΈΉΰΉ‰ΰΈ‚ΰΈ²ΰΈ’**")
171
- seller_phone_number_input = gr.Textbox(value = ast.literal_eval(form_info["Seller Phone Number"]), label="", container=False)
172
-
173
- gr.Markdown("**ΰΈŠΰΈ·ΰΉˆΰΈ­ΰΈœΰΈΉΰΉ‰ΰΈ‹ΰΈ·ΰΉ‰ΰΈ­**")
174
- buyer_name_input = gr.Textbox(value = ast.literal_eval(form_info["Buyer Name"]), label="", container=False)
175
-
176
- gr.Markdown("**ΰΈ—ΰΈ΅ΰΉˆΰΈ­ΰΈ’ΰΈΉΰΉˆΰΈœΰΈΉΰΉ‰ΰΈ‹ΰΈ·ΰΉ‰ΰΈ­**")
177
- buyer_address_input = gr.Textbox(value = ast.literal_eval(form_info["Buyer Address"]), label="", container=False)
178
-
179
- gr.Markdown("**ΰΈ§ΰΈ±ΰΈ™ΰΈ—ΰΈ΅ΰΉˆΰΈ—ΰΈ³ΰΈ˜ΰΈΈΰΈ£ΰΈΰΈ£ΰΈ£ΰΈ‘**")
180
- transaction_date_input = gr.Textbox(value = ast.literal_eval(form_info["Transaction Date"]), label="", container=False)
181
-
182
- gr.Markdown("**ΰΈˆΰΈ³ΰΈ™ΰΈ§ΰΈ™ΰΉ€ΰΈ‡ΰΈ΄ΰΈ™ΰΈ—ΰΈ΅ΰΉˆΰΈŠΰΈ³ΰΈ£ΰΈ°ΰΈ—ΰΈ±ΰΉ‰ΰΈ‡ΰΈ«ΰΈ‘ΰΈ”**")
183
- with gr.Row():
184
- total_payment_amount_input = gr.Number(value = ast.literal_eval(form_info['Total Payment Amount']), label="", container=False)
185
- gr.Markdown("ΰΈšΰΈ²ΰΈ—")
186
-
187
- gr.Markdown("**การพิΰΈͺΰΈΉΰΈˆΰΈ™ΰΉŒΰΈ„ΰΉˆΰΈ²ΰΉƒΰΈŠΰΉ‰ΰΈˆΰΉˆΰΈ²ΰΈ’**")
188
- expense_justification_input = gr.Textbox(value=ast.literal_eval(form_info["Expense Description"]), label="", container=False, lines=4)
189
-
190
- submit_btn = gr.Button("Submit", variant="primary")
191
-
192
- seller_name_input.change(update_seller_name_input, inputs=[seller_name_input], outputs=[form_information])
193
- seller_address_input.change(update_seller_address_input, inputs=[seller_address_input], outputs=[form_information])
194
- seller_phone_number_input.change(update_seller_phone_number_input, inputs=[seller_phone_number_input], outputs=[form_information])
195
- buyer_name_input.change(update_buyer_name_input, inputs=[buyer_name_input], outputs=[form_information])
196
- buyer_address_input.change(update_buyer_address_input, inputs=[buyer_address_input], outputs=[form_information])
197
- transaction_date_input.change(update_transaction_date_input, inputs=[transaction_date_input], outputs=[form_information])
198
- total_payment_amount_input.change(update_total_payment_amount_input, inputs=[total_payment_amount_input], outputs=[form_information])
199
-
200
- form_information.change(update_form_information_handler, inputs=[form_information], outputs=[seller_name_input, seller_address_input, seller_phone_number_input, buyer_name_input, buyer_address_input, transaction_date_input, total_payment_amount_input, expense_justification_input])
 
 
 
 
201
 
202
  if __name__ == "__main__":
203
- app.launch()
 
 
89
  expense_justification_input = form_information.get("Expense Description", None)
90
  expense_justification_input = None if expense_justification_input == "None" else expense_justification_input
91
 
 
 
 
 
 
92
  return seller_name_input, seller_address_input, seller_phone_number_input, buyer_name_input, buyer_address_input, transaction_date_input, total_payment_amount_input, expense_justification_input
93
 
94
  _chat_prefill = [
 
117
  raise e
118
 
119
  # Update form information after processing
120
+ form_information = get_form_info()
121
  update_form_information_handler(form_information)
122
 
123
+ return response, form_information
124
 
125
  # Create the Gradio app with tabs
126
+ def create_expense_register_page():
127
+ with gr.Blocks() as page:
128
+ form_information = gr.State(form_info)
129
+
130
+ # Reset button at the top
131
+ new_btn = gr.Button("ΰΉ€ΰΈ£ΰΈ΄ΰΉˆΰΈ‘ΰΉƒΰΈ«ΰΈ‘ΰΉˆ", variant="primary")
132
+
133
+ with gr.Tabs():
134
+ # Chat tab using ChatInterface
135
+ with gr.Tab("ΰΉΰΈŠΰΈ—"):
136
+ chat_interface = gr.ChatInterface(
137
+ fn=chat_handler,
138
+ type="messages",
139
+ chatbot=gr.Chatbot(value=_chat_prefill, type="messages", label="กΰΈ₯ΰΉˆΰΈ­ΰΈ‡ΰΈ‚ΰΉ‰ΰΈ­ΰΈ„ΰΈ§ΰΈ²ΰΈ‘"),
140
+ multimodal=True, # Enable image uploads
141
+ submit_btn="ΰΈͺΰΉˆΰΈ‡ΰΈ‚ΰΉ‰ΰΈ­ΰΈ„ΰΈ§ΰΈ²ΰΈ‘",
142
+ autofocus=True,
143
+ examples=None,
144
+ additional_outputs=[form_information]
145
+ )
146
+
147
+ # Function to reset the chat and generate a new session ID
148
+ def reset_chat():
149
+ global CURRENT_SESSION_ID
150
+ CURRENT_SESSION_ID = generate_session_id()
151
+ logger.info(f"Chat reset with new session ID: {CURRENT_SESSION_ID}")
152
+ # Reset form info
153
+ form_info.clear()
154
+ # Return the initial chat message
155
+ return _chat_prefill
156
+
157
+ new_btn.click(fn=reset_chat, inputs=[], outputs=chat_interface.chatbot_value)
158
+
159
+ # Form tab (unchanged)
160
+ with gr.Tab("ฟอร์ฑ"):
161
+ gr.Markdown("**ΰΈŠΰΈ·ΰΉˆΰΈ­ΰΈœΰΈΉΰΉ‰ΰΈ‚ΰΈ²ΰΈ’**")
162
+ seller_name_input = gr.Textbox(value = ast.literal_eval(form_info["Seller Name"]), label="", container=False)
163
+
164
+ gr.Markdown("**ΰΈ—ΰΈ΅ΰΉˆΰΈ­ΰΈ’ΰΈΉΰΉˆΰΈœΰΈΉΰΉ‰ΰΈ‚ΰΈ²ΰΈ’**")
165
+ seller_address_input = gr.Textbox(value = ast.literal_eval(form_info["Seller Address"]), label="", container=False)
166
+
167
+ gr.Markdown("**ΰΉ€ΰΈšΰΈ­ΰΈ£ΰΉŒΰΉ‚ΰΈ—ΰΈ£ΰΈ¨ΰΈ±ΰΈžΰΈ—ΰΉŒΰΈœΰΈΉΰΉ‰ΰΈ‚ΰΈ²ΰΈ’**")
168
+ seller_phone_number_input = gr.Textbox(value = ast.literal_eval(form_info["Seller Phone Number"]), label="", container=False)
169
+
170
+ gr.Markdown("**ΰΈŠΰΈ·ΰΉˆΰΈ­ΰΈœΰΈΉΰΉ‰ΰΈ‹ΰΈ·ΰΉ‰ΰΈ­**")
171
+ buyer_name_input = gr.Textbox(value = ast.literal_eval(form_info["Buyer Name"]), label="", container=False)
172
+
173
+ gr.Markdown("**ΰΈ—ΰΈ΅ΰΉˆΰΈ­ΰΈ’ΰΈΉΰΉˆΰΈœΰΈΉΰΉ‰ΰΈ‹ΰΈ·ΰΉ‰ΰΈ­**")
174
+ buyer_address_input = gr.Textbox(value = ast.literal_eval(form_info["Buyer Address"]), label="", container=False)
175
+
176
+ gr.Markdown("**ΰΈ§ΰΈ±ΰΈ™ΰΈ—ΰΈ΅ΰΉˆΰΈ—ΰΈ³ΰΈ˜ΰΈΈΰΈ£ΰΈΰΈ£ΰΈ£ΰΈ‘**")
177
+ transaction_date_input = gr.DateTime(include_time=False, type="datetime", show_label=False)
178
+
179
+ gr.Markdown("**ΰΈˆΰΈ³ΰΈ™ΰΈ§ΰΈ™ΰΉ€ΰΈ‡ΰΈ΄ΰΈ™ΰΈ—ΰΈ΅ΰΉˆΰΈŠΰΈ³ΰΈ£ΰΈ°ΰΈ—ΰΈ±ΰΉ‰ΰΈ‡ΰΈ«ΰΈ‘ΰΈ”**")
180
+ with gr.Row():
181
+ total_payment_amount_input = gr.Number(value = ast.literal_eval(form_info['Total Payment Amount']), label="", container=False)
182
+ gr.Markdown("ΰΈšΰΈ²ΰΈ—")
183
+
184
+ gr.Markdown("**การพิΰΈͺΰΈΉΰΈˆΰΈ™ΰΉŒΰΈ„ΰΉˆΰΈ²ΰΉƒΰΈŠΰΉ‰ΰΈˆΰΉˆΰΈ²ΰΈ’**")
185
+ expense_justification_input = gr.Textbox(value=ast.literal_eval(form_info["Expense Description"]), label="", container=False, lines=4)
186
+
187
+ submit_btn = gr.Button("Submit", variant="primary")
188
+
189
+ seller_name_input.change(update_seller_name_input, inputs=[seller_name_input], outputs=[form_information])
190
+ seller_address_input.change(update_seller_address_input, inputs=[seller_address_input], outputs=[form_information])
191
+ seller_phone_number_input.change(update_seller_phone_number_input, inputs=[seller_phone_number_input], outputs=[form_information])
192
+ buyer_name_input.change(update_buyer_name_input, inputs=[buyer_name_input], outputs=[form_information])
193
+ buyer_address_input.change(update_buyer_address_input, inputs=[buyer_address_input], outputs=[form_information])
194
+ transaction_date_input.change(update_transaction_date_input, inputs=[transaction_date_input], outputs=[form_information])
195
+ total_payment_amount_input.change(update_total_payment_amount_input, inputs=[total_payment_amount_input], outputs=[form_information])
196
+
197
+ form_information.change(update_form_information_handler, inputs=[form_information], outputs=[seller_name_input, seller_address_input, seller_phone_number_input, buyer_name_input, buyer_address_input, transaction_date_input, total_payment_amount_input, expense_justification_input])
198
+
199
+ return page
200
 
201
  if __name__ == "__main__":
202
+ page = create_expense_register_page()
203
+ page.launch()
src/chatbot/dashboard/dashboard_page.py CHANGED
@@ -16,7 +16,7 @@ from dashboard.visualize_component import (
16
  render_deliverable_summary_cards
17
  )
18
 
19
- DB_PATH = "database/hello_earth_data.db"
20
 
21
  # ------------------------ Database Utilities ------------------------
22
 
@@ -46,7 +46,19 @@ def get_all_deliverable_budgets(project_id):
46
 
47
  def get_all_expenses(project_id):
48
  query = """
49
- SELECT e.*
 
 
 
 
 
 
 
 
 
 
 
 
50
  FROM Expense e
51
  JOIN Deliverable d ON e.associated_deliverable_id = d.deliverable_id
52
  WHERE d.project_id = ?
@@ -72,14 +84,18 @@ def filter_expenses(search_term, df):
72
  search_term = search_term.lower()
73
  mask = pd.Series(False, index=df.index)
74
  for col in [
75
- 'expense_id', 'associated_deliverable_id', 'seller_name',
76
- 'seller_address', 'seller_phone_number', 'buyer_name',
77
- 'buyer_address', 'transaction_date', 'total_payment_amount',
78
- 'expense_description', 'status'
79
  ]:
80
  mask |= df[col].astype(str).str.lower().str.contains(search_term)
81
  return df[mask]
82
 
 
 
 
 
 
83
  # ------------------------ UI Setup ------------------------
84
 
85
  def create_dashboard_page():
@@ -102,30 +118,44 @@ def create_dashboard_page():
102
  # --- Page 2: Dashboard View ---
103
  with gr.Column(visible=False) as dashboard_page:
104
  dashboard_header = gr.Markdown("")
 
105
  back_button = gr.Button("β¬… Back to Projects")
106
 
107
  with gr.Column():
108
- gr.Markdown("## Overall Project Financial Snapshot")
 
 
109
  with gr.Row():
110
  total_budget_md = gr.Markdown()
111
  total_expense_md = gr.Markdown()
112
  leftover_md = gr.Markdown()
 
 
113
  gauge_plot = gr.Plot()
114
 
115
- gr.Markdown("## Deliverable-Level Financial Insights")
 
 
116
  with gr.Row():
117
  bar_chart_plot = gr.Plot()
118
  pie_chart_plot = gr.Plot()
 
 
119
  with gr.Row():
120
  daily_plot = gr.Plot()
121
  cum_plot = gr.Plot()
 
 
122
  with gr.Row():
123
  with gr.Column(scale=1):
124
  risk_plot = gr.Plot()
125
  with gr.Column(scale=2):
126
  cards_html = gr.HTML()
 
 
127
  gantt_plot = gr.Plot()
128
 
 
129
  gr.Markdown("## πŸ’΅ Expense Table")
130
  search_box = gr.Textbox(placeholder="Search expenses", label="Search")
131
  expense_table = gr.DataFrame()
@@ -154,11 +184,14 @@ def create_dashboard_page():
154
  else:
155
  status, color = "βœ… Budget on track", "green"
156
 
 
 
157
  return [
158
  project_id,
159
  gr.update(visible=False),
160
  gr.update(visible=True),
161
  gr.update(value=f"# πŸ“Š Financial Dashboard β€” {get_title_by_id(project_options, project_id)}"),
 
162
  gr.update(value=f"### Total Money Granted\n## {total_budget:,.0f}"),
163
  gr.update(value=f"### Total Expense Spendings\n## {total_expense:,.0f}\n({(total_expense / total_budget * 100):.1f}% of budget)"),
164
  gr.update(value=f"### Leftover Budget\n## {leftover:,.0f}\n<span style='color: {color};'>{status}</span>"),
@@ -170,7 +203,7 @@ def create_dashboard_page():
170
  gr.update(value=generate_risk_level_distribution_pie_chart(deliverables)),
171
  gr.update(value=generate_deliverable_timeline_gantt_chart(deliverables)),
172
  gr.update(value=render_deliverable_summary_cards(deliverables)),
173
- gr.update(value=expenses),
174
  expenses
175
  ]
176
 
@@ -187,6 +220,7 @@ def create_dashboard_page():
187
  project_selector_page,
188
  dashboard_page,
189
  dashboard_header,
 
190
  total_budget_md,
191
  total_expense_md,
192
  leftover_md,
 
16
  render_deliverable_summary_cards
17
  )
18
 
19
+ DB_PATH = "../database/hello_earth_data_2.db"
20
 
21
  # ------------------------ Database Utilities ------------------------
22
 
 
46
 
47
  def get_all_expenses(project_id):
48
  query = """
49
+ SELECT
50
+ e.expense_id,
51
+ e.associated_deliverable_id,
52
+ d.title AS deliverable_title,
53
+ e.seller_name,
54
+ e.seller_address,
55
+ e.seller_phone_number,
56
+ e.buyer_name,
57
+ e.buyer_address,
58
+ e.transaction_date,
59
+ e.total_payment_amount,
60
+ e.expense_description,
61
+ e.status
62
  FROM Expense e
63
  JOIN Deliverable d ON e.associated_deliverable_id = d.deliverable_id
64
  WHERE d.project_id = ?
 
84
  search_term = search_term.lower()
85
  mask = pd.Series(False, index=df.index)
86
  for col in [
87
+ 'deliverable_title', 'seller_name', 'seller_address', 'seller_phone_number',
88
+ 'buyer_name', 'buyer_address', 'transaction_date',
89
+ 'total_payment_amount', 'expense_description', 'status'
 
90
  ]:
91
  mask |= df[col].astype(str).str.lower().str.contains(search_term)
92
  return df[mask]
93
 
94
+ def update_project_detail(project_id):
95
+ project = get_project_data()
96
+ info = project.loc[project['project_id'] == project_id, 'detail_information'].values
97
+ return info[0] if len(info) > 0 else "No description available."
98
+
99
  # ------------------------ UI Setup ------------------------
100
 
101
  def create_dashboard_page():
 
118
  # --- Page 2: Dashboard View ---
119
  with gr.Column(visible=False) as dashboard_page:
120
  dashboard_header = gr.Markdown("")
121
+ project_detail_md = gr.Markdown()
122
  back_button = gr.Button("β¬… Back to Projects")
123
 
124
  with gr.Column():
125
+ gr.Markdown("## πŸ’° Overall Project Financial Snapshot")
126
+
127
+ gr.Markdown("### Budget Summary")
128
  with gr.Row():
129
  total_budget_md = gr.Markdown()
130
  total_expense_md = gr.Markdown()
131
  leftover_md = gr.Markdown()
132
+
133
+ gr.Markdown("### Utilization Gauge")
134
  gauge_plot = gr.Plot()
135
 
136
+ gr.Markdown("## πŸ“¦ Deliverable-Level Financial Insights")
137
+
138
+ gr.Markdown("### Budget vs Expense")
139
  with gr.Row():
140
  bar_chart_plot = gr.Plot()
141
  pie_chart_plot = gr.Plot()
142
+
143
+ gr.Markdown("### Spending Over Time")
144
  with gr.Row():
145
  daily_plot = gr.Plot()
146
  cum_plot = gr.Plot()
147
+
148
+ gr.Markdown("### Risk & Deliverables")
149
  with gr.Row():
150
  with gr.Column(scale=1):
151
  risk_plot = gr.Plot()
152
  with gr.Column(scale=2):
153
  cards_html = gr.HTML()
154
+
155
+ gr.Markdown("### Deliverable Timeline (Gantt Chart)")
156
  gantt_plot = gr.Plot()
157
 
158
+
159
  gr.Markdown("## πŸ’΅ Expense Table")
160
  search_box = gr.Textbox(placeholder="Search expenses", label="Search")
161
  expense_table = gr.DataFrame()
 
184
  else:
185
  status, color = "βœ… Budget on track", "green"
186
 
187
+ detail_text = update_project_detail(project_id)
188
+
189
  return [
190
  project_id,
191
  gr.update(visible=False),
192
  gr.update(visible=True),
193
  gr.update(value=f"# πŸ“Š Financial Dashboard β€” {get_title_by_id(project_options, project_id)}"),
194
+ gr.update(value=detail_text),
195
  gr.update(value=f"### Total Money Granted\n## {total_budget:,.0f}"),
196
  gr.update(value=f"### Total Expense Spendings\n## {total_expense:,.0f}\n({(total_expense / total_budget * 100):.1f}% of budget)"),
197
  gr.update(value=f"### Leftover Budget\n## {leftover:,.0f}\n<span style='color: {color};'>{status}</span>"),
 
203
  gr.update(value=generate_risk_level_distribution_pie_chart(deliverables)),
204
  gr.update(value=generate_deliverable_timeline_gantt_chart(deliverables)),
205
  gr.update(value=render_deliverable_summary_cards(deliverables)),
206
+ gr.update(value=expenses.drop(columns=["expense_id", "associated_deliverable_id"])),
207
  expenses
208
  ]
209
 
 
220
  project_selector_page,
221
  dashboard_page,
222
  dashboard_header,
223
+ project_detail_md,
224
  total_budget_md,
225
  total_expense_md,
226
  leftover_md,
src/chatbot/dashboard/visualize_component.py CHANGED
@@ -1,7 +1,6 @@
1
  import plotly.graph_objects as go
2
  import plotly.express as px
3
  import pandas as pd
4
- from datetime import datetime
5
 
6
  def generate_budget_utilization_gauge_chart(total_budget, total_expense):
7
  """Generate a gauge chart comparing budget vs. total expense."""
@@ -24,8 +23,8 @@ def generate_budget_utilization_gauge_chart(total_budget, total_expense):
24
  title={'text': "Total Expense", 'font': {'size': 24}},
25
  delta={
26
  'reference': total_budget,
27
- 'increasing': {'color': 'red'},
28
- 'decreasing': {'color': 'green'}
29
  },
30
  gauge={
31
  'axis': {'range': [None, total_budget * 1.2], 'tickwidth': 1},
@@ -312,30 +311,6 @@ def generate_deliverable_timeline_gantt_chart(deliverable_df):
312
  # Reverse Y-axis to have earliest on top
313
  fig.update_yaxes(autorange='reversed')
314
 
315
- # Add vertical "Today" line
316
- today = datetime.today()
317
-
318
- fig.add_shape(
319
- type='line',
320
- x0=today,
321
- x1=today,
322
- y0=0,
323
- y1=1,
324
- xref='x',
325
- yref='paper',
326
- line=dict(color='red', width=2, dash='dash')
327
- )
328
-
329
- fig.add_annotation(
330
- x=today,
331
- y=1.02,
332
- xref='x',
333
- yref='paper',
334
- text='Today',
335
- showarrow=False,
336
- font=dict(color='red', size=12)
337
- )
338
-
339
  # Layout customization
340
  fig.update_layout(
341
  paper_bgcolor='rgba(0,0,0,0)',
@@ -347,14 +322,13 @@ def generate_deliverable_timeline_gantt_chart(deliverable_df):
347
  return fig
348
 
349
  def render_deliverable_summary_cards(deliverable_df):
350
- """Render a grid of HTML cards summarizing deliverables with risk level and status indicators."""
351
 
352
  def format_date(date_str):
353
  if pd.isna(date_str):
354
  return "-"
355
  return pd.to_datetime(date_str).strftime("%d %b %Y")
356
 
357
- # Define color mappings
358
  risk_level_colors = {
359
  "green": "#28a745",
360
  "yellow": "#ffc107",
@@ -369,7 +343,6 @@ def render_deliverable_summary_cards(deliverable_df):
369
  "approved": "#28a745"
370
  }
371
 
372
- # Start HTML grid
373
  cards_html = """
374
  <div style='display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;'>
375
  """
@@ -379,6 +352,7 @@ def render_deliverable_summary_cards(deliverable_df):
379
  deliverable_id = row.get('deliverable_id', '-')
380
  status = str(row.get('status', 'N/A')).lower()
381
  risk_level = str(row.get('risk_level', 'unknown')).lower()
 
382
 
383
  status_color = status_colors.get(status, "#6c757d")
384
  risk_color = risk_level_colors.get(risk_level, "#6c757d")
@@ -387,7 +361,7 @@ def render_deliverable_summary_cards(deliverable_df):
387
  end_date = format_date(row.get('end_date'))
388
 
389
  cards_html += f"""
390
- <div style='border: 1px solid #dee2e6; border-radius: 10px; padding: 15px; background-color: #ffffff;'>
391
  <div style='font-weight: bold; font-size: 1.1em; margin-bottom: 5px;'>
392
  {title}
393
  <div style='font-size: 0.85em; color: #6c757d;'>ID: {deliverable_id}</div>
@@ -404,6 +378,12 @@ def render_deliverable_summary_cards(deliverable_df):
404
  <strong>Start:</strong> {start_date}<br>
405
  <strong>End:</strong> {end_date}
406
  </div>
 
 
 
 
 
 
407
  </div>
408
  """
409
 
 
1
  import plotly.graph_objects as go
2
  import plotly.express as px
3
  import pandas as pd
 
4
 
5
  def generate_budget_utilization_gauge_chart(total_budget, total_expense):
6
  """Generate a gauge chart comparing budget vs. total expense."""
 
23
  title={'text': "Total Expense", 'font': {'size': 24}},
24
  delta={
25
  'reference': total_budget,
26
+ 'increasing': {'color': 'red', 'symbol': "\u25B2"},
27
+ 'decreasing': {'color': 'green', 'symbol': "\u25BC"}
28
  },
29
  gauge={
30
  'axis': {'range': [None, total_budget * 1.2], 'tickwidth': 1},
 
311
  # Reverse Y-axis to have earliest on top
312
  fig.update_yaxes(autorange='reversed')
313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  # Layout customization
315
  fig.update_layout(
316
  paper_bgcolor='rgba(0,0,0,0)',
 
322
  return fig
323
 
324
  def render_deliverable_summary_cards(deliverable_df):
325
+ """Render HTML cards for deliverables with expandable risk rationale using <details>/<summary> (JS-free, Gradio-safe)."""
326
 
327
  def format_date(date_str):
328
  if pd.isna(date_str):
329
  return "-"
330
  return pd.to_datetime(date_str).strftime("%d %b %Y")
331
 
 
332
  risk_level_colors = {
333
  "green": "#28a745",
334
  "yellow": "#ffc107",
 
343
  "approved": "#28a745"
344
  }
345
 
 
346
  cards_html = """
347
  <div style='display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;'>
348
  """
 
352
  deliverable_id = row.get('deliverable_id', '-')
353
  status = str(row.get('status', 'N/A')).lower()
354
  risk_level = str(row.get('risk_level', 'unknown')).lower()
355
+ rationale = row.get('risk_level_rationale', 'No rationale provided')
356
 
357
  status_color = status_colors.get(status, "#6c757d")
358
  risk_color = risk_level_colors.get(risk_level, "#6c757d")
 
361
  end_date = format_date(row.get('end_date'))
362
 
363
  cards_html += f"""
364
+ <div style='border: 1px solid #dee2e6; border-radius: 10px; padding: 15px; background-color: #ffffff; box-shadow: 0 2px 6px rgba(0,0,0,0.05);'>
365
  <div style='font-weight: bold; font-size: 1.1em; margin-bottom: 5px;'>
366
  {title}
367
  <div style='font-size: 0.85em; color: #6c757d;'>ID: {deliverable_id}</div>
 
378
  <strong>Start:</strong> {start_date}<br>
379
  <strong>End:</strong> {end_date}
380
  </div>
381
+ <details style='margin-top: 12px; font-size: 0.85em; color: #495057;'>
382
+ <summary style='cursor: pointer; color: #007bff;'>Show Risk Rationale</summary>
383
+ <div style='margin-top: 6px; padding: 8px; background-color: #f8f9fa; border-radius: 5px; border: 1px solid #dee2e6;'>
384
+ <strong>Risk Rationale:</strong><br>{rationale}
385
+ </div>
386
+ </details>
387
  </div>
388
  """
389
 
src/chatbot/database/Deliverable.csv DELETED
@@ -1,9 +0,0 @@
1
- deliverable_id,project_id,title,status,risk_level,risk_level_rationale,start_date,end_date
2
- 14eff22b-ca43-45d3-8e29-37c8eb8bcaba,626e47da-76ae-4650-9d78-31072c1b5b0d,Area Assessment,done,green,No environmental threats detected.,2023-01-05,2023-03-01
3
- 4fba146b-b655-4cb5-8760-245b3cc1cff9,626e47da-76ae-4650-9d78-31072c1b5b0d,Planting Phase,ongoing,yellow,Tide schedule interference.,2023-03-15,2023-08-30
4
- c0819e22-02bf-4dd9-9936-710c40f26701,626e47da-76ae-4650-9d78-31072c1b5b0d,Monitoring Phase,ongoing,green,Stable growth rates observed.,2023-09-01,2023-11-01
5
- 51ee4582-bd59-4b0e-91f8-c3288ccff1c5,626e47da-76ae-4650-9d78-31072c1b5b0d,Community Education,ongoing,yellow,Low turnout in workshops.,2023-09-15,2023-12-15
6
- 40b469db-7b99-4002-89a5-d5622558dd88,f56b2354-ac70-4682-82f2-727ce13f4b71,Community Engagement,done,green,High public interest and participation.,2023-02-05,2023-04-01
7
- 114583cd-2522-4721-855d-e0ad7ffd1b05,f56b2354-ac70-4682-82f2-727ce13f4b71,Planting Execution,ongoing,red,Insufficient volunteer workforce.,2023-04-10,2023-10-15
8
- 3cddb3f6-6950-4f83-9142-b69f7352fd51,00cfa2f7-acb1-40aa-a420-d6c127c38c64,Equipment Procurement,done,green,Procurement completed on time.,2023-03-05,2023-04-01
9
- d8c0554d-f4f2-4fa7-96df-e3d4b45bbd40,00cfa2f7-acb1-40aa-a420-d6c127c38c64,Volunteer Training,ongoing,yellow,Training attendance dropped by 10%.,2023-04-10,2023-06-30
 
 
 
 
 
 
 
 
 
 
src/chatbot/database/Deliverable_Budget.csv DELETED
@@ -1,6 +0,0 @@
1
- id,deliverable_id,wage,materials,tools_equipment,services,misc
2
- 02ad1d05-6444-4007-99bf-03acd46338ff,14eff22b-ca43-45d3-8e29-37c8eb8bcaba,1000.0,1500.0,500.0,800.0,100.0
3
- 80e373d0-edb9-45bd-a14e-54e8e8acf57f,4fba146b-b655-4cb5-8760-245b3cc1cff9,1200.0,2000.0,700.0,1000.0,150.0
4
- dbe0fd74-ca7e-4792-b49f-0812dba78778,c0819e22-02bf-4dd9-9936-710c40f26701,1100.0,800.0,400.0,600.0,90.0
5
- ff2964e9-d8e6-46c7-b604-246add155edc,51ee4582-bd59-4b0e-91f8-c3288ccff1c5,950.0,500.0,300.0,750.0,120.0
6
- 416e697e-6e28-4fc8-81bf-496731d8486a,40b469db-7b99-4002-89a5-d5622558dd88,1500.0,1000.0,300.0,500.0,50.0
 
 
 
 
 
 
 
src/chatbot/database/Expense.csv DELETED
@@ -1,7 +0,0 @@
1
- expense_id,associated_deliverable_id,seller_name,seller_address,seller_phone_number,buyer_name,buyer_address,transaction_date,total_payment_amount,expense_description,status
2
- c3fac245-20ef-4ab9-8a02-afe9e2f59952,14eff22b-ca43-45d3-8e29-37c8eb8bcaba,EcoTools Ltd.,101 Earth Ave,0811111111,Mangrove Org,900 Forest Blvd,2023-01-20,1800.0,Survey equipment rental,approved
3
- 75135cca-df34-4f24-bed9-90ac1456c737,4fba146b-b655-4cb5-8760-245b3cc1cff9,Green Nursery Supplies,202 Plant Rd,0822222222,Mangrove Org,900 Forest Blvd,2023-04-10,2200.0,Mangrove saplings and planting tools,approved
4
- 7dda7444-4762-40d3-ba00-17fd1e297ab0,4fba146b-b655-4cb5-8760-245b3cc1cff9,TideLogistics,303 Coastal Lane,0833333333,Mangrove Org,900 Forest Blvd,2023-06-05,1300.0,Transport service for volunteers and gear,pending
5
- 81590aa0-fdb6-4de3-b756-39ee8b30a5e1,c0819e22-02bf-4dd9-9936-710c40f26701,DroneVision Inc.,404 Sky Blvd,0844444444,Mangrove Org,900 Forest Blvd,2023-09-10,1600.0,Aerial monitoring drone rental,approved
6
- 6660e3a4-3329-4105-b411-551fa09fc3d3,51ee4582-bd59-4b0e-91f8-c3288ccff1c5,EduLeaf,505 Learning St,0855555555,Mangrove Org,900 Forest Blvd,2023-10-01,900.0,Educational materials and workshop kits,approved
7
- 69aa3f56-167b-49ba-8039-d72ff84390bc,51ee4582-bd59-4b0e-91f8-c3288ccff1c5,CommVoice,606 Broadcast Ave,0866666666,Mangrove Org,900 Forest Blvd,2023-11-05,450.0,Public awareness campaign ads,pending
 
 
 
 
 
 
 
 
src/chatbot/database/Project.csv DELETED
@@ -1,4 +0,0 @@
1
- project_id,title,status,detail_information,start_date,end_date
2
- 626e47da-76ae-4650-9d78-31072c1b5b0d,Mangrove Restoration,started,Restoring coastal ecosystems using mangrove plantations.,2023-01-01,2023-12-31
3
- f56b2354-ac70-4682-82f2-727ce13f4b71,Urban Tree Planting,started,Planting trees across the city for shade and air quality.,2023-02-01,2023-11-30
4
- 00cfa2f7-acb1-40aa-a420-d6c127c38c64,River Clean-up Campaign,started,Mobilizing volunteers to clean plastic from major rivers.,2023-03-01,2023-09-30
 
 
 
 
 
src/chatbot/database/create_sqlite_db.py DELETED
@@ -1,64 +0,0 @@
1
- import sqlite3
2
-
3
- conn = sqlite3.connect('hello_earth_data.db')
4
- cursor = conn.cursor()
5
-
6
- cursor.execute('''
7
- CREATE TABLE IF NOT EXISTS Project (
8
- project_id TEXT PRIMARY KEY,
9
- title TEXT,
10
- status TEXT,
11
- detail_information TEXT,
12
- start_date DATETIME,
13
- end_date DATETIME
14
- )
15
- ''')
16
-
17
- cursor.execute('''
18
- CREATE TABLE IF NOT EXISTS Deliverable (
19
- deliverable_id TEXT PRIMARY KEY,
20
- project_id TEXT,
21
- title TEXT,
22
- status TEXT CHECK(status IN ('done', 'ongoing')),
23
- risk_level TEXT CHECK(risk_level IN ('green', 'yellow', 'red')),
24
- risk_level_rationale TEXT,
25
- start_date DATETIME,
26
- end_date DATETIME,
27
- FOREIGN KEY (project_id) REFERENCES Project(project_id)
28
- )
29
- ''')
30
-
31
- cursor.execute('''
32
- CREATE TABLE IF NOT EXISTS Expense (
33
- expense_id TEXT PRIMARY KEY,
34
- associated_deliverable_id TEXT,
35
- seller_name TEXT,
36
- seller_address TEXT,
37
- seller_phone_number TEXT,
38
- buyer_name TEXT,
39
- buyer_address TEXT,
40
- transaction_date DATETIME,
41
- total_payment_amount REAL,
42
- expense_description TEXT,
43
- status TEXT,
44
- FOREIGN KEY (associated_deliverable_id) REFERENCES Deliverable(deliverable_id)
45
- )
46
- ''')
47
-
48
- cursor.execute('''
49
- CREATE TABLE IF NOT EXISTS Deliverable_Budget (
50
- id TEXT PRIMARY KEY,
51
- deliverable_id TEXT,
52
- wage REAL,
53
- materials REAL,
54
- tools_equipment REAL,
55
- services REAL,
56
- misc REAL,
57
- FOREIGN KEY (deliverable_id) REFERENCES Deliverable(deliverable_id)
58
- )
59
- ''')
60
-
61
- conn.commit()
62
- conn.close()
63
-
64
- print("SQLite database created with the specified schema.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/chatbot/database/export_data.py DELETED
@@ -1,22 +0,0 @@
1
- import sqlite3
2
- import pandas as pd
3
-
4
- def export_all_tables_to_csv(db_path='hello_earth_data.db', output_dir='.'):
5
- conn = sqlite3.connect(db_path)
6
- cursor = conn.cursor()
7
-
8
- # Get list of all tables
9
- cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
10
- tables = [row[0] for row in cursor.fetchall()]
11
-
12
- # Export each table
13
- for table in tables:
14
- df = pd.read_sql_query(f"SELECT * FROM {table}", conn)
15
- output_path = f"{output_dir}/{table}.csv"
16
- df.to_csv(output_path, index=False)
17
- print(f"βœ… Exported {table} to {output_path}")
18
-
19
- conn.close()
20
-
21
- if __name__ == '__main__':
22
- export_all_tables_to_csv()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/chatbot/database/hello_earth_data.db DELETED
Binary file (36.9 kB)
 
src/chatbot/database/mockup_data.py DELETED
@@ -1,317 +0,0 @@
1
- import sqlite3
2
- import uuid
3
-
4
- def generate_uuid():
5
- return str(uuid.uuid4())
6
-
7
- def insert_mock_data():
8
- conn = sqlite3.connect('hello_earth_data.db')
9
- cursor = conn.cursor()
10
-
11
- mock_data = []
12
-
13
- # Project 1
14
- project_1_id = generate_uuid()
15
- deliverable_1_1_id = generate_uuid()
16
- deliverable_1_2_id = generate_uuid()
17
- deliverable_1_3_id = generate_uuid() # New Deliverable
18
- deliverable_1_4_id = generate_uuid() # New Deliverable
19
- mock_data.append({
20
- "project": {
21
- "project_id": project_1_id,
22
- "title": "Mangrove Restoration",
23
- "status": "started",
24
- "detail_information": "Restoring coastal ecosystems using mangrove plantations.",
25
- "start_date": "2023-01-01",
26
- "end_date": "2023-12-31"
27
- },
28
- "deliverables": [
29
- {
30
- "deliverable_id": deliverable_1_1_id,
31
- "title": "Area Assessment",
32
- "status": "done",
33
- "risk_level": "green",
34
- "risk_level_rationale": "No environmental threats detected.",
35
- "start_date": "2023-01-05",
36
- "end_date": "2023-03-01"
37
- },
38
- {
39
- "deliverable_id": deliverable_1_2_id,
40
- "title": "Planting Phase",
41
- "status": "ongoing",
42
- "risk_level": "yellow",
43
- "risk_level_rationale": "Tide schedule interference.",
44
- "start_date": "2023-03-15",
45
- "end_date": "2023-08-30"
46
- },
47
- {
48
- "deliverable_id": deliverable_1_3_id,
49
- "title": "Monitoring Phase",
50
- "status": "ongoing",
51
- "risk_level": "green",
52
- "risk_level_rationale": "Stable growth rates observed.",
53
- "start_date": "2023-09-01",
54
- "end_date": "2023-11-01"
55
- },
56
- {
57
- "deliverable_id": deliverable_1_4_id,
58
- "title": "Community Education",
59
- "status": "ongoing",
60
- "risk_level": "yellow",
61
- "risk_level_rationale": "Low turnout in workshops.",
62
- "start_date": "2023-09-15",
63
- "end_date": "2023-12-15"
64
- }
65
- ],
66
- "budgets": [
67
- {
68
- "id": generate_uuid(),
69
- "deliverable_id": deliverable_1_1_id,
70
- "wage": 1000.0,
71
- "materials": 1500.0,
72
- "tools_equipment": 500.0,
73
- "services": 800.0,
74
- "misc": 100.0
75
- },
76
- {
77
- "id": generate_uuid(),
78
- "deliverable_id": deliverable_1_2_id,
79
- "wage": 1200.0,
80
- "materials": 2000.0,
81
- "tools_equipment": 700.0,
82
- "services": 1000.0,
83
- "misc": 150.0
84
- },
85
- {
86
- "id": generate_uuid(),
87
- "deliverable_id": deliverable_1_3_id,
88
- "wage": 1100.0,
89
- "materials": 800.0,
90
- "tools_equipment": 400.0,
91
- "services": 600.0,
92
- "misc": 90.0
93
- },
94
- {
95
- "id": generate_uuid(),
96
- "deliverable_id": deliverable_1_4_id,
97
- "wage": 950.0,
98
- "materials": 500.0,
99
- "tools_equipment": 300.0,
100
- "services": 750.0,
101
- "misc": 120.0
102
- }
103
- ],
104
- "expenses": [
105
- {
106
- "expense_id": generate_uuid(),
107
- "associated_deliverable_id": deliverable_1_1_id,
108
- "seller_name": "EcoTools Ltd.",
109
- "seller_address": "101 Earth Ave",
110
- "seller_phone_number": "0811111111",
111
- "buyer_name": "Mangrove Org",
112
- "buyer_address": "900 Forest Blvd",
113
- "transaction_date": "2023-01-20",
114
- "total_payment_amount": 1800.0,
115
- "expense_description": "Survey equipment rental",
116
- "status": "approved"
117
- },
118
- {
119
- "expense_id": generate_uuid(),
120
- "associated_deliverable_id": deliverable_1_2_id,
121
- "seller_name": "Green Nursery Supplies",
122
- "seller_address": "202 Plant Rd",
123
- "seller_phone_number": "0822222222",
124
- "buyer_name": "Mangrove Org",
125
- "buyer_address": "900 Forest Blvd",
126
- "transaction_date": "2023-04-10",
127
- "total_payment_amount": 2200.0,
128
- "expense_description": "Mangrove saplings and planting tools",
129
- "status": "approved"
130
- },
131
- {
132
- "expense_id": generate_uuid(),
133
- "associated_deliverable_id": deliverable_1_2_id,
134
- "seller_name": "TideLogistics",
135
- "seller_address": "303 Coastal Lane",
136
- "seller_phone_number": "0833333333",
137
- "buyer_name": "Mangrove Org",
138
- "buyer_address": "900 Forest Blvd",
139
- "transaction_date": "2023-06-05",
140
- "total_payment_amount": 1300.0,
141
- "expense_description": "Transport service for volunteers and gear",
142
- "status": "pending"
143
- },
144
- {
145
- "expense_id": generate_uuid(),
146
- "associated_deliverable_id": deliverable_1_3_id,
147
- "seller_name": "DroneVision Inc.",
148
- "seller_address": "404 Sky Blvd",
149
- "seller_phone_number": "0844444444",
150
- "buyer_name": "Mangrove Org",
151
- "buyer_address": "900 Forest Blvd",
152
- "transaction_date": "2023-09-10",
153
- "total_payment_amount": 1600.0,
154
- "expense_description": "Aerial monitoring drone rental",
155
- "status": "approved"
156
- },
157
- {
158
- "expense_id": generate_uuid(),
159
- "associated_deliverable_id": deliverable_1_4_id,
160
- "seller_name": "EduLeaf",
161
- "seller_address": "505 Learning St",
162
- "seller_phone_number": "0855555555",
163
- "buyer_name": "Mangrove Org",
164
- "buyer_address": "900 Forest Blvd",
165
- "transaction_date": "2023-10-01",
166
- "total_payment_amount": 900.0,
167
- "expense_description": "Educational materials and workshop kits",
168
- "status": "approved"
169
- },
170
- {
171
- "expense_id": generate_uuid(),
172
- "associated_deliverable_id": deliverable_1_4_id,
173
- "seller_name": "CommVoice",
174
- "seller_address": "606 Broadcast Ave",
175
- "seller_phone_number": "0866666666",
176
- "buyer_name": "Mangrove Org",
177
- "buyer_address": "900 Forest Blvd",
178
- "transaction_date": "2023-11-05",
179
- "total_payment_amount": 450.0,
180
- "expense_description": "Public awareness campaign ads",
181
- "status": "pending"
182
- }
183
- ]
184
- })
185
-
186
-
187
- # Project 2
188
- project_2_id = generate_uuid()
189
- deliverable_2_1_id = generate_uuid()
190
- deliverable_2_2_id = generate_uuid()
191
- mock_data.append({
192
- "project": {
193
- "project_id": project_2_id,
194
- "title": "Urban Tree Planting",
195
- "status": "started",
196
- "detail_information": "Planting trees across the city for shade and air quality.",
197
- "start_date": "2023-02-01",
198
- "end_date": "2023-11-30"
199
- },
200
- "deliverables": [
201
- {
202
- "deliverable_id": deliverable_2_1_id,
203
- "title": "Community Engagement",
204
- "status": "done",
205
- "risk_level": "green",
206
- "risk_level_rationale": "High public interest and participation.",
207
- "start_date": "2023-02-05",
208
- "end_date": "2023-04-01"
209
- },
210
- {
211
- "deliverable_id": deliverable_2_2_id,
212
- "title": "Planting Execution",
213
- "status": "ongoing",
214
- "risk_level": "red",
215
- "risk_level_rationale": "Insufficient volunteer workforce.",
216
- "start_date": "2023-04-10",
217
- "end_date": "2023-10-15"
218
- }
219
- ],
220
- "budgets": [
221
- {
222
- "id": generate_uuid(),
223
- "deliverable_id": deliverable_2_1_id,
224
- "wage": 1500.0,
225
- "materials": 1000.0,
226
- "tools_equipment": 300.0,
227
- "services": 500.0,
228
- "misc": 50.0
229
- }
230
- ],
231
- "expenses": []
232
- })
233
-
234
- # Project 3
235
- project_3_id = generate_uuid()
236
- deliverable_3_1_id = generate_uuid()
237
- deliverable_3_2_id = generate_uuid()
238
- mock_data.append({
239
- "project": {
240
- "project_id": project_3_id,
241
- "title": "River Clean-up Campaign",
242
- "status": "started",
243
- "detail_information": "Mobilizing volunteers to clean plastic from major rivers.",
244
- "start_date": "2023-03-01",
245
- "end_date": "2023-09-30"
246
- },
247
- "deliverables": [
248
- {
249
- "deliverable_id": deliverable_3_1_id,
250
- "title": "Equipment Procurement",
251
- "status": "done",
252
- "risk_level": "green",
253
- "risk_level_rationale": "Procurement completed on time.",
254
- "start_date": "2023-03-05",
255
- "end_date": "2023-04-01"
256
- },
257
- {
258
- "deliverable_id": deliverable_3_2_id,
259
- "title": "Volunteer Training",
260
- "status": "ongoing",
261
- "risk_level": "yellow",
262
- "risk_level_rationale": "Training attendance dropped by 10%.",
263
- "start_date": "2023-04-10",
264
- "end_date": "2023-06-30"
265
- }
266
- ],
267
- "budgets": [],
268
- "expenses": []
269
- })
270
-
271
- # === INSERT DATA INTO DB ===
272
- for item in mock_data:
273
- project = item["project"]
274
- cursor.execute('''
275
- INSERT INTO Project (project_id, title, status, detail_information, start_date, end_date)
276
- VALUES (?, ?, ?, ?, ?, ?)
277
- ''', (
278
- project["project_id"], project["title"], project["status"],
279
- project["detail_information"], project["start_date"], project["end_date"]
280
- ))
281
-
282
- for d in item.get("deliverables", []):
283
- cursor.execute('''
284
- INSERT INTO Deliverable (deliverable_id, project_id, title, status, risk_level,
285
- risk_level_rationale, start_date, end_date)
286
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
287
- ''', (
288
- d["deliverable_id"], project["project_id"], d["title"], d["status"],
289
- d["risk_level"], d["risk_level_rationale"], d["start_date"], d["end_date"]
290
- ))
291
-
292
- for b in item.get("budgets", []):
293
- cursor.execute('''
294
- INSERT INTO Deliverable_Budget (id, deliverable_id, wage, materials, tools_equipment, services, misc)
295
- VALUES (?, ?, ?, ?, ?, ?, ?)
296
- ''', (
297
- b["id"], b["deliverable_id"], b["wage"], b["materials"],
298
- b["tools_equipment"], b["services"], b["misc"]
299
- ))
300
-
301
- for e in item.get("expenses", []):
302
- cursor.execute('''
303
- INSERT INTO Expense (expense_id, associated_deliverable_id, seller_name, seller_address, seller_phone_number,
304
- buyer_name, buyer_address, transaction_date, total_payment_amount, expense_description, status)
305
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
306
- ''', (
307
- e["expense_id"], e["associated_deliverable_id"], e["seller_name"], e["seller_address"],
308
- e["seller_phone_number"], e["buyer_name"], e["buyer_address"],
309
- e["transaction_date"], e["total_payment_amount"], e["expense_description"], e["status"]
310
- ))
311
-
312
- conn.commit()
313
- conn.close()
314
- print("βœ… Multiple projects inserted with UUIDs.")
315
-
316
- if __name__ == '__main__':
317
- insert_mock_data()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/chatbot/kie.py CHANGED
@@ -78,7 +78,10 @@ def extract_form_information(client, receipt_text, max_retries=2):
78
  "Seller Phone Number": {"type": "string"},
79
  "Buyer Name": {"type": "string"},
80
  "Buyer Address": {"type": "string"},
81
- "Transaction Date": {"type": "string"},
 
 
 
82
 
83
  # "Payment Details Table": {
84
  # "type": "object",
 
78
  "Seller Phone Number": {"type": "string"},
79
  "Buyer Name": {"type": "string"},
80
  "Buyer Address": {"type": "string"},
81
+ "Transaction Date": {
82
+ "type": "string",
83
+ "description": "Date of transaction in ISO 8601 format (YYYY-MM-DD)"
84
+ },
85
 
86
  # "Payment Details Table": {
87
  # "type": "object",
src/chatbot/llm_engine.py CHANGED
@@ -26,9 +26,8 @@ def generate_expense_info_feedback(acceptance_criteria: dict, form_info: dict) -
26
  Generate feedback using OpenAI Chat Completion based on form_info.
27
  """
28
  current_date = datetime.now()
29
- buddhist_year = current_date.year + 543 # Convert to Buddhist year
30
- formatted_date = current_date.strftime(f"%d %B {buddhist_year}") # Format with Buddhist year
31
- print("current date (Buddhist year): {}".format(formatted_date))
32
 
33
  response = client.responses.create(
34
  model="gpt-4.1-mini",
 
26
  Generate feedback using OpenAI Chat Completion based on form_info.
27
  """
28
  current_date = datetime.now()
29
+ formatted_date = current_date.strftime(f"%d %B {current_date.year}") # Format with Buddhist year
30
+ print("current date: {}".format(formatted_date))
 
31
 
32
  response = client.responses.create(
33
  model="gpt-4.1-mini",
src/chatbot/prompts/agent_prompts.py CHANGED
@@ -15,6 +15,7 @@ Associated Deliverable: The deliverable associated with the payment.
15
  Expense Description: The description of the expense as it pertains to the project.
16
 
17
  Users cannot add new fields to the form, but they can edit the existing fields.
 
18
  Each time the form is revised, feedback will be provided, and your job to summarize current form information and convey the feedback to the user.
19
  Do not stray from the feedback provided.
20
  Do not mention the correct fields to the user, focus on the invalid one shown in the provided feedback.
 
15
  Expense Description: The description of the expense as it pertains to the project.
16
 
17
  Users cannot add new fields to the form, but they can edit the existing fields.
18
+ When inputting the 'Transaction Date', automatically convert the date to ISO 8601 format (YYYY-MM-DD).
19
  Each time the form is revised, feedback will be provided, and your job to summarize current form information and convey the feedback to the user.
20
  Do not stray from the feedback provided.
21
  Do not mention the correct fields to the user, focus on the invalid one shown in the provided feedback.
src/chatbot/prompts/kie_prompts.py CHANGED
@@ -1,5 +1,6 @@
1
  kie_prompt = """
2
- You are an AI model tasked with extracting key information from a Thai receipt document for payment confirmation. The image of the receipt will be provided as input. Your goal is to generate a JSON object containing the following keys:
 
3
 
4
  Seller Name: The name of the person or entity making the sale.
5
  Seller Address: The address of the seller.
 
1
  kie_prompt = """
2
+ You are an AI model tasked with extracting key information from a Thai receipt document for payment confirmation.
3
+ The image of the receipt will be provided as input. Your goal is to generate a JSON object containing the following keys:
4
 
5
  Seller Name: The name of the person or entity making the sale.
6
  Seller Address: The address of the seller.
src/{DB β†’ database}/Deliverable.csv RENAMED
File without changes
src/{DB β†’ database}/Deliverable_Budget.csv RENAMED
File without changes
src/{DB β†’ database}/Expense.csv RENAMED
File without changes
src/{DB β†’ database}/Project.csv RENAMED
File without changes
src/{DB β†’ database}/archive_db/Deliverable.csv RENAMED
File without changes
src/{DB β†’ database}/archive_db/Deliverable_Budget.csv RENAMED
File without changes
src/{DB β†’ database}/archive_db/Expense.csv RENAMED
File without changes
src/{DB β†’ database}/archive_db/Project.csv RENAMED
File without changes
src/{DB β†’ database}/archive_db/hello_earth_data.db RENAMED
File without changes
src/{DB β†’ database}/create_sqlite_db.py RENAMED
File without changes
src/{DB β†’ database}/export_data.py RENAMED
File without changes
src/{DB β†’ database}/hello_earth_data_2.db RENAMED
File without changes
src/{DB β†’ database}/mockup_data.py RENAMED
File without changes
src/poetry.lock CHANGED
@@ -201,104 +201,104 @@ pycparser = "*"
201
 
202
  [[package]]
203
  name = "charset-normalizer"
204
- version = "3.4.1"
205
  description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
206
  optional = false
207
  python-versions = ">=3.7"
208
  groups = ["main"]
209
  files = [
210
- {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"},
211
- {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"},
212
- {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"},
213
- {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"},
214
- {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"},
215
- {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"},
216
- {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"},
217
- {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"},
218
- {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"},
219
- {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"},
220
- {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"},
221
- {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"},
222
- {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"},
223
- {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"},
224
- {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"},
225
- {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"},
226
- {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"},
227
- {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"},
228
- {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"},
229
- {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"},
230
- {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"},
231
- {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"},
232
- {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"},
233
- {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"},
234
- {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"},
235
- {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"},
236
- {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"},
237
- {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"},
238
- {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"},
239
- {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"},
240
- {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"},
241
- {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"},
242
- {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"},
243
- {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"},
244
- {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"},
245
- {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"},
246
- {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"},
247
- {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"},
248
- {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"},
249
- {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"},
250
- {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"},
251
- {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"},
252
- {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"},
253
- {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"},
254
- {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"},
255
- {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"},
256
- {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"},
257
- {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"},
258
- {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"},
259
- {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"},
260
- {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"},
261
- {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"},
262
- {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"},
263
- {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"},
264
- {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"},
265
- {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"},
266
- {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"},
267
- {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"},
268
- {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"},
269
- {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"},
270
- {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"},
271
- {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"},
272
- {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"},
273
- {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"},
274
- {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"},
275
- {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"},
276
- {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"},
277
- {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"},
278
- {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"},
279
- {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"},
280
- {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"},
281
- {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"},
282
- {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"},
283
- {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"},
284
- {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"},
285
- {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"},
286
- {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"},
287
- {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"},
288
- {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"},
289
- {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"},
290
- {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"},
291
- {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"},
292
- {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"},
293
- {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"},
294
- {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"},
295
- {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"},
296
- {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"},
297
- {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"},
298
- {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"},
299
- {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"},
300
- {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"},
301
- {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"},
302
  ]
303
 
304
  [[package]]
@@ -475,14 +475,14 @@ tqdm = ["tqdm"]
475
 
476
  [[package]]
477
  name = "gradio"
478
- version = "5.28.0"
479
  description = "Python library for easily interacting with trained machine learning models"
480
  optional = false
481
  python-versions = ">=3.10"
482
  groups = ["main"]
483
  files = [
484
- {file = "gradio-5.28.0-py3-none-any.whl", hash = "sha256:f4c56bfbf6d1343728de4f6104e559ec26dbea3771efbba0cd8e4f0046e864db"},
485
- {file = "gradio-5.28.0.tar.gz", hash = "sha256:31f259f35beba6b58ef0b942d44891f9f8e05e466778cb1c830b75fe75ac5b65"},
486
  ]
487
 
488
  [package.dependencies]
@@ -520,6 +520,24 @@ uvicorn = {version = ">=0.14.0", markers = "sys_platform != \"emscripten\""}
520
  mcp = ["mcp (>=1.6.0,<2.0.0)", "pydantic (>=2.11) ; sys_platform != \"emscripten\""]
521
  oauth = ["authlib", "itsdangerous"]
522
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
523
  [[package]]
524
  name = "gradio-client"
525
  version = "1.10.0"
@@ -935,18 +953,18 @@ files = [
935
 
936
  [[package]]
937
  name = "langchain"
938
- version = "0.3.24"
939
  description = "Building applications with LLMs through composability"
940
  optional = false
941
- python-versions = "<4.0,>=3.9"
942
  groups = ["main"]
943
  files = [
944
- {file = "langchain-0.3.24-py3-none-any.whl", hash = "sha256:596c5444716644ddd0cd819fb2bc9d0fd4221503b219fdfb5016edcfaa7da8ef"},
945
- {file = "langchain-0.3.24.tar.gz", hash = "sha256:caf1bacdabbea429bc79b58b118c06c3386107d92812e15922072b91745f070f"},
946
  ]
947
 
948
  [package.dependencies]
949
- langchain-core = ">=0.3.55,<1.0.0"
950
  langchain-text-splitters = ">=0.3.8,<1.0.0"
951
  langsmith = ">=0.1.17,<0.4"
952
  pydantic = ">=2.7.4,<3.0.0"
@@ -975,14 +993,14 @@ xai = ["langchain-xai"]
975
 
976
  [[package]]
977
  name = "langchain-core"
978
- version = "0.3.56"
979
  description = "Building applications with LLMs through composability"
980
  optional = false
981
- python-versions = "<4.0,>=3.9"
982
  groups = ["main"]
983
  files = [
984
- {file = "langchain_core-0.3.56-py3-none-any.whl", hash = "sha256:a20c6aca0fa0da265d96d3b14a5a01828ac5d2d9d27516434873d76f2d4839ed"},
985
- {file = "langchain_core-0.3.56.tar.gz", hash = "sha256:de896585bc56e12652327dcd195227c3739a07e86e587c91a07101e0df11dffe"},
986
  ]
987
 
988
  [package.dependencies]
@@ -996,18 +1014,18 @@ typing-extensions = ">=4.7"
996
 
997
  [[package]]
998
  name = "langchain-openai"
999
- version = "0.3.14"
1000
  description = "An integration package connecting OpenAI and LangChain"
1001
  optional = false
1002
- python-versions = "<4.0,>=3.9"
1003
  groups = ["main"]
1004
  files = [
1005
- {file = "langchain_openai-0.3.14-py3-none-any.whl", hash = "sha256:b8e648d2d7678a5540818199d141ff727c6f1514294b3e1e999a95357c9d66a0"},
1006
- {file = "langchain_openai-0.3.14.tar.gz", hash = "sha256:0662db78620c2e5c3ccfc1c36dc959c0ddc80e6bdf7ef81632cbf4b2cc9b9461"},
1007
  ]
1008
 
1009
  [package.dependencies]
1010
- langchain-core = ">=0.3.53,<1.0.0"
1011
  openai = ">=1.68.2,<2.0.0"
1012
  tiktoken = ">=0.7,<1"
1013
 
@@ -1096,14 +1114,14 @@ orjson = ">=3.10.1"
1096
 
1097
  [[package]]
1098
  name = "langsmith"
1099
- version = "0.3.39"
1100
  description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
1101
  optional = false
1102
  python-versions = ">=3.9"
1103
  groups = ["main"]
1104
  files = [
1105
- {file = "langsmith-0.3.39-py3-none-any.whl", hash = "sha256:0c2af42e943e112bd0a1bd7452922141945b71f08df32cc5d6faa637100bc5e3"},
1106
- {file = "langsmith-0.3.39.tar.gz", hash = "sha256:1624a70efe1c9378ed0802618e9f7cc14e45d50ec4a9b3af45137fa27ad95690"},
1107
  ]
1108
 
1109
  [package.dependencies]
@@ -1121,6 +1139,22 @@ openai-agents = ["openai-agents (>=0.0.3,<0.1)"]
1121
  otel = ["opentelemetry-api (>=1.30.0,<2.0.0)", "opentelemetry-exporter-otlp-proto-http (>=1.30.0,<2.0.0)", "opentelemetry-sdk (>=1.30.0,<2.0.0)"]
1122
  pytest = ["pytest (>=7.0.0)", "rich (>=13.9.4,<14.0.0)"]
1123
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1124
  [[package]]
1125
  name = "markdown-it-py"
1126
  version = "3.0.0"
@@ -1246,6 +1280,31 @@ files = [
1246
  {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
1247
  ]
1248
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1249
  [[package]]
1250
  name = "numpy"
1251
  version = "2.2.5"
@@ -1313,14 +1372,14 @@ files = [
1313
 
1314
  [[package]]
1315
  name = "openai"
1316
- version = "1.76.2"
1317
  description = "The official Python library for the openai API"
1318
  optional = false
1319
  python-versions = ">=3.8"
1320
  groups = ["main"]
1321
  files = [
1322
- {file = "openai-1.76.2-py3-none-any.whl", hash = "sha256:9c1d9ad59e6e3bea7205eedc9ca66eeebae18d47b527e505a2b0d2fb1538e26e"},
1323
- {file = "openai-1.76.2.tar.gz", hash = "sha256:f430c8b848775907405c6eff54621254c96f6444c593c097e0cc3a9f8fdda96f"},
1324
  ]
1325
 
1326
  [package.dependencies]
@@ -1698,6 +1757,27 @@ tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "ole
1698
  typing = ["typing-extensions ; python_version < \"3.10\""]
1699
  xmp = ["defusedxml"]
1700
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1701
  [[package]]
1702
  name = "prompt-toolkit"
1703
  version = "3.0.51"
@@ -2195,31 +2275,31 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
2195
 
2196
  [[package]]
2197
  name = "ruff"
2198
- version = "0.11.7"
2199
  description = "An extremely fast Python linter and code formatter, written in Rust."
2200
  optional = false
2201
  python-versions = ">=3.7"
2202
  groups = ["main"]
2203
  markers = "sys_platform != \"emscripten\""
2204
  files = [
2205
- {file = "ruff-0.11.7-py3-none-linux_armv6l.whl", hash = "sha256:d29e909d9a8d02f928d72ab7837b5cbc450a5bdf578ab9ebee3263d0a525091c"},
2206
- {file = "ruff-0.11.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dd1fb86b168ae349fb01dd497d83537b2c5541fe0626e70c786427dd8363aaee"},
2207
- {file = "ruff-0.11.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3d7d2e140a6fbbc09033bce65bd7ea29d6a0adeb90b8430262fbacd58c38ada"},
2208
- {file = "ruff-0.11.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4809df77de390a1c2077d9b7945d82f44b95d19ceccf0c287c56e4dc9b91ca64"},
2209
- {file = "ruff-0.11.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3a0c2e169e6b545f8e2dba185eabbd9db4f08880032e75aa0e285a6d3f48201"},
2210
- {file = "ruff-0.11.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49b888200a320dd96a68e86736cf531d6afba03e4f6cf098401406a257fcf3d6"},
2211
- {file = "ruff-0.11.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2b19cdb9cf7dae00d5ee2e7c013540cdc3b31c4f281f1dacb5a799d610e90db4"},
2212
- {file = "ruff-0.11.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64e0ee994c9e326b43539d133a36a455dbaab477bc84fe7bfbd528abe2f05c1e"},
2213
- {file = "ruff-0.11.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bad82052311479a5865f52c76ecee5d468a58ba44fb23ee15079f17dd4c8fd63"},
2214
- {file = "ruff-0.11.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7940665e74e7b65d427b82bffc1e46710ec7f30d58b4b2d5016e3f0321436502"},
2215
- {file = "ruff-0.11.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:169027e31c52c0e36c44ae9a9c7db35e505fee0b39f8d9fca7274a6305295a92"},
2216
- {file = "ruff-0.11.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:305b93f9798aee582e91e34437810439acb28b5fc1fee6b8205c78c806845a94"},
2217
- {file = "ruff-0.11.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a681db041ef55550c371f9cd52a3cf17a0da4c75d6bd691092dfc38170ebc4b6"},
2218
- {file = "ruff-0.11.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:07f1496ad00a4a139f4de220b0c97da6d4c85e0e4aa9b2624167b7d4d44fd6b6"},
2219
- {file = "ruff-0.11.7-py3-none-win32.whl", hash = "sha256:f25dfb853ad217e6e5f1924ae8a5b3f6709051a13e9dad18690de6c8ff299e26"},
2220
- {file = "ruff-0.11.7-py3-none-win_amd64.whl", hash = "sha256:0a931d85959ceb77e92aea4bbedfded0a31534ce191252721128f77e5ae1f98a"},
2221
- {file = "ruff-0.11.7-py3-none-win_arm64.whl", hash = "sha256:778c1e5d6f9e91034142dfd06110534ca13220bfaad5c3735f6cb844654f6177"},
2222
- {file = "ruff-0.11.7.tar.gz", hash = "sha256:655089ad3224070736dc32844fde783454f8558e71f501cb207485fe4eee23d4"},
2223
  ]
2224
 
2225
  [[package]]
@@ -2427,6 +2507,21 @@ anyio = ">=3.6.2,<5"
2427
  [package.extras]
2428
  full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"]
2429
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2430
  [[package]]
2431
  name = "tenacity"
2432
  version = "9.1.2"
@@ -2977,4 +3072,4 @@ cffi = ["cffi (>=1.11)"]
2977
  [metadata]
2978
  lock-version = "2.1"
2979
  python-versions = ">=3.12.4,<4.0.0"
2980
- content-hash = "efbddde7effbf9adb8d0fd2294ffca2d5f4460bf12f75cfab57a0a47ca868c0e"
 
201
 
202
  [[package]]
203
  name = "charset-normalizer"
204
+ version = "3.4.2"
205
  description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
206
  optional = false
207
  python-versions = ">=3.7"
208
  groups = ["main"]
209
  files = [
210
+ {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"},
211
+ {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"},
212
+ {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"},
213
+ {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"},
214
+ {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"},
215
+ {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"},
216
+ {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"},
217
+ {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"},
218
+ {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"},
219
+ {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"},
220
+ {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"},
221
+ {file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"},
222
+ {file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"},
223
+ {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"},
224
+ {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"},
225
+ {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"},
226
+ {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"},
227
+ {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"},
228
+ {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"},
229
+ {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"},
230
+ {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"},
231
+ {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"},
232
+ {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"},
233
+ {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"},
234
+ {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"},
235
+ {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"},
236
+ {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"},
237
+ {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"},
238
+ {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"},
239
+ {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"},
240
+ {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"},
241
+ {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"},
242
+ {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"},
243
+ {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"},
244
+ {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"},
245
+ {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"},
246
+ {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"},
247
+ {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"},
248
+ {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"},
249
+ {file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"},
250
+ {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"},
251
+ {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"},
252
+ {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"},
253
+ {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"},
254
+ {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"},
255
+ {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"},
256
+ {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"},
257
+ {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"},
258
+ {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"},
259
+ {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"},
260
+ {file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"},
261
+ {file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"},
262
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"},
263
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"},
264
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"},
265
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"},
266
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"},
267
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"},
268
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"},
269
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"},
270
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"},
271
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"},
272
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"},
273
+ {file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"},
274
+ {file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"},
275
+ {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"},
276
+ {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"},
277
+ {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"},
278
+ {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"},
279
+ {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"},
280
+ {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"},
281
+ {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"},
282
+ {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"},
283
+ {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"},
284
+ {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"},
285
+ {file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"},
286
+ {file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"},
287
+ {file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"},
288
+ {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"},
289
+ {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"},
290
+ {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"},
291
+ {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"},
292
+ {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"},
293
+ {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"},
294
+ {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"},
295
+ {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"},
296
+ {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"},
297
+ {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"},
298
+ {file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"},
299
+ {file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"},
300
+ {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"},
301
+ {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"},
302
  ]
303
 
304
  [[package]]
 
475
 
476
  [[package]]
477
  name = "gradio"
478
+ version = "5.29.0"
479
  description = "Python library for easily interacting with trained machine learning models"
480
  optional = false
481
  python-versions = ">=3.10"
482
  groups = ["main"]
483
  files = [
484
+ {file = "gradio-5.29.0-py3-none-any.whl", hash = "sha256:6b58321c3b2d596a701e9b1660334772a160262e4c67f18848bd54b6c0db7d89"},
485
+ {file = "gradio-5.29.0.tar.gz", hash = "sha256:56fdd8b7cb31de8e4c382677560ef8a79f4ae0c3fbb139341bce052aab728064"},
486
  ]
487
 
488
  [package.dependencies]
 
520
  mcp = ["mcp (>=1.6.0,<2.0.0)", "pydantic (>=2.11) ; sys_platform != \"emscripten\""]
521
  oauth = ["authlib", "itsdangerous"]
522
 
523
+ [[package]]
524
+ name = "gradio-calendar"
525
+ version = "0.0.6"
526
+ description = "Gradio component for selecting dates with a calendar πŸ“†"
527
+ optional = false
528
+ python-versions = ">=3.8"
529
+ groups = ["main"]
530
+ files = [
531
+ {file = "gradio_calendar-0.0.6-py3-none-any.whl", hash = "sha256:2431b84ee2228be96770e907a478a4724cc36cc970a10e2b4209c85aa2373e2c"},
532
+ {file = "gradio_calendar-0.0.6.tar.gz", hash = "sha256:728addfc07c350d46b69459447eb1e390d87ada0ddaed3457bd78da480eca2ec"},
533
+ ]
534
+
535
+ [package.dependencies]
536
+ gradio = ">=4.0,<6.0"
537
+
538
+ [package.extras]
539
+ dev = ["build", "twine"]
540
+
541
  [[package]]
542
  name = "gradio-client"
543
  version = "1.10.0"
 
953
 
954
  [[package]]
955
  name = "langchain"
956
+ version = "0.3.25"
957
  description = "Building applications with LLMs through composability"
958
  optional = false
959
+ python-versions = ">=3.9"
960
  groups = ["main"]
961
  files = [
962
+ {file = "langchain-0.3.25-py3-none-any.whl", hash = "sha256:931f7d2d1eaf182f9f41c5e3272859cfe7f94fc1f7cef6b3e5a46024b4884c21"},
963
+ {file = "langchain-0.3.25.tar.gz", hash = "sha256:a1d72aa39546a23db08492d7228464af35c9ee83379945535ceef877340d2a3a"},
964
  ]
965
 
966
  [package.dependencies]
967
+ langchain-core = ">=0.3.58,<1.0.0"
968
  langchain-text-splitters = ">=0.3.8,<1.0.0"
969
  langsmith = ">=0.1.17,<0.4"
970
  pydantic = ">=2.7.4,<3.0.0"
 
993
 
994
  [[package]]
995
  name = "langchain-core"
996
+ version = "0.3.58"
997
  description = "Building applications with LLMs through composability"
998
  optional = false
999
+ python-versions = ">=3.9"
1000
  groups = ["main"]
1001
  files = [
1002
+ {file = "langchain_core-0.3.58-py3-none-any.whl", hash = "sha256:266f90d2a079fe9510190ad3be88bd993baad43e6cee0f822a883767a4bfdd5b"},
1003
+ {file = "langchain_core-0.3.58.tar.gz", hash = "sha256:6ee2282b02fa65bf4ee1afa869d431505536757ff2f1f9f0b432d8ca755d66c6"},
1004
  ]
1005
 
1006
  [package.dependencies]
 
1014
 
1015
  [[package]]
1016
  name = "langchain-openai"
1017
+ version = "0.3.16"
1018
  description = "An integration package connecting OpenAI and LangChain"
1019
  optional = false
1020
+ python-versions = ">=3.9"
1021
  groups = ["main"]
1022
  files = [
1023
+ {file = "langchain_openai-0.3.16-py3-none-any.whl", hash = "sha256:eae74a6758d38a26159c5fde5abf8ef313e6400efb01a08f12dd7410c9f4fd0f"},
1024
+ {file = "langchain_openai-0.3.16.tar.gz", hash = "sha256:4e423e39d072f1432adc9430f2905fe635cc019f01ad1bdffa5ed8d0dda32149"},
1025
  ]
1026
 
1027
  [package.dependencies]
1028
+ langchain-core = ">=0.3.58,<1.0.0"
1029
  openai = ">=1.68.2,<2.0.0"
1030
  tiktoken = ">=0.7,<1"
1031
 
 
1114
 
1115
  [[package]]
1116
  name = "langsmith"
1117
+ version = "0.3.42"
1118
  description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
1119
  optional = false
1120
  python-versions = ">=3.9"
1121
  groups = ["main"]
1122
  files = [
1123
+ {file = "langsmith-0.3.42-py3-none-any.whl", hash = "sha256:18114327f3364385dae4026ebfd57d1c1cb46d8f80931098f0f10abe533475ff"},
1124
+ {file = "langsmith-0.3.42.tar.gz", hash = "sha256:2b5cbc450ab808b992362aac6943bb1d285579aa68a3a8be901d30a393458f25"},
1125
  ]
1126
 
1127
  [package.dependencies]
 
1139
  otel = ["opentelemetry-api (>=1.30.0,<2.0.0)", "opentelemetry-exporter-otlp-proto-http (>=1.30.0,<2.0.0)", "opentelemetry-sdk (>=1.30.0,<2.0.0)"]
1140
  pytest = ["pytest (>=7.0.0)", "rich (>=13.9.4,<14.0.0)"]
1141
 
1142
+ [[package]]
1143
+ name = "markdown"
1144
+ version = "3.8"
1145
+ description = "Python implementation of John Gruber's Markdown."
1146
+ optional = false
1147
+ python-versions = ">=3.9"
1148
+ groups = ["main"]
1149
+ files = [
1150
+ {file = "markdown-3.8-py3-none-any.whl", hash = "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc"},
1151
+ {file = "markdown-3.8.tar.gz", hash = "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f"},
1152
+ ]
1153
+
1154
+ [package.extras]
1155
+ docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"]
1156
+ testing = ["coverage", "pyyaml"]
1157
+
1158
  [[package]]
1159
  name = "markdown-it-py"
1160
  version = "3.0.0"
 
1280
  {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
1281
  ]
1282
 
1283
+ [[package]]
1284
+ name = "narwhals"
1285
+ version = "1.39.1"
1286
+ description = "Extremely lightweight compatibility layer between dataframe libraries"
1287
+ optional = false
1288
+ python-versions = ">=3.8"
1289
+ groups = ["main"]
1290
+ files = [
1291
+ {file = "narwhals-1.39.1-py3-none-any.whl", hash = "sha256:68d0f29c760f1a9419ada537f35f21ff202b0be1419e6d22135a0352c6d96deb"},
1292
+ {file = "narwhals-1.39.1.tar.gz", hash = "sha256:cf15389e6f8c5321e8cd0ca8b5bace3b1aea5f5622fa59dfd64821998741d836"},
1293
+ ]
1294
+
1295
+ [package.extras]
1296
+ cudf = ["cudf (>=24.10.0)"]
1297
+ dask = ["dask[dataframe] (>=2024.8)"]
1298
+ duckdb = ["duckdb (>=1.0)"]
1299
+ ibis = ["ibis-framework (>=6.0.0)", "packaging", "pyarrow-hotfix", "rich"]
1300
+ modin = ["modin"]
1301
+ pandas = ["pandas (>=0.25.3)"]
1302
+ polars = ["polars (>=0.20.3)"]
1303
+ pyarrow = ["pyarrow (>=11.0.0)"]
1304
+ pyspark = ["pyspark (>=3.5.0)"]
1305
+ pyspark-connect = ["pyspark[connect] (>=3.5.0)"]
1306
+ sqlframe = ["sqlframe (>=3.22.0)"]
1307
+
1308
  [[package]]
1309
  name = "numpy"
1310
  version = "2.2.5"
 
1372
 
1373
  [[package]]
1374
  name = "openai"
1375
+ version = "1.77.0"
1376
  description = "The official Python library for the openai API"
1377
  optional = false
1378
  python-versions = ">=3.8"
1379
  groups = ["main"]
1380
  files = [
1381
+ {file = "openai-1.77.0-py3-none-any.whl", hash = "sha256:07706e91eb71631234996989a8ea991d5ee56f0744ef694c961e0824d4f39218"},
1382
+ {file = "openai-1.77.0.tar.gz", hash = "sha256:897969f927f0068b8091b4b041d1f8175bcf124f7ea31bab418bf720971223bc"},
1383
  ]
1384
 
1385
  [package.dependencies]
 
1757
  typing = ["typing-extensions ; python_version < \"3.10\""]
1758
  xmp = ["defusedxml"]
1759
 
1760
+ [[package]]
1761
+ name = "plotly"
1762
+ version = "6.1.0"
1763
+ description = "An open-source interactive data visualization library for Python"
1764
+ optional = false
1765
+ python-versions = ">=3.8"
1766
+ groups = ["main"]
1767
+ files = [
1768
+ {file = "plotly-6.1.0-py3-none-any.whl", hash = "sha256:a29d3ed523c9d7960095693af1ee52689830df0f9c6bae3e5e92c20c4f5684c3"},
1769
+ {file = "plotly-6.1.0.tar.gz", hash = "sha256:f13f497ccc2d97f06f771a30b27fab0cbd220f2975865f4ecbc75057135521de"},
1770
+ ]
1771
+
1772
+ [package.dependencies]
1773
+ narwhals = ">=1.15.1"
1774
+ packaging = "*"
1775
+
1776
+ [package.extras]
1777
+ dev = ["black (==25.1.0)"]
1778
+ express = ["numpy"]
1779
+ kaleido = ["kaleido (==1.0.0rc13)"]
1780
+
1781
  [[package]]
1782
  name = "prompt-toolkit"
1783
  version = "3.0.51"
 
2275
 
2276
  [[package]]
2277
  name = "ruff"
2278
+ version = "0.11.8"
2279
  description = "An extremely fast Python linter and code formatter, written in Rust."
2280
  optional = false
2281
  python-versions = ">=3.7"
2282
  groups = ["main"]
2283
  markers = "sys_platform != \"emscripten\""
2284
  files = [
2285
+ {file = "ruff-0.11.8-py3-none-linux_armv6l.whl", hash = "sha256:896a37516c594805e34020c4a7546c8f8a234b679a7716a3f08197f38913e1a3"},
2286
+ {file = "ruff-0.11.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ab86d22d3d721a40dd3ecbb5e86ab03b2e053bc93c700dc68d1c3346b36ce835"},
2287
+ {file = "ruff-0.11.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:258f3585057508d317610e8a412788cf726efeefa2fec4dba4001d9e6f90d46c"},
2288
+ {file = "ruff-0.11.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:727d01702f7c30baed3fc3a34901a640001a2828c793525043c29f7614994a8c"},
2289
+ {file = "ruff-0.11.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3dca977cc4fc8f66e89900fa415ffe4dbc2e969da9d7a54bfca81a128c5ac219"},
2290
+ {file = "ruff-0.11.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c657fa987d60b104d2be8b052d66da0a2a88f9bd1d66b2254333e84ea2720c7f"},
2291
+ {file = "ruff-0.11.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f2e74b021d0de5eceb8bd32919f6ff8a9b40ee62ed97becd44993ae5b9949474"},
2292
+ {file = "ruff-0.11.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9b5ef39820abc0f2c62111f7045009e46b275f5b99d5e59dda113c39b7f4f38"},
2293
+ {file = "ruff-0.11.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1dba3135ca503727aa4648152c0fa67c3b1385d3dc81c75cd8a229c4b2a1458"},
2294
+ {file = "ruff-0.11.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f024d32e62faad0f76b2d6afd141b8c171515e4fb91ce9fd6464335c81244e5"},
2295
+ {file = "ruff-0.11.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d365618d3ad747432e1ae50d61775b78c055fee5936d77fb4d92c6f559741948"},
2296
+ {file = "ruff-0.11.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4d9aaa91035bdf612c8ee7266153bcf16005c7c7e2f5878406911c92a31633cb"},
2297
+ {file = "ruff-0.11.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0eba551324733efc76116d9f3a0d52946bc2751f0cd30661564117d6fd60897c"},
2298
+ {file = "ruff-0.11.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:161eb4cff5cfefdb6c9b8b3671d09f7def2f960cee33481dd898caf2bcd02304"},
2299
+ {file = "ruff-0.11.8-py3-none-win32.whl", hash = "sha256:5b18caa297a786465cc511d7f8be19226acf9c0a1127e06e736cd4e1878c3ea2"},
2300
+ {file = "ruff-0.11.8-py3-none-win_amd64.whl", hash = "sha256:6e70d11043bef637c5617297bdedec9632af15d53ac1e1ba29c448da9341b0c4"},
2301
+ {file = "ruff-0.11.8-py3-none-win_arm64.whl", hash = "sha256:304432e4c4a792e3da85b7699feb3426a0908ab98bf29df22a31b0cdd098fac2"},
2302
+ {file = "ruff-0.11.8.tar.gz", hash = "sha256:6d742d10626f9004b781f4558154bb226620a7242080e11caeffab1a40e99df8"},
2303
  ]
2304
 
2305
  [[package]]
 
2507
  [package.extras]
2508
  full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"]
2509
 
2510
+ [[package]]
2511
+ name = "tabulate"
2512
+ version = "0.9.0"
2513
+ description = "Pretty-print tabular data"
2514
+ optional = false
2515
+ python-versions = ">=3.7"
2516
+ groups = ["main"]
2517
+ files = [
2518
+ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"},
2519
+ {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"},
2520
+ ]
2521
+
2522
+ [package.extras]
2523
+ widechars = ["wcwidth"]
2524
+
2525
  [[package]]
2526
  name = "tenacity"
2527
  version = "9.1.2"
 
3072
  [metadata]
3073
  lock-version = "2.1"
3074
  python-versions = ">=3.12.4,<4.0.0"
3075
+ content-hash = "83328808e618fc1322ad57b7279040ddcd509dd60d4582ca4056ec1a8ea8e5d2"
src/pyproject.toml CHANGED
@@ -14,7 +14,11 @@ dependencies = [
14
  "langgraph (>=0.4.1,<0.5.0)",
15
  "langchain (>=0.3.24,<0.4.0)",
16
  "langchain-openai (>=0.3.14,<0.4.0)",
17
- "ipython (>=9.2.0,<10.0.0)"
 
 
 
 
18
  ]
19
 
20
 
 
14
  "langgraph (>=0.4.1,<0.5.0)",
15
  "langchain (>=0.3.24,<0.4.0)",
16
  "langchain-openai (>=0.3.14,<0.4.0)",
17
+ "ipython (>=9.2.0,<10.0.0)",
18
+ "gradio-calendar (>=0.0.6,<0.0.7)",
19
+ "tabulate (>=0.9.0,<0.10.0)",
20
+ "markdown (>=3.8,<4.0)",
21
+ "plotly (>=6.1.0,<7.0.0)"
22
  ]
23
 
24