spagestic commited on
Commit
dbdb569
·
1 Parent(s): 4c5a050

Profile-based chat titles are implemented

Browse files
Files changed (4) hide show
  1. app.py +1 -1
  2. assets/app.js +13 -2
  3. ui/intake/prompts.py +43 -0
  4. ui/server_api.py +16 -3
app.py CHANGED
@@ -84,7 +84,7 @@ def api_build_research_prompt(
84
  family: server_api.DropdownValue,
85
  timeline: server_api.DropdownValue,
86
  goals: str,
87
- ) -> str:
88
  return server_api.build_research_prompt(
89
  current_country,
90
  residence_status,
 
84
  family: server_api.DropdownValue,
85
  timeline: server_api.DropdownValue,
86
  goals: str,
87
+ ) -> dict[str, str]:
88
  return server_api.build_research_prompt(
89
  current_country,
90
  residence_status,
assets/app.js CHANGED
@@ -33,6 +33,7 @@ const state = {
33
  busy: false,
34
  view: "form",
35
  activeResearchTaskId: null,
 
36
  };
37
 
38
  const els = {
@@ -189,7 +190,7 @@ function persistActiveSession() {
189
  const existing = index >= 0 ? sessions[index] : null;
190
  const title = existing?.titleManuallySet
191
  ? existing.title
192
- : sessionTitle(state.history);
193
 
194
  const payload = {
195
  id: state.sessionId,
@@ -244,6 +245,7 @@ function deleteSession(sessionId) {
244
  state.sessionId = crypto.randomUUID();
245
  state.history = [];
246
  state.globeState = emptyGlobeState();
 
247
  resetForm();
248
  els.chatInput.value = "";
249
  renderMessages();
@@ -391,6 +393,7 @@ function loadSession(sessionId) {
391
  state.sessionId = session.id;
392
  state.history = session.history || [];
393
  state.globeState = session.globeState || emptyGlobeState();
 
394
  els.chatInput.value = "";
395
  renderMessages();
396
  applyGlobeState(state.globeState);
@@ -406,6 +409,7 @@ function startNewChat() {
406
  state.sessionId = crypto.randomUUID();
407
  state.history = [];
408
  state.globeState = emptyGlobeState();
 
409
  resetForm();
410
  els.chatInput.value = "";
411
  renderMessages();
@@ -888,7 +892,14 @@ async function submitForm(event) {
888
  setStatus("Building research prompt...");
889
  try {
890
  const result = await gradioPredict("/build_research_prompt", formPayload());
891
- const message = unwrapResult(result) || "";
 
 
 
 
 
 
 
892
  if (!message) {
893
  setStatus("Could not build prompt.");
894
  return;
 
33
  busy: false,
34
  view: "form",
35
  activeResearchTaskId: null,
36
+ sessionAutoTitle: null,
37
  };
38
 
39
  const els = {
 
190
  const existing = index >= 0 ? sessions[index] : null;
191
  const title = existing?.titleManuallySet
192
  ? existing.title
193
+ : existing?.title ?? state.sessionAutoTitle ?? sessionTitle(state.history);
194
 
195
  const payload = {
196
  id: state.sessionId,
 
245
  state.sessionId = crypto.randomUUID();
246
  state.history = [];
247
  state.globeState = emptyGlobeState();
248
+ state.sessionAutoTitle = null;
249
  resetForm();
250
  els.chatInput.value = "";
251
  renderMessages();
 
393
  state.sessionId = session.id;
394
  state.history = session.history || [];
395
  state.globeState = session.globeState || emptyGlobeState();
396
+ state.sessionAutoTitle = session.titleManuallySet ? null : session.title || null;
397
  els.chatInput.value = "";
398
  renderMessages();
399
  applyGlobeState(state.globeState);
 
409
  state.sessionId = crypto.randomUUID();
410
  state.history = [];
411
  state.globeState = emptyGlobeState();
412
+ state.sessionAutoTitle = null;
413
  resetForm();
414
  els.chatInput.value = "";
415
  renderMessages();
 
892
  setStatus("Building research prompt...");
893
  try {
894
  const result = await gradioPredict("/build_research_prompt", formPayload());
895
+ const payload = unwrapResult(result) || {};
896
+ const message =
897
+ typeof payload === "string" ? payload : String(payload.text || "");
898
+ const title =
899
+ typeof payload === "object" && payload !== null && !Array.isArray(payload)
900
+ ? String(payload.title || "")
901
+ : "";
902
+ state.sessionAutoTitle = title || null;
903
  if (!message) {
904
  setStatus("Could not build prompt.");
905
  return;
ui/intake/prompts.py CHANGED
@@ -107,5 +107,48 @@ def build_profile_prompt(
107
  )
108
 
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  def example_prompt(prompt: str) -> dict[str, object]:
111
  return _chatbox_value(prompt)
 
107
  )
108
 
109
 
110
+ def _truncate_title(title: str, max_length: int = 72) -> str:
111
+ if len(title) <= max_length:
112
+ return title
113
+ return f"{title[: max_length - 3]}..."
114
+
115
+
116
+ def build_session_title(
117
+ current_country: DropdownValue,
118
+ residence_status: DropdownValue,
119
+ education: DropdownValue,
120
+ occupation: DropdownValue,
121
+ experience: DropdownValue,
122
+ budget: DropdownValue,
123
+ family: DropdownValue,
124
+ timeline: DropdownValue,
125
+ goals: str,
126
+ ) -> str:
127
+ del residence_status, experience, budget, family # unused for title
128
+
129
+ parts = [
130
+ part
131
+ for part in (
132
+ _format_value(occupation),
133
+ _format_value(current_country),
134
+ _format_value(timeline),
135
+ )
136
+ if part
137
+ ]
138
+ if not parts:
139
+ education_text = _format_value(education)
140
+ if education_text:
141
+ parts.append(education_text)
142
+
143
+ if parts:
144
+ return _truncate_title(" · ".join(parts))
145
+
146
+ goals_text = " ".join((goals or "").split())
147
+ if goals_text:
148
+ return _truncate_title(goals_text)
149
+
150
+ return "Untitled chat"
151
+
152
+
153
  def example_prompt(prompt: str) -> dict[str, object]:
154
  return _chatbox_value(prompt)
ui/server_api.py CHANGED
@@ -23,7 +23,7 @@ from ui.intake.choices import (
23
  country_choices,
24
  )
25
  from ui.intake.examples import demo_personas, persona_prompt
26
- from ui.intake.prompts import build_profile_prompt
27
 
28
  DropdownValue = str | int | float | list[str | int | float] | None
29
 
@@ -70,7 +70,7 @@ def build_research_prompt(
70
  family: DropdownValue,
71
  timeline: DropdownValue,
72
  goals: str,
73
- ) -> str:
74
  prompt = build_profile_prompt(
75
  None,
76
  current_country,
@@ -84,7 +84,20 @@ def build_research_prompt(
84
  timeline,
85
  goals,
86
  )
87
- return str(prompt.get("text") or "")
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
 
90
  def build_persona_prompt(persona_id: str) -> str:
 
23
  country_choices,
24
  )
25
  from ui.intake.examples import demo_personas, persona_prompt
26
+ from ui.intake.prompts import build_profile_prompt, build_session_title
27
 
28
  DropdownValue = str | int | float | list[str | int | float] | None
29
 
 
70
  family: DropdownValue,
71
  timeline: DropdownValue,
72
  goals: str,
73
+ ) -> dict[str, str]:
74
  prompt = build_profile_prompt(
75
  None,
76
  current_country,
 
84
  timeline,
85
  goals,
86
  )
87
+ return {
88
+ "text": str(prompt.get("text") or ""),
89
+ "title": build_session_title(
90
+ current_country,
91
+ residence_status,
92
+ education,
93
+ occupation,
94
+ experience,
95
+ budget,
96
+ family,
97
+ timeline,
98
+ goals,
99
+ ),
100
+ }
101
 
102
 
103
  def build_persona_prompt(persona_id: str) -> str: