NujacsaintS commited on
Commit
e67fd82
·
verified ·
1 Parent(s): 9f5e052

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -236
app.py CHANGED
@@ -1,251 +1,42 @@
1
- from shiny import App, ui, render, reactive
2
- import json
3
- import datetime as dt
 
 
 
 
4
 
5
  # -----------------------------
6
- # UI
7
  # -----------------------------
8
 
9
- app_ui = ui.page_fluid(
10
- ui.h2("Tessai Link: Phase 0"),
11
- ui.p(
12
- "This form helps us understand your current environment and what you "
13
- "are hoping to change. Fill out what you can -- we will review the rest together."
14
- ),
15
-
16
- ui.layout_columns(
17
- # Left column: basic company + contacts
18
- ui.card(
19
- ui.card_header("1. Company & Contact"),
20
- ui.input_text("company_name", "Company name"),
21
- ui.input_text("contact_name", "Primary contact name"),
22
- ui.input_text("contact_role", "Contact role / title"),
23
- ui.input_text("contact_email", "Contact email"),
24
- ui.input_text("contact_phone", "Contact phone (optional)"),
25
- ),
26
-
27
- # Right column: project trigger + goals
28
- ui.card(
29
- ui.card_header("2. Why now?"),
30
- ui.input_text_area(
31
- "project_trigger",
32
- "What triggered this project now?",
33
- placeholder="Example: Our current system is slowing us down, we are growing, a new compliance requirement, etc.",
34
- rows=4,
35
- ),
36
- ui.input_text_area(
37
- "primary_outcomes",
38
- "What outcomes would feel like a clear win?",
39
- placeholder="Example: Fewer dropped handoffs, clearer ownership, faster quoting, better visibility across teams...",
40
- rows=4,
41
- ),
42
- ),
43
- ),
44
 
45
- ui.layout_columns(
46
- # Current tools / systems / data
47
- ui.card(
48
- ui.card_header("3. Current tools & data"),
49
- ui.input_text_area(
50
- "current_tools",
51
- "Current tools / systems in use",
52
- placeholder="Example: Excel, email, QuickBooks, Odoo, custom access DB, paper forms...",
53
- rows=4,
54
- ),
55
- ui.input_text_area(
56
- "data_sources",
57
- "Key data sources we should know about",
58
- placeholder="Example: Shared drives, vendor portals, ERP, CRM, PDF drawings, email inboxes...",
59
- rows=4,
60
- ),
61
- ),
62
 
63
- # Scope, change profile, constraints
64
- ui.card(
65
- ui.card_header("4. Scope & constraints"),
66
- ui.input_selectize(
67
- "areas_of_interest",
68
- "Primary areas you want to improve (choose all that apply)",
69
- choices=[
70
- "Lead / opportunity tracking",
71
- "Quoting / estimating",
72
- "Operations / workflows",
73
- "Vendor integration",
74
- "Reporting / dashboards",
75
- "Document / email intake",
76
- "Change management / approvals",
77
- "Other",
78
- ],
79
- multiple=True,
80
- ),
81
- ui.input_radio_buttons(
82
- "change_profile",
83
- "How would you describe this change?",
84
- choices=[
85
- "Exploring options -- nothing urgent yet",
86
- "We have a clearly broken process to fix",
87
- "We are replacing or consolidating existing systems",
88
- "We have a hard deadline / compliance date",
89
- ],
90
- ),
91
- ui.input_select(
92
- "team_size",
93
- "Roughly how many people are affected?",
94
- choices=[
95
- "1–5",
96
- "6–15",
97
- "16–50",
98
- "51–150",
99
- "150+",
100
- ],
101
- ),
102
- ui.input_select(
103
- "timeline",
104
- "Ideal timeline to see first meaningful results",
105
- choices=[
106
- "0–6 weeks",
107
- "6–12 weeks",
108
- "3–6 months",
109
- "6–12 months",
110
- "Just exploring for now",
111
- ],
112
- ),
113
- ),
114
- ),
115
 
116
- ui.layout_columns(
117
- ui.card(
118
- ui.card_header("5. Risks, blockers, and notes"),
119
- ui.input_text_area(
120
- "risks_blockers",
121
- "Known risks or blockers",
122
- placeholder="Example: Limited internal capacity, key person risk, uncertain budget, complex approvals...",
123
- rows=3,
124
- ),
125
- ui.input_text_area(
126
- "other_notes",
127
- "Anything else we should know?",
128
- placeholder="Free space for context, history, politics, or 'things that have been tried before'.",
129
- rows=3,
130
- ),
131
- ),
132
- ),
133
 
134
- ui.hr(),
135
- ui.input_action_button("submit", "Submit intake", class_="btn-primary"),
136
-
137
- ui.hr(),
138
- ui.layout_columns(
139
- ui.card(
140
- ui.card_header("Intake summary (human-readable)"),
141
- ui.output_text_verbatim("intake_summary"),
142
- ),
143
- ui.card(
144
- ui.card_header("Raw payload (for systems)"),
145
- ui.output_text_verbatim("intake_payload"),
146
- ),
147
- ),
148
- )
149
 
150
  # -----------------------------
151
- # Server
152
  # -----------------------------
153
 
 
 
 
 
 
154
 
155
- def server(input, output, session):
156
- # Build a structured dict from the current inputs
157
- def build_payload():
158
- return {
159
- "submitted_at": dt.datetime.now().isoformat(timespec="seconds"),
160
- "company": {
161
- "name": input.company_name(),
162
- "contact_name": input.contact_name(),
163
- "contact_role": input.contact_role(),
164
- "contact_email": input.contact_email(),
165
- "contact_phone": input.contact_phone(),
166
- },
167
- "project": {
168
- "trigger": input.project_trigger(),
169
- "primary_outcomes": input.primary_outcomes(),
170
- },
171
- "environment": {
172
- "current_tools": input.current_tools(),
173
- "data_sources": input.data_sources(),
174
- },
175
- "scope": {
176
- "areas_of_interest": input.areas_of_interest(),
177
- "change_profile": input.change_profile(),
178
- "team_size": input.team_size(),
179
- "timeline": input.timeline(),
180
- },
181
- "risks_and_notes": {
182
- "risks_blockers": input.risks_blockers(),
183
- "other_notes": input.other_notes(),
184
- },
185
- }
186
-
187
- # Reactive value that updates only when "Submit intake" is clicked
188
- @reactive.calc
189
- def submitted_payload():
190
- # Wait for the button click event
191
- input.submit()
192
- return build_payload()
193
-
194
- @output
195
- @render.text
196
- def intake_summary():
197
- d = submitted_payload()
198
-
199
- company = d["company"]
200
- project = d["project"]
201
- env = d["environment"]
202
- scope = d["scope"]
203
- risks = d["risks_and_notes"]
204
-
205
- areas = scope["areas_of_interest"] or []
206
- areas_str = ", ".join(areas) if areas else "Not specified"
207
-
208
- lines = [
209
- f"Submitted at: {d['submitted_at']}",
210
- "",
211
- f"Company: {company['name'] or 'Unknown'}",
212
- f"Contact: {company['contact_name'] or 'Unknown'} "
213
- f"({company['contact_role'] or 'role not specified'})",
214
- f"Email: {company['contact_email'] or 'not provided'}",
215
- f"Phone: {company['contact_phone'] or 'not provided'}",
216
- "",
217
- "Why now:",
218
- project["trigger"] or "(no description provided)",
219
- "",
220
- "Primary outcomes:",
221
- project["primary_outcomes"] or "(no outcomes described yet)",
222
- "",
223
- "Current tools / systems:",
224
- env["current_tools"] or "(not listed)",
225
- "",
226
- "Key data sources:",
227
- env["data_sources"] or "(not listed)",
228
- "",
229
- "Scope snapshot:",
230
- f" Areas of interest: {areas_str}",
231
- f" Change profile: {scope['change_profile'] or 'Not specified'}",
232
- f" Team size affected: {scope['team_size'] or 'Not specified'}",
233
- f" Timeline: {scope['timeline'] or 'Not specified'}",
234
- "",
235
- "Risks / blockers:",
236
- risks["risks_blockers"] or "(none listed)",
237
- "",
238
- "Other notes:",
239
- risks["other_notes"] or "(none)",
240
- ]
241
-
242
- return "\n".join(lines)
243
-
244
- @output
245
- @render.text
246
- def intake_payload():
247
- d = submitted_payload()
248
- return json.dumps(d, indent=2)
249
 
 
 
 
 
250
 
251
- app = App(app_ui, server)
 
1
+ from fastapi import FastAPI
2
+ from fastapi.responses import HTMLResponse, JSONResponse
3
+ from pydantic import BaseModel
4
+ from typing import Dict
5
+ import time
6
+
7
+ app = FastAPI(title="Tessai LLM Bridge", version="0.1.0")
8
 
9
  # -----------------------------
10
+ # Models
11
  # -----------------------------
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
+ class ChatRequest(BaseModel):
15
+ session_id: str
16
+ message: str
17
+ context: Dict[str, str] | None = None
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ class ChatResponse(BaseModel):
21
+ session_id: str
22
+ reply: str
23
+ tokens_used: int
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  # -----------------------------
27
+ # Simple in-memory metrics
28
  # -----------------------------
29
 
30
+ metrics = {
31
+ "total_requests": 0,
32
+ "total_tokens": 0,
33
+ "sessions": {} # session_id -> {"last_seen": float, "requests": int, "tokens": int}
34
+ }
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
+ def record_request(session_id: str, tokens_used: int) -> None:
38
+ now = time.time()
39
+ metrics["total_requests"] += 1
40
+ metrics["total_tokens"] += tokens_used
41
 
42
+ if session_id not in metr_