spagestic commited on
Commit
35d176d
·
1 Parent(s): 425ab31

Implement new chat interface for immigration research, including user profile input and example prompts. Introduce a dedicated prompts module for system instructions, enhancing clarity and functionality.

Browse files
Files changed (2) hide show
  1. ui/chat.py +173 -34
  2. ui/inference/prompts.py +69 -0
ui/chat.py CHANGED
@@ -1,42 +1,171 @@
1
  # ui/chat.py
 
 
2
  import gradio as gr
3
 
4
  from ui.globe import render_globe_panel
5
  from ui.globe_commands import empty_globe_state
6
  from ui.inference import respond
 
 
 
 
 
7
 
8
- ADDITIONAL_INPUTS = [
9
- gr.Textbox(
10
- value=(
11
- "You are Borderless, an immigration research assistant with access to "
12
- "web search, page scraping, and an interactive 3D globe. Use "
13
- "search_immigration_info as your primary discovery tool for visa rules, "
14
- "pathways, documents, fees, processing times, and economic context — "
15
- "then scrape_web_page on the best official URLs for full content. Prefer "
16
- "official .gov, immigration authority, and embassy domains; use "
17
- "include_domains when you know the right government site. Use "
18
- "crawl_web_site only when multiple pages from the same official site "
19
- "are needed; prefer scrape_web_page when one page is enough. Cite source "
20
- "URLs when answering from search or scraped content. When you recommend "
21
- "or compare destination countries, call update_globe with action show so "
22
- "the user can see them on the globe. When the user asks to mark, map, "
23
- "show, highlight, or fly to countries, call update_globe immediately "
24
- "instead of describing the tool call."
25
- ),
26
- label="System message",
27
  ),
28
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
29
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
30
- gr.Slider(
31
- minimum=0.1,
32
- maximum=1.0,
33
- value=0.95,
34
- step=0.05,
35
- label="Top-p (nucleus sampling)",
36
  ),
37
  ]
38
 
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  class SidebarChatInterface(gr.ChatInterface):
41
  def __init__(
42
  self,
@@ -67,18 +196,28 @@ def create_chat_interface(
67
  For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
68
  """
69
  globe_state = gr.JSON(value=empty_globe_state(), visible=False, elem_id="globe-state")
 
 
 
 
 
 
 
 
 
70
 
71
  chat = SidebarChatInterface(
72
  respond,
73
  multimodal=True,
74
- textbox=gr.MultimodalTextbox(
75
- show_label=False,
76
- placeholder="Enter message or upload file...",
77
- file_count="multiple",
78
- sources=["upload"],
79
- ),
80
  history_container=history_container,
81
- additional_inputs=ADDITIONAL_INPUTS + [globe_state],
 
 
 
 
 
 
82
  additional_outputs=[globe_state],
83
  )
84
 
 
1
  # ui/chat.py
2
+ from __future__ import annotations
3
+
4
  import gradio as gr
5
 
6
  from ui.globe import render_globe_panel
7
  from ui.globe_commands import empty_globe_state
8
  from ui.inference import respond
9
+ from ui.inference.prompts import BORDERLESS_SYSTEM_PROMPT
10
+
11
+ DEFAULT_MAX_TOKENS = 1800
12
+ DEFAULT_TEMPERATURE = 0.35
13
+ DEFAULT_TOP_P = 0.9
14
 
15
+ EXAMPLE_PROMPTS = [
16
+ (
17
+ "India software engineer",
18
+ "I'm a software engineer from India with 5 years of backend experience, "
19
+ "a master's degree, English fluency, and a budget of about USD 18,000. "
20
+ "I want to relocate for work within the next 12-18 months. Which "
21
+ "countries are realistic, what visa pathways should I look at, and "
22
+ "what documents should I prepare?",
23
+ ),
24
+ (
25
+ "Hong Kong student",
26
+ "I hold a Hong Kong passport and want to study in Europe on a modest "
27
+ "budget. I speak English and conversational Mandarin, can show around "
28
+ "USD 12,000 in savings, and care about post-study work options. Compare "
29
+ "realistic countries and mark them on the globe.",
 
 
 
 
30
  ),
31
+ (
32
+ "Remote worker family",
33
+ "I'm a freelance product designer from Brazil, married with one child, "
34
+ "earning around USD 4,500 per month from overseas clients. We want a "
35
+ "safe country with good schools, a route that does not require a local "
36
+ "job offer immediately, and a timeline under one year.",
 
 
37
  ),
38
  ]
39
 
40
 
41
+ def _chatbox_value(text: str) -> dict[str, object]:
42
+ return {"text": text.strip(), "files": []}
43
+
44
+
45
+ def example_prompt(prompt: str) -> dict[str, object]:
46
+ return _chatbox_value(prompt)
47
+
48
+
49
+ def build_profile_prompt(
50
+ citizenship: str,
51
+ current_location: str,
52
+ education: str,
53
+ work_history: str,
54
+ languages: str,
55
+ budget: str,
56
+ family: str,
57
+ timeline: str,
58
+ goals: str,
59
+ ) -> dict[str, object]:
60
+ sections = [
61
+ ("Citizenship/passports", citizenship),
62
+ ("Current location", current_location),
63
+ ("Education", education),
64
+ ("Work history", work_history),
65
+ ("Languages", languages),
66
+ ("Budget and savings", budget),
67
+ ("Family/dependents", family),
68
+ ("Target timeline", timeline),
69
+ ("Goals and preferences", goals),
70
+ ]
71
+ details = "\n".join(
72
+ f"- {label}: {value.strip()}"
73
+ for label, value in sections
74
+ if value and value.strip()
75
+ )
76
+ if not details:
77
+ details = "- I have not filled in the profile yet. Ask me only for the missing details that matter most."
78
+
79
+ return _chatbox_value(
80
+ "Research realistic migration options for my profile.\n\n"
81
+ f"{details}\n\n"
82
+ "Please recommend 3-5 suitable countries, mark them on the globe, "
83
+ "compare visa pathways, required documents, approximate costs, "
84
+ "realistic timelines, risks, and official sources to verify."
85
+ )
86
+
87
+
88
+ def render_intake_panel(chat_input: gr.MultimodalTextbox) -> None:
89
+ with gr.Column(elem_classes=["borderless-intake"]):
90
+ gr.Markdown(
91
+ "## Borderless\n"
92
+ "Describe your background once. The agent researches official sources, "
93
+ "compares realistic visa pathways, and marks suitable countries on the globe.",
94
+ elem_classes=["borderless-hero"],
95
+ )
96
+ with gr.Accordion("Start with a guided profile", open=True):
97
+ with gr.Row():
98
+ citizenship = gr.Textbox(
99
+ label="Citizenship / passports",
100
+ placeholder="e.g. India; no second passport",
101
+ )
102
+ current_location = gr.Textbox(
103
+ label="Current location",
104
+ placeholder="e.g. Singapore on an employment pass",
105
+ )
106
+ with gr.Row():
107
+ education = gr.Textbox(
108
+ label="Education",
109
+ placeholder="e.g. Master's in computer science",
110
+ )
111
+ work_history = gr.Textbox(
112
+ label="Work history",
113
+ placeholder="e.g. 5 years as backend software engineer",
114
+ )
115
+ with gr.Row():
116
+ languages = gr.Textbox(
117
+ label="Languages",
118
+ placeholder="e.g. English C1, German A2",
119
+ )
120
+ budget = gr.Textbox(
121
+ label="Budget",
122
+ placeholder="e.g. USD 18,000 available for relocation",
123
+ )
124
+ with gr.Row():
125
+ family = gr.Textbox(
126
+ label="Family / dependents",
127
+ placeholder="e.g. spouse, one child, or solo applicant",
128
+ )
129
+ timeline = gr.Textbox(
130
+ label="Target timeline",
131
+ placeholder="e.g. 12-18 months",
132
+ )
133
+ goals = gr.Textbox(
134
+ label="Goals in everyday language",
135
+ lines=3,
136
+ placeholder=(
137
+ "e.g. I want a realistic skilled-worker route, lower risk, "
138
+ "and a path to permanent residence."
139
+ ),
140
+ )
141
+ gr.Button("Create research prompt", variant="primary").click(
142
+ fn=build_profile_prompt,
143
+ inputs=[
144
+ citizenship,
145
+ current_location,
146
+ education,
147
+ work_history,
148
+ languages,
149
+ budget,
150
+ family,
151
+ timeline,
152
+ goals,
153
+ ],
154
+ outputs=chat_input,
155
+ queue=False,
156
+ )
157
+
158
+ gr.Markdown("Try a demo persona:", elem_classes=["borderless-examples-title"])
159
+ with gr.Row():
160
+ for label, prompt in EXAMPLE_PROMPTS:
161
+ gr.Button(label, size="sm").click(
162
+ fn=example_prompt,
163
+ inputs=[gr.State(prompt)],
164
+ outputs=chat_input,
165
+ queue=False,
166
+ )
167
+
168
+
169
  class SidebarChatInterface(gr.ChatInterface):
170
  def __init__(
171
  self,
 
196
  For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
197
  """
198
  globe_state = gr.JSON(value=empty_globe_state(), visible=False, elem_id="globe-state")
199
+ chat_input = gr.MultimodalTextbox(
200
+ show_label=False,
201
+ placeholder="Ask a follow-up, or create a prompt from the guided profile above...",
202
+ file_count="multiple",
203
+ sources=["upload"],
204
+ render=False,
205
+ )
206
+
207
+ render_intake_panel(chat_input)
208
 
209
  chat = SidebarChatInterface(
210
  respond,
211
  multimodal=True,
212
+ textbox=chat_input,
 
 
 
 
 
213
  history_container=history_container,
214
+ additional_inputs=[
215
+ gr.State(BORDERLESS_SYSTEM_PROMPT),
216
+ gr.State(DEFAULT_MAX_TOKENS),
217
+ gr.State(DEFAULT_TEMPERATURE),
218
+ gr.State(DEFAULT_TOP_P),
219
+ globe_state,
220
+ ],
221
  additional_outputs=[globe_state],
222
  )
223
 
ui/inference/prompts.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """System prompts for Borderless immigration research sessions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ BORDERLESS_SYSTEM_PROMPT = """
6
+ You are Borderless, an agentic immigration research assistant with access to web
7
+ search, page scraping, country metadata, and an interactive 3D globe.
8
+
9
+ Your job is to help the user research realistic migration options. You are not
10
+ a lawyer and must not present the answer as legal advice. Be practical,
11
+ specific, and clear about uncertainty.
12
+
13
+ Research protocol:
14
+ 1. Parse the user's profile: citizenship, current location, education, work
15
+ history, languages, budget, timeline, family constraints, and goals.
16
+ 2. Identify 3-5 plausible destination countries. Prefer realistic fit over
17
+ popular destinations.
18
+ 3. Use get_country_profile for countries you plan to compare or mark on the
19
+ globe.
20
+ 4. Use search_immigration_info to discover current visa rules, documents, fees,
21
+ processing times, and official government pages. Prefer official immigration
22
+ authority, government, and embassy sources. Use include_domains when you know
23
+ the correct official domains.
24
+ 5. Use scrape_web_page on the best official URLs before making concrete claims
25
+ about eligibility, required documents, fees, processing times, or application
26
+ steps. Use crawl_web_site only when several pages from the same official site
27
+ are necessary.
28
+ 6. If you recommend or compare destination countries, call update_globe with
29
+ action "show". Pass ISO-2 country codes and concise marker labels such as
30
+ "Skilled worker - 6-12 mo" or "Study route - lower budget".
31
+ 7. If a tool fails, continue with a partial answer, explain what could not be
32
+ verified, and tell the user which official source to check next.
33
+
34
+ Source quality rules:
35
+ - Cite official source URLs for facts that affect eligibility, documents, fees,
36
+ timelines, or application steps.
37
+ - Treat law firm blogs, forums, and relocation sites as context only unless no
38
+ official source is available; label them as unofficial.
39
+ - Do not invent point scores, income thresholds, fees, or processing times.
40
+ If current official data is not found, say what is missing.
41
+
42
+ Final answer format:
43
+ Start with a short, plain-English recommendation. Then use these sections:
44
+
45
+ ## Snapshot
46
+ Summarize the user's profile and key constraints in 2-4 bullets.
47
+
48
+ ## Best-Fit Countries
49
+ Use a compact table with country, recommended pathway, why it fits, main risk,
50
+ and rough timeline.
51
+
52
+ ## Pathway Details
53
+ For each recommended country, list the visa pathway, eligibility notes,
54
+ required documents, approximate steps, timeline, and budget sensitivity.
55
+
56
+ ## Documents To Prepare
57
+ Group common documents first, then country-specific documents.
58
+
59
+ ## Risks And Tradeoffs
60
+ Mention language, job market, funds, age/points, credential recognition,
61
+ family constraints, and policy uncertainty where relevant.
62
+
63
+ ## Official Sources
64
+ List cited official URLs and what each source supports.
65
+
66
+ ## Next Steps
67
+ Give 3-5 concrete actions the user can take next. End by reminding them to
68
+ verify details on official sites or with a qualified immigration professional.
69
+ """.strip()