amd-gaia 0.15.0__py3-none-any.whl → 0.15.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.1.dist-info}/METADATA +223 -223
- amd_gaia-0.15.1.dist-info/RECORD +178 -0
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.1.dist-info}/entry_points.txt +1 -0
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.1.dist-info}/licenses/LICENSE.md +20 -20
- gaia/__init__.py +29 -29
- gaia/agents/__init__.py +19 -19
- gaia/agents/base/__init__.py +9 -9
- gaia/agents/base/agent.py +2177 -2177
- gaia/agents/base/api_agent.py +120 -120
- gaia/agents/base/console.py +1841 -1841
- gaia/agents/base/errors.py +237 -237
- gaia/agents/base/mcp_agent.py +86 -86
- gaia/agents/base/tools.py +83 -83
- gaia/agents/blender/agent.py +556 -556
- gaia/agents/blender/agent_simple.py +133 -135
- gaia/agents/blender/app.py +211 -211
- gaia/agents/blender/app_simple.py +41 -41
- gaia/agents/blender/core/__init__.py +16 -16
- gaia/agents/blender/core/materials.py +506 -506
- gaia/agents/blender/core/objects.py +316 -316
- gaia/agents/blender/core/rendering.py +225 -225
- gaia/agents/blender/core/scene.py +220 -220
- gaia/agents/blender/core/view.py +146 -146
- gaia/agents/chat/__init__.py +9 -9
- gaia/agents/chat/agent.py +835 -835
- gaia/agents/chat/app.py +1058 -1058
- gaia/agents/chat/session.py +508 -508
- gaia/agents/chat/tools/__init__.py +15 -15
- gaia/agents/chat/tools/file_tools.py +96 -96
- gaia/agents/chat/tools/rag_tools.py +1729 -1729
- gaia/agents/chat/tools/shell_tools.py +436 -436
- gaia/agents/code/__init__.py +7 -7
- gaia/agents/code/agent.py +549 -549
- gaia/agents/code/cli.py +377 -0
- gaia/agents/code/models.py +135 -135
- gaia/agents/code/orchestration/__init__.py +24 -24
- gaia/agents/code/orchestration/checklist_executor.py +1763 -1763
- gaia/agents/code/orchestration/checklist_generator.py +713 -713
- gaia/agents/code/orchestration/factories/__init__.py +9 -9
- gaia/agents/code/orchestration/factories/base.py +63 -63
- gaia/agents/code/orchestration/factories/nextjs_factory.py +118 -118
- gaia/agents/code/orchestration/factories/python_factory.py +106 -106
- gaia/agents/code/orchestration/orchestrator.py +841 -841
- gaia/agents/code/orchestration/project_analyzer.py +391 -391
- gaia/agents/code/orchestration/steps/__init__.py +67 -67
- gaia/agents/code/orchestration/steps/base.py +188 -188
- gaia/agents/code/orchestration/steps/error_handler.py +314 -314
- gaia/agents/code/orchestration/steps/nextjs.py +828 -828
- gaia/agents/code/orchestration/steps/python.py +307 -307
- gaia/agents/code/orchestration/template_catalog.py +469 -469
- gaia/agents/code/orchestration/workflows/__init__.py +14 -14
- gaia/agents/code/orchestration/workflows/base.py +80 -80
- gaia/agents/code/orchestration/workflows/nextjs.py +186 -186
- gaia/agents/code/orchestration/workflows/python.py +94 -94
- gaia/agents/code/prompts/__init__.py +11 -11
- gaia/agents/code/prompts/base_prompt.py +77 -77
- gaia/agents/code/prompts/code_patterns.py +2036 -2036
- gaia/agents/code/prompts/nextjs_prompt.py +40 -40
- gaia/agents/code/prompts/python_prompt.py +109 -109
- gaia/agents/code/schema_inference.py +365 -365
- gaia/agents/code/system_prompt.py +41 -41
- gaia/agents/code/tools/__init__.py +42 -42
- gaia/agents/code/tools/cli_tools.py +1138 -1138
- gaia/agents/code/tools/code_formatting.py +319 -319
- gaia/agents/code/tools/code_tools.py +769 -769
- gaia/agents/code/tools/error_fixing.py +1347 -1347
- gaia/agents/code/tools/external_tools.py +180 -180
- gaia/agents/code/tools/file_io.py +845 -845
- gaia/agents/code/tools/prisma_tools.py +190 -190
- gaia/agents/code/tools/project_management.py +1016 -1016
- gaia/agents/code/tools/testing.py +321 -321
- gaia/agents/code/tools/typescript_tools.py +122 -122
- gaia/agents/code/tools/validation_parsing.py +461 -461
- gaia/agents/code/tools/validation_tools.py +806 -806
- gaia/agents/code/tools/web_dev_tools.py +1758 -1758
- gaia/agents/code/validators/__init__.py +16 -16
- gaia/agents/code/validators/antipattern_checker.py +241 -241
- gaia/agents/code/validators/ast_analyzer.py +197 -197
- gaia/agents/code/validators/requirements_validator.py +145 -145
- gaia/agents/code/validators/syntax_validator.py +171 -171
- gaia/agents/docker/__init__.py +7 -7
- gaia/agents/docker/agent.py +642 -642
- gaia/agents/emr/__init__.py +8 -8
- gaia/agents/emr/agent.py +1506 -1506
- gaia/agents/emr/cli.py +1322 -1322
- gaia/agents/emr/constants.py +475 -475
- gaia/agents/emr/dashboard/__init__.py +4 -4
- gaia/agents/emr/dashboard/server.py +1974 -1974
- gaia/agents/jira/__init__.py +11 -11
- gaia/agents/jira/agent.py +894 -894
- gaia/agents/jira/jql_templates.py +299 -299
- gaia/agents/routing/__init__.py +7 -7
- gaia/agents/routing/agent.py +567 -570
- gaia/agents/routing/system_prompt.py +75 -75
- gaia/agents/summarize/__init__.py +11 -0
- gaia/agents/summarize/agent.py +885 -0
- gaia/agents/summarize/prompts.py +129 -0
- gaia/api/__init__.py +23 -23
- gaia/api/agent_registry.py +238 -238
- gaia/api/app.py +305 -305
- gaia/api/openai_server.py +575 -575
- gaia/api/schemas.py +186 -186
- gaia/api/sse_handler.py +373 -373
- gaia/apps/__init__.py +4 -4
- gaia/apps/llm/__init__.py +6 -6
- gaia/apps/llm/app.py +173 -169
- gaia/apps/summarize/app.py +116 -633
- gaia/apps/summarize/html_viewer.py +133 -133
- gaia/apps/summarize/pdf_formatter.py +284 -284
- gaia/audio/__init__.py +2 -2
- gaia/audio/audio_client.py +439 -439
- gaia/audio/audio_recorder.py +269 -269
- gaia/audio/kokoro_tts.py +599 -599
- gaia/audio/whisper_asr.py +432 -432
- gaia/chat/__init__.py +16 -16
- gaia/chat/app.py +430 -430
- gaia/chat/prompts.py +522 -522
- gaia/chat/sdk.py +1228 -1225
- gaia/cli.py +5481 -5632
- gaia/database/__init__.py +10 -10
- gaia/database/agent.py +176 -176
- gaia/database/mixin.py +290 -290
- gaia/database/testing.py +64 -64
- gaia/eval/batch_experiment.py +2332 -2332
- gaia/eval/claude.py +542 -542
- gaia/eval/config.py +37 -37
- gaia/eval/email_generator.py +512 -512
- gaia/eval/eval.py +3179 -3179
- gaia/eval/groundtruth.py +1130 -1130
- gaia/eval/transcript_generator.py +582 -582
- gaia/eval/webapp/README.md +167 -167
- gaia/eval/webapp/package-lock.json +875 -875
- gaia/eval/webapp/package.json +20 -20
- gaia/eval/webapp/public/app.js +3402 -3402
- gaia/eval/webapp/public/index.html +87 -87
- gaia/eval/webapp/public/styles.css +3661 -3661
- gaia/eval/webapp/server.js +415 -415
- gaia/eval/webapp/test-setup.js +72 -72
- gaia/llm/__init__.py +9 -2
- gaia/llm/base_client.py +60 -0
- gaia/llm/exceptions.py +12 -0
- gaia/llm/factory.py +70 -0
- gaia/llm/lemonade_client.py +3236 -3221
- gaia/llm/lemonade_manager.py +294 -294
- gaia/llm/providers/__init__.py +9 -0
- gaia/llm/providers/claude.py +108 -0
- gaia/llm/providers/lemonade.py +120 -0
- gaia/llm/providers/openai_provider.py +79 -0
- gaia/llm/vlm_client.py +382 -382
- gaia/logger.py +189 -189
- gaia/mcp/agent_mcp_server.py +245 -245
- gaia/mcp/blender_mcp_client.py +138 -138
- gaia/mcp/blender_mcp_server.py +648 -648
- gaia/mcp/context7_cache.py +332 -332
- gaia/mcp/external_services.py +518 -518
- gaia/mcp/mcp_bridge.py +811 -550
- gaia/mcp/servers/__init__.py +6 -6
- gaia/mcp/servers/docker_mcp.py +83 -83
- gaia/perf_analysis.py +361 -0
- gaia/rag/__init__.py +10 -10
- gaia/rag/app.py +293 -293
- gaia/rag/demo.py +304 -304
- gaia/rag/pdf_utils.py +235 -235
- gaia/rag/sdk.py +2194 -2194
- gaia/security.py +163 -163
- gaia/talk/app.py +289 -289
- gaia/talk/sdk.py +538 -538
- gaia/testing/__init__.py +87 -87
- gaia/testing/assertions.py +330 -330
- gaia/testing/fixtures.py +333 -333
- gaia/testing/mocks.py +493 -493
- gaia/util.py +46 -46
- gaia/utils/__init__.py +33 -33
- gaia/utils/file_watcher.py +675 -675
- gaia/utils/parsing.py +223 -223
- gaia/version.py +100 -100
- amd_gaia-0.15.0.dist-info/RECORD +0 -168
- gaia/agents/code/app.py +0 -266
- gaia/llm/llm_client.py +0 -723
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.1.dist-info}/WHEEL +0 -0
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.1.dist-info}/top_level.txt +0 -0
gaia/agents/emr/constants.py
CHANGED
|
@@ -1,475 +1,475 @@
|
|
|
1
|
-
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
-
# SPDX-License-Identifier: MIT
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
Constants and schemas for the Medical Intake Agent.
|
|
6
|
-
|
|
7
|
-
This module contains database schemas, VLM prompts, and manual entry
|
|
8
|
-
time estimation logic used by the Medical Intake Agent.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
# =============================================================================
|
|
12
|
-
# MANUAL DATA ENTRY TIME ESTIMATION
|
|
13
|
-
# =============================================================================
|
|
14
|
-
# Based on research: average data entry speed is 40 WPM (~200 CPM) but medical
|
|
15
|
-
# forms require looking back and forth, finding fields in UI, and verification.
|
|
16
|
-
#
|
|
17
|
-
# Formula per field: (BASE_TIME + chars * TYPING_TIME) * COMPLEXITY * (1 + VERIFICATION)
|
|
18
|
-
#
|
|
19
|
-
# Example calculation for a typical form with 15 fields, ~300 total characters:
|
|
20
|
-
# Base time: 15 fields * 10 sec = 150 sec
|
|
21
|
-
# Typing: 300 chars * 0.3 sec = 90 sec
|
|
22
|
-
# Subtotal: ~240 sec (4 min)
|
|
23
|
-
# With verification (+15%): ~276 sec (4.6 min)
|
|
24
|
-
#
|
|
25
|
-
# This aligns with studies showing manual EMR data entry takes 3-8 minutes
|
|
26
|
-
# per patient depending on form complexity.
|
|
27
|
-
|
|
28
|
-
TYPING_SECONDS_PER_CHAR = 0.3 # Slower than typical typing due to form lookup
|
|
29
|
-
BASE_SECONDS_PER_FIELD = 10 # Time to locate field, click, prepare to type
|
|
30
|
-
VERIFICATION_OVERHEAD = 0.15 # 15% extra time for checking/verification
|
|
31
|
-
|
|
32
|
-
# Field complexity multipliers (some fields take longer to enter)
|
|
33
|
-
FIELD_COMPLEXITY = {
|
|
34
|
-
# Simple fields - quick to enter
|
|
35
|
-
"first_name": 1.0,
|
|
36
|
-
"last_name": 1.0,
|
|
37
|
-
"gender": 0.5, # Usually a dropdown
|
|
38
|
-
"phone": 1.0,
|
|
39
|
-
"email": 1.0,
|
|
40
|
-
"state": 0.5, # Often a dropdown
|
|
41
|
-
"zip_code": 0.8,
|
|
42
|
-
# Medium complexity - require more attention
|
|
43
|
-
"date_of_birth": 1.2, # Date formatting
|
|
44
|
-
"address": 1.2,
|
|
45
|
-
"city": 1.0,
|
|
46
|
-
"insurance_provider": 1.2,
|
|
47
|
-
"insurance_id": 1.0,
|
|
48
|
-
"emergency_contact_name": 1.0,
|
|
49
|
-
"emergency_contact_phone": 1.0,
|
|
50
|
-
# Complex fields - may have multiple items, require careful reading
|
|
51
|
-
"reason_for_visit": 1.5,
|
|
52
|
-
"allergies": 1.8, # Critical field, needs careful entry
|
|
53
|
-
"medications": 1.8, # May have multiple items
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def estimate_manual_entry_time(extracted_data: dict) -> float:
|
|
58
|
-
"""
|
|
59
|
-
Estimate how long manual data entry would take for extracted form data.
|
|
60
|
-
|
|
61
|
-
The estimation is based on:
|
|
62
|
-
1. Number of fields extracted (base time per field)
|
|
63
|
-
2. Character count of each field (typing time)
|
|
64
|
-
3. Field complexity (some fields require more care)
|
|
65
|
-
4. Verification overhead (checking entries)
|
|
66
|
-
|
|
67
|
-
Args:
|
|
68
|
-
extracted_data: Dictionary of extracted patient data
|
|
69
|
-
|
|
70
|
-
Returns:
|
|
71
|
-
Estimated manual entry time in seconds
|
|
72
|
-
"""
|
|
73
|
-
total_seconds = 0.0
|
|
74
|
-
field_count = 0
|
|
75
|
-
|
|
76
|
-
# Fields to skip in estimation (metadata, not user-entered)
|
|
77
|
-
skip_fields = {
|
|
78
|
-
"source_file",
|
|
79
|
-
"raw_extraction",
|
|
80
|
-
"additional_fields",
|
|
81
|
-
"is_new_patient",
|
|
82
|
-
"processing_time_seconds",
|
|
83
|
-
"file_hash",
|
|
84
|
-
"file_content",
|
|
85
|
-
"estimated_manual_seconds",
|
|
86
|
-
"id",
|
|
87
|
-
"created_at",
|
|
88
|
-
"updated_at",
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
for field_name, value in extracted_data.items():
|
|
92
|
-
if value is None or value == "" or field_name in skip_fields:
|
|
93
|
-
continue
|
|
94
|
-
|
|
95
|
-
# Convert value to string for character counting
|
|
96
|
-
value_str = str(value)
|
|
97
|
-
char_count = len(value_str)
|
|
98
|
-
|
|
99
|
-
if char_count == 0:
|
|
100
|
-
continue
|
|
101
|
-
|
|
102
|
-
field_count += 1
|
|
103
|
-
|
|
104
|
-
# Get complexity multiplier (default 1.0 for unknown fields)
|
|
105
|
-
complexity = FIELD_COMPLEXITY.get(field_name, 1.0)
|
|
106
|
-
|
|
107
|
-
# Calculate time for this field
|
|
108
|
-
field_time = (
|
|
109
|
-
BASE_SECONDS_PER_FIELD # Base time to find and click field
|
|
110
|
-
+ (char_count * TYPING_SECONDS_PER_CHAR) # Typing time
|
|
111
|
-
) * complexity
|
|
112
|
-
|
|
113
|
-
total_seconds += field_time
|
|
114
|
-
|
|
115
|
-
# Add verification overhead (checking all entries)
|
|
116
|
-
total_seconds *= 1 + VERIFICATION_OVERHEAD
|
|
117
|
-
|
|
118
|
-
# Minimum time if we have any fields (at least 30 seconds)
|
|
119
|
-
if field_count > 0:
|
|
120
|
-
total_seconds = max(total_seconds, 30.0)
|
|
121
|
-
|
|
122
|
-
return round(total_seconds, 1)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
# =============================================================================
|
|
126
|
-
# DATABASE SCHEMA
|
|
127
|
-
# =============================================================================
|
|
128
|
-
|
|
129
|
-
PATIENT_SCHEMA = """
|
|
130
|
-
CREATE TABLE IF NOT EXISTS patients (
|
|
131
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
132
|
-
-- Patient info - basic
|
|
133
|
-
first_name TEXT,
|
|
134
|
-
last_name TEXT,
|
|
135
|
-
date_of_birth TEXT,
|
|
136
|
-
age TEXT,
|
|
137
|
-
gender TEXT,
|
|
138
|
-
preferred_pronouns TEXT,
|
|
139
|
-
ssn TEXT,
|
|
140
|
-
marital_status TEXT,
|
|
141
|
-
spouse_name TEXT,
|
|
142
|
-
-- Contact info
|
|
143
|
-
phone TEXT,
|
|
144
|
-
mobile_phone TEXT,
|
|
145
|
-
work_phone TEXT,
|
|
146
|
-
email TEXT,
|
|
147
|
-
address TEXT,
|
|
148
|
-
city TEXT,
|
|
149
|
-
state TEXT,
|
|
150
|
-
zip_code TEXT,
|
|
151
|
-
-- Demographics
|
|
152
|
-
preferred_language TEXT,
|
|
153
|
-
race TEXT,
|
|
154
|
-
ethnicity TEXT,
|
|
155
|
-
contact_preference TEXT,
|
|
156
|
-
-- Emergency contact
|
|
157
|
-
emergency_contact_name TEXT,
|
|
158
|
-
emergency_contact_relationship TEXT,
|
|
159
|
-
emergency_contact_phone TEXT,
|
|
160
|
-
-- Physicians
|
|
161
|
-
referring_physician TEXT,
|
|
162
|
-
referring_physician_phone TEXT,
|
|
163
|
-
primary_care_physician TEXT,
|
|
164
|
-
preferred_pharmacy TEXT,
|
|
165
|
-
-- Employment
|
|
166
|
-
employment_status TEXT,
|
|
167
|
-
occupation TEXT,
|
|
168
|
-
employer TEXT,
|
|
169
|
-
employer_address TEXT,
|
|
170
|
-
-- Primary insurance
|
|
171
|
-
insurance_provider TEXT,
|
|
172
|
-
insurance_id TEXT,
|
|
173
|
-
insurance_group_number TEXT,
|
|
174
|
-
insured_name TEXT,
|
|
175
|
-
insured_dob TEXT,
|
|
176
|
-
insurance_phone TEXT,
|
|
177
|
-
billing_address TEXT,
|
|
178
|
-
guarantor_name TEXT,
|
|
179
|
-
-- Secondary insurance
|
|
180
|
-
secondary_insurance_provider TEXT,
|
|
181
|
-
secondary_insurance_id TEXT,
|
|
182
|
-
-- Medical/Pain history
|
|
183
|
-
reason_for_visit TEXT,
|
|
184
|
-
date_of_injury TEXT,
|
|
185
|
-
pain_location TEXT,
|
|
186
|
-
pain_onset TEXT,
|
|
187
|
-
pain_cause TEXT,
|
|
188
|
-
pain_progression TEXT,
|
|
189
|
-
work_related_injury TEXT,
|
|
190
|
-
car_accident TEXT,
|
|
191
|
-
medical_conditions TEXT,
|
|
192
|
-
allergies TEXT,
|
|
193
|
-
medications TEXT,
|
|
194
|
-
-- Form metadata
|
|
195
|
-
form_date TEXT,
|
|
196
|
-
signature_date TEXT,
|
|
197
|
-
-- System fields
|
|
198
|
-
created_at TEXT DEFAULT (datetime('now')),
|
|
199
|
-
updated_at TEXT DEFAULT (datetime('now')),
|
|
200
|
-
source_file TEXT,
|
|
201
|
-
raw_extraction TEXT,
|
|
202
|
-
additional_fields TEXT,
|
|
203
|
-
is_new_patient BOOLEAN DEFAULT TRUE,
|
|
204
|
-
processing_time_seconds REAL,
|
|
205
|
-
estimated_manual_seconds REAL,
|
|
206
|
-
file_hash TEXT,
|
|
207
|
-
file_content BLOB
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
CREATE INDEX IF NOT EXISTS idx_patients_name ON patients(last_name, first_name);
|
|
211
|
-
CREATE INDEX IF NOT EXISTS idx_patients_dob ON patients(date_of_birth);
|
|
212
|
-
CREATE INDEX IF NOT EXISTS idx_patients_hash ON patients(file_hash);
|
|
213
|
-
|
|
214
|
-
-- Alerts table for tracking critical notifications
|
|
215
|
-
CREATE TABLE IF NOT EXISTS alerts (
|
|
216
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
217
|
-
patient_id INTEGER REFERENCES patients(id),
|
|
218
|
-
alert_type TEXT NOT NULL,
|
|
219
|
-
priority TEXT DEFAULT 'medium',
|
|
220
|
-
message TEXT NOT NULL,
|
|
221
|
-
data TEXT,
|
|
222
|
-
created_at TEXT DEFAULT (datetime('now')),
|
|
223
|
-
acknowledged BOOLEAN DEFAULT FALSE,
|
|
224
|
-
acknowledged_by TEXT,
|
|
225
|
-
acknowledged_at TEXT
|
|
226
|
-
);
|
|
227
|
-
|
|
228
|
-
CREATE INDEX IF NOT EXISTS idx_alerts_patient ON alerts(patient_id);
|
|
229
|
-
CREATE INDEX IF NOT EXISTS idx_alerts_acknowledged ON alerts(acknowledged);
|
|
230
|
-
|
|
231
|
-
-- Intake sessions for audit trail
|
|
232
|
-
CREATE TABLE IF NOT EXISTS intake_sessions (
|
|
233
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
234
|
-
patient_id INTEGER REFERENCES patients(id),
|
|
235
|
-
source_file TEXT,
|
|
236
|
-
processing_time_seconds REAL,
|
|
237
|
-
is_new_patient BOOLEAN,
|
|
238
|
-
changes_detected TEXT,
|
|
239
|
-
created_at TEXT DEFAULT (datetime('now'))
|
|
240
|
-
);
|
|
241
|
-
"""
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
# =============================================================================
|
|
245
|
-
# VLM EXTRACTION PROMPT
|
|
246
|
-
# =============================================================================
|
|
247
|
-
|
|
248
|
-
EXTRACTION_PROMPT = """You are a medical data extraction system. Extract ALL patient information from this intake form image.
|
|
249
|
-
|
|
250
|
-
Return a JSON object with ALL fields you can extract. Use these standard field names when applicable:
|
|
251
|
-
|
|
252
|
-
REQUIRED (always include):
|
|
253
|
-
- "first_name": patient's first name
|
|
254
|
-
- "last_name": patient's last name
|
|
255
|
-
|
|
256
|
-
PATIENT INFO:
|
|
257
|
-
- "form_date": date form was filled (YYYY-MM-DD)
|
|
258
|
-
- "date_of_birth": YYYY-MM-DD format
|
|
259
|
-
- "age": patient's age if listed
|
|
260
|
-
- "gender": Male/Female/Other
|
|
261
|
-
- "preferred_pronouns": he/him, she/her, they/them if listed
|
|
262
|
-
- "ssn": Social Security Number (XXX-XX-XXXX)
|
|
263
|
-
- "marital_status": Single/Married/Divorced/Widowed/Partnered
|
|
264
|
-
- "spouse_name": spouse's name if listed
|
|
265
|
-
- "phone": home phone number
|
|
266
|
-
- "mobile_phone": cell/mobile phone number
|
|
267
|
-
- "work_phone": work phone number
|
|
268
|
-
- "email"
|
|
269
|
-
- "address": street address
|
|
270
|
-
- "city", "state", "zip_code"
|
|
271
|
-
- "preferred_language": English/Spanish/etc if listed
|
|
272
|
-
- "race", "ethnicity": if listed
|
|
273
|
-
- "contact_preference": preferred contact method if listed
|
|
274
|
-
|
|
275
|
-
EMERGENCY CONTACT:
|
|
276
|
-
- "emergency_contact_name": name of emergency contact person
|
|
277
|
-
- "emergency_contact_relationship": relationship to patient (e.g. Mom, Spouse, Friend)
|
|
278
|
-
- "emergency_contact_phone": emergency contact's phone number
|
|
279
|
-
|
|
280
|
-
PHYSICIANS:
|
|
281
|
-
- "referring_physician": name of referring physician/doctor
|
|
282
|
-
- "referring_physician_phone": phone number next to referring physician
|
|
283
|
-
- "primary_care_physician": PCP name if different from referring
|
|
284
|
-
- "preferred_pharmacy": pharmacy name if listed
|
|
285
|
-
|
|
286
|
-
EMPLOYMENT:
|
|
287
|
-
- "employment_status": Employed/Self Employed/Unemployed/Retired/Student/Disabled/Military
|
|
288
|
-
- "occupation": job title if listed
|
|
289
|
-
- "employer": employer/company name
|
|
290
|
-
- "employer_address": employer address if listed
|
|
291
|
-
|
|
292
|
-
PRIMARY INSURANCE:
|
|
293
|
-
- "insurance_provider": insurance company name
|
|
294
|
-
- "insurance_id": policy number
|
|
295
|
-
- "insurance_group_number": group number
|
|
296
|
-
- "insured_name": name of insured person (may differ from patient)
|
|
297
|
-
- "insured_dob": DOB of insured (YYYY-MM-DD)
|
|
298
|
-
- "insurance_phone": insurance contact number
|
|
299
|
-
- "billing_address": billing address if different from home
|
|
300
|
-
- "guarantor_name": person responsible for payment if listed
|
|
301
|
-
|
|
302
|
-
SECONDARY INSURANCE:
|
|
303
|
-
- "secondary_insurance_provider", "secondary_insurance_id"
|
|
304
|
-
|
|
305
|
-
MEDICAL/PAIN HISTORY:
|
|
306
|
-
- "reason_for_visit": chief complaint or reason for visit
|
|
307
|
-
- "date_of_injury": date of injury or onset of symptoms (YYYY-MM-DD)
|
|
308
|
-
- "pain_location": where pain is located if listed
|
|
309
|
-
- "pain_onset": when pain began (e.g. three months ago)
|
|
310
|
-
- "pain_cause": what caused the pain/condition
|
|
311
|
-
- "pain_progression": Improved/Worsened/Stayed the same
|
|
312
|
-
- "work_related_injury": Yes/No
|
|
313
|
-
- "car_accident": Yes/No
|
|
314
|
-
- "medical_conditions": existing medical conditions
|
|
315
|
-
- "allergies": known allergies
|
|
316
|
-
- "medications": current medications
|
|
317
|
-
|
|
318
|
-
SIGNATURE:
|
|
319
|
-
- "signature_date": date signed (YYYY-MM-DD)
|
|
320
|
-
|
|
321
|
-
ADDITIONAL FIELDS:
|
|
322
|
-
Extract ANY other fields visible on the form using descriptive snake_case names.
|
|
323
|
-
|
|
324
|
-
IMPORTANT:
|
|
325
|
-
- Extract EVERY field visible on the form
|
|
326
|
-
- Use null for fields that exist but are blank
|
|
327
|
-
- Omit fields not present on this specific form
|
|
328
|
-
- Return ONLY the JSON object, no other text
|
|
329
|
-
- Dates must be in YYYY-MM-DD format
|
|
330
|
-
- For checkboxes, use Yes/No values"""
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
# Standard columns that map to database schema
|
|
334
|
-
STANDARD_COLUMNS = [
|
|
335
|
-
# Patient info - basic
|
|
336
|
-
"first_name",
|
|
337
|
-
"last_name",
|
|
338
|
-
"date_of_birth",
|
|
339
|
-
"age",
|
|
340
|
-
"gender",
|
|
341
|
-
"preferred_pronouns",
|
|
342
|
-
"ssn",
|
|
343
|
-
"marital_status",
|
|
344
|
-
"spouse_name",
|
|
345
|
-
# Contact info
|
|
346
|
-
"phone", # home phone
|
|
347
|
-
"mobile_phone", # cell phone
|
|
348
|
-
"work_phone",
|
|
349
|
-
"email",
|
|
350
|
-
"address",
|
|
351
|
-
"city",
|
|
352
|
-
"state",
|
|
353
|
-
"zip_code",
|
|
354
|
-
# Demographics
|
|
355
|
-
"preferred_language",
|
|
356
|
-
"race",
|
|
357
|
-
"ethnicity",
|
|
358
|
-
"contact_preference",
|
|
359
|
-
# Emergency contact
|
|
360
|
-
"emergency_contact_name",
|
|
361
|
-
"emergency_contact_relationship",
|
|
362
|
-
"emergency_contact_phone",
|
|
363
|
-
# Physicians
|
|
364
|
-
"referring_physician",
|
|
365
|
-
"referring_physician_phone",
|
|
366
|
-
"primary_care_physician",
|
|
367
|
-
"preferred_pharmacy",
|
|
368
|
-
# Employment
|
|
369
|
-
"employment_status",
|
|
370
|
-
"occupation",
|
|
371
|
-
"employer",
|
|
372
|
-
"employer_address",
|
|
373
|
-
# Primary insurance
|
|
374
|
-
"insurance_provider",
|
|
375
|
-
"insurance_id",
|
|
376
|
-
"insurance_group_number",
|
|
377
|
-
"insured_name",
|
|
378
|
-
"insured_dob",
|
|
379
|
-
"insurance_phone",
|
|
380
|
-
"billing_address",
|
|
381
|
-
"guarantor_name",
|
|
382
|
-
# Secondary insurance
|
|
383
|
-
"secondary_insurance_provider",
|
|
384
|
-
"secondary_insurance_id",
|
|
385
|
-
# Medical/Pain history
|
|
386
|
-
"reason_for_visit",
|
|
387
|
-
"date_of_injury",
|
|
388
|
-
"pain_location",
|
|
389
|
-
"pain_onset",
|
|
390
|
-
"pain_cause",
|
|
391
|
-
"pain_progression",
|
|
392
|
-
"work_related_injury",
|
|
393
|
-
"car_accident",
|
|
394
|
-
"medical_conditions",
|
|
395
|
-
"allergies",
|
|
396
|
-
"medications",
|
|
397
|
-
# Form metadata
|
|
398
|
-
"form_date",
|
|
399
|
-
"signature_date",
|
|
400
|
-
# System fields
|
|
401
|
-
"source_file",
|
|
402
|
-
"raw_extraction",
|
|
403
|
-
"additional_fields",
|
|
404
|
-
"is_new_patient",
|
|
405
|
-
"processing_time_seconds",
|
|
406
|
-
"estimated_manual_seconds",
|
|
407
|
-
"file_hash",
|
|
408
|
-
"file_content",
|
|
409
|
-
]
|
|
410
|
-
|
|
411
|
-
# Columns that can be updated for returning patients
|
|
412
|
-
UPDATABLE_COLUMNS = [
|
|
413
|
-
# Contact info (can change)
|
|
414
|
-
"phone", # home phone
|
|
415
|
-
"mobile_phone", # cell phone
|
|
416
|
-
"work_phone",
|
|
417
|
-
"email",
|
|
418
|
-
"address",
|
|
419
|
-
"city",
|
|
420
|
-
"state",
|
|
421
|
-
"zip_code",
|
|
422
|
-
"contact_preference",
|
|
423
|
-
# Marital status (can change)
|
|
424
|
-
"marital_status",
|
|
425
|
-
"spouse_name",
|
|
426
|
-
# Emergency contact (can change)
|
|
427
|
-
"emergency_contact_name",
|
|
428
|
-
"emergency_contact_relationship",
|
|
429
|
-
"emergency_contact_phone",
|
|
430
|
-
# Physicians (can change)
|
|
431
|
-
"referring_physician",
|
|
432
|
-
"referring_physician_phone",
|
|
433
|
-
"primary_care_physician",
|
|
434
|
-
"preferred_pharmacy",
|
|
435
|
-
# Employment (can change)
|
|
436
|
-
"employment_status",
|
|
437
|
-
"occupation",
|
|
438
|
-
"employer",
|
|
439
|
-
"employer_address",
|
|
440
|
-
# Insurance (can change)
|
|
441
|
-
"insurance_provider",
|
|
442
|
-
"insurance_id",
|
|
443
|
-
"insurance_group_number",
|
|
444
|
-
"insured_name",
|
|
445
|
-
"insured_dob",
|
|
446
|
-
"insurance_phone",
|
|
447
|
-
"billing_address",
|
|
448
|
-
"guarantor_name",
|
|
449
|
-
"secondary_insurance_provider",
|
|
450
|
-
"secondary_insurance_id",
|
|
451
|
-
# Medical/Pain (can change each visit)
|
|
452
|
-
"reason_for_visit",
|
|
453
|
-
"date_of_injury",
|
|
454
|
-
"pain_location",
|
|
455
|
-
"pain_onset",
|
|
456
|
-
"pain_cause",
|
|
457
|
-
"pain_progression",
|
|
458
|
-
"work_related_injury",
|
|
459
|
-
"car_accident",
|
|
460
|
-
"medical_conditions",
|
|
461
|
-
"allergies",
|
|
462
|
-
"medications",
|
|
463
|
-
# Form metadata
|
|
464
|
-
"form_date",
|
|
465
|
-
"signature_date",
|
|
466
|
-
# System fields
|
|
467
|
-
"source_file",
|
|
468
|
-
"raw_extraction",
|
|
469
|
-
"additional_fields",
|
|
470
|
-
"is_new_patient",
|
|
471
|
-
"processing_time_seconds",
|
|
472
|
-
"estimated_manual_seconds",
|
|
473
|
-
"file_hash",
|
|
474
|
-
"file_content",
|
|
475
|
-
]
|
|
1
|
+
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Constants and schemas for the Medical Intake Agent.
|
|
6
|
+
|
|
7
|
+
This module contains database schemas, VLM prompts, and manual entry
|
|
8
|
+
time estimation logic used by the Medical Intake Agent.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# =============================================================================
|
|
12
|
+
# MANUAL DATA ENTRY TIME ESTIMATION
|
|
13
|
+
# =============================================================================
|
|
14
|
+
# Based on research: average data entry speed is 40 WPM (~200 CPM) but medical
|
|
15
|
+
# forms require looking back and forth, finding fields in UI, and verification.
|
|
16
|
+
#
|
|
17
|
+
# Formula per field: (BASE_TIME + chars * TYPING_TIME) * COMPLEXITY * (1 + VERIFICATION)
|
|
18
|
+
#
|
|
19
|
+
# Example calculation for a typical form with 15 fields, ~300 total characters:
|
|
20
|
+
# Base time: 15 fields * 10 sec = 150 sec
|
|
21
|
+
# Typing: 300 chars * 0.3 sec = 90 sec
|
|
22
|
+
# Subtotal: ~240 sec (4 min)
|
|
23
|
+
# With verification (+15%): ~276 sec (4.6 min)
|
|
24
|
+
#
|
|
25
|
+
# This aligns with studies showing manual EMR data entry takes 3-8 minutes
|
|
26
|
+
# per patient depending on form complexity.
|
|
27
|
+
|
|
28
|
+
TYPING_SECONDS_PER_CHAR = 0.3 # Slower than typical typing due to form lookup
|
|
29
|
+
BASE_SECONDS_PER_FIELD = 10 # Time to locate field, click, prepare to type
|
|
30
|
+
VERIFICATION_OVERHEAD = 0.15 # 15% extra time for checking/verification
|
|
31
|
+
|
|
32
|
+
# Field complexity multipliers (some fields take longer to enter)
|
|
33
|
+
FIELD_COMPLEXITY = {
|
|
34
|
+
# Simple fields - quick to enter
|
|
35
|
+
"first_name": 1.0,
|
|
36
|
+
"last_name": 1.0,
|
|
37
|
+
"gender": 0.5, # Usually a dropdown
|
|
38
|
+
"phone": 1.0,
|
|
39
|
+
"email": 1.0,
|
|
40
|
+
"state": 0.5, # Often a dropdown
|
|
41
|
+
"zip_code": 0.8,
|
|
42
|
+
# Medium complexity - require more attention
|
|
43
|
+
"date_of_birth": 1.2, # Date formatting
|
|
44
|
+
"address": 1.2,
|
|
45
|
+
"city": 1.0,
|
|
46
|
+
"insurance_provider": 1.2,
|
|
47
|
+
"insurance_id": 1.0,
|
|
48
|
+
"emergency_contact_name": 1.0,
|
|
49
|
+
"emergency_contact_phone": 1.0,
|
|
50
|
+
# Complex fields - may have multiple items, require careful reading
|
|
51
|
+
"reason_for_visit": 1.5,
|
|
52
|
+
"allergies": 1.8, # Critical field, needs careful entry
|
|
53
|
+
"medications": 1.8, # May have multiple items
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def estimate_manual_entry_time(extracted_data: dict) -> float:
|
|
58
|
+
"""
|
|
59
|
+
Estimate how long manual data entry would take for extracted form data.
|
|
60
|
+
|
|
61
|
+
The estimation is based on:
|
|
62
|
+
1. Number of fields extracted (base time per field)
|
|
63
|
+
2. Character count of each field (typing time)
|
|
64
|
+
3. Field complexity (some fields require more care)
|
|
65
|
+
4. Verification overhead (checking entries)
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
extracted_data: Dictionary of extracted patient data
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Estimated manual entry time in seconds
|
|
72
|
+
"""
|
|
73
|
+
total_seconds = 0.0
|
|
74
|
+
field_count = 0
|
|
75
|
+
|
|
76
|
+
# Fields to skip in estimation (metadata, not user-entered)
|
|
77
|
+
skip_fields = {
|
|
78
|
+
"source_file",
|
|
79
|
+
"raw_extraction",
|
|
80
|
+
"additional_fields",
|
|
81
|
+
"is_new_patient",
|
|
82
|
+
"processing_time_seconds",
|
|
83
|
+
"file_hash",
|
|
84
|
+
"file_content",
|
|
85
|
+
"estimated_manual_seconds",
|
|
86
|
+
"id",
|
|
87
|
+
"created_at",
|
|
88
|
+
"updated_at",
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
for field_name, value in extracted_data.items():
|
|
92
|
+
if value is None or value == "" or field_name in skip_fields:
|
|
93
|
+
continue
|
|
94
|
+
|
|
95
|
+
# Convert value to string for character counting
|
|
96
|
+
value_str = str(value)
|
|
97
|
+
char_count = len(value_str)
|
|
98
|
+
|
|
99
|
+
if char_count == 0:
|
|
100
|
+
continue
|
|
101
|
+
|
|
102
|
+
field_count += 1
|
|
103
|
+
|
|
104
|
+
# Get complexity multiplier (default 1.0 for unknown fields)
|
|
105
|
+
complexity = FIELD_COMPLEXITY.get(field_name, 1.0)
|
|
106
|
+
|
|
107
|
+
# Calculate time for this field
|
|
108
|
+
field_time = (
|
|
109
|
+
BASE_SECONDS_PER_FIELD # Base time to find and click field
|
|
110
|
+
+ (char_count * TYPING_SECONDS_PER_CHAR) # Typing time
|
|
111
|
+
) * complexity
|
|
112
|
+
|
|
113
|
+
total_seconds += field_time
|
|
114
|
+
|
|
115
|
+
# Add verification overhead (checking all entries)
|
|
116
|
+
total_seconds *= 1 + VERIFICATION_OVERHEAD
|
|
117
|
+
|
|
118
|
+
# Minimum time if we have any fields (at least 30 seconds)
|
|
119
|
+
if field_count > 0:
|
|
120
|
+
total_seconds = max(total_seconds, 30.0)
|
|
121
|
+
|
|
122
|
+
return round(total_seconds, 1)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
# =============================================================================
|
|
126
|
+
# DATABASE SCHEMA
|
|
127
|
+
# =============================================================================
|
|
128
|
+
|
|
129
|
+
PATIENT_SCHEMA = """
|
|
130
|
+
CREATE TABLE IF NOT EXISTS patients (
|
|
131
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
132
|
+
-- Patient info - basic
|
|
133
|
+
first_name TEXT,
|
|
134
|
+
last_name TEXT,
|
|
135
|
+
date_of_birth TEXT,
|
|
136
|
+
age TEXT,
|
|
137
|
+
gender TEXT,
|
|
138
|
+
preferred_pronouns TEXT,
|
|
139
|
+
ssn TEXT,
|
|
140
|
+
marital_status TEXT,
|
|
141
|
+
spouse_name TEXT,
|
|
142
|
+
-- Contact info
|
|
143
|
+
phone TEXT,
|
|
144
|
+
mobile_phone TEXT,
|
|
145
|
+
work_phone TEXT,
|
|
146
|
+
email TEXT,
|
|
147
|
+
address TEXT,
|
|
148
|
+
city TEXT,
|
|
149
|
+
state TEXT,
|
|
150
|
+
zip_code TEXT,
|
|
151
|
+
-- Demographics
|
|
152
|
+
preferred_language TEXT,
|
|
153
|
+
race TEXT,
|
|
154
|
+
ethnicity TEXT,
|
|
155
|
+
contact_preference TEXT,
|
|
156
|
+
-- Emergency contact
|
|
157
|
+
emergency_contact_name TEXT,
|
|
158
|
+
emergency_contact_relationship TEXT,
|
|
159
|
+
emergency_contact_phone TEXT,
|
|
160
|
+
-- Physicians
|
|
161
|
+
referring_physician TEXT,
|
|
162
|
+
referring_physician_phone TEXT,
|
|
163
|
+
primary_care_physician TEXT,
|
|
164
|
+
preferred_pharmacy TEXT,
|
|
165
|
+
-- Employment
|
|
166
|
+
employment_status TEXT,
|
|
167
|
+
occupation TEXT,
|
|
168
|
+
employer TEXT,
|
|
169
|
+
employer_address TEXT,
|
|
170
|
+
-- Primary insurance
|
|
171
|
+
insurance_provider TEXT,
|
|
172
|
+
insurance_id TEXT,
|
|
173
|
+
insurance_group_number TEXT,
|
|
174
|
+
insured_name TEXT,
|
|
175
|
+
insured_dob TEXT,
|
|
176
|
+
insurance_phone TEXT,
|
|
177
|
+
billing_address TEXT,
|
|
178
|
+
guarantor_name TEXT,
|
|
179
|
+
-- Secondary insurance
|
|
180
|
+
secondary_insurance_provider TEXT,
|
|
181
|
+
secondary_insurance_id TEXT,
|
|
182
|
+
-- Medical/Pain history
|
|
183
|
+
reason_for_visit TEXT,
|
|
184
|
+
date_of_injury TEXT,
|
|
185
|
+
pain_location TEXT,
|
|
186
|
+
pain_onset TEXT,
|
|
187
|
+
pain_cause TEXT,
|
|
188
|
+
pain_progression TEXT,
|
|
189
|
+
work_related_injury TEXT,
|
|
190
|
+
car_accident TEXT,
|
|
191
|
+
medical_conditions TEXT,
|
|
192
|
+
allergies TEXT,
|
|
193
|
+
medications TEXT,
|
|
194
|
+
-- Form metadata
|
|
195
|
+
form_date TEXT,
|
|
196
|
+
signature_date TEXT,
|
|
197
|
+
-- System fields
|
|
198
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
199
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
200
|
+
source_file TEXT,
|
|
201
|
+
raw_extraction TEXT,
|
|
202
|
+
additional_fields TEXT,
|
|
203
|
+
is_new_patient BOOLEAN DEFAULT TRUE,
|
|
204
|
+
processing_time_seconds REAL,
|
|
205
|
+
estimated_manual_seconds REAL,
|
|
206
|
+
file_hash TEXT,
|
|
207
|
+
file_content BLOB
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
CREATE INDEX IF NOT EXISTS idx_patients_name ON patients(last_name, first_name);
|
|
211
|
+
CREATE INDEX IF NOT EXISTS idx_patients_dob ON patients(date_of_birth);
|
|
212
|
+
CREATE INDEX IF NOT EXISTS idx_patients_hash ON patients(file_hash);
|
|
213
|
+
|
|
214
|
+
-- Alerts table for tracking critical notifications
|
|
215
|
+
CREATE TABLE IF NOT EXISTS alerts (
|
|
216
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
217
|
+
patient_id INTEGER REFERENCES patients(id),
|
|
218
|
+
alert_type TEXT NOT NULL,
|
|
219
|
+
priority TEXT DEFAULT 'medium',
|
|
220
|
+
message TEXT NOT NULL,
|
|
221
|
+
data TEXT,
|
|
222
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
223
|
+
acknowledged BOOLEAN DEFAULT FALSE,
|
|
224
|
+
acknowledged_by TEXT,
|
|
225
|
+
acknowledged_at TEXT
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
CREATE INDEX IF NOT EXISTS idx_alerts_patient ON alerts(patient_id);
|
|
229
|
+
CREATE INDEX IF NOT EXISTS idx_alerts_acknowledged ON alerts(acknowledged);
|
|
230
|
+
|
|
231
|
+
-- Intake sessions for audit trail
|
|
232
|
+
CREATE TABLE IF NOT EXISTS intake_sessions (
|
|
233
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
234
|
+
patient_id INTEGER REFERENCES patients(id),
|
|
235
|
+
source_file TEXT,
|
|
236
|
+
processing_time_seconds REAL,
|
|
237
|
+
is_new_patient BOOLEAN,
|
|
238
|
+
changes_detected TEXT,
|
|
239
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
240
|
+
);
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# =============================================================================
|
|
245
|
+
# VLM EXTRACTION PROMPT
|
|
246
|
+
# =============================================================================
|
|
247
|
+
|
|
248
|
+
EXTRACTION_PROMPT = """You are a medical data extraction system. Extract ALL patient information from this intake form image.
|
|
249
|
+
|
|
250
|
+
Return a JSON object with ALL fields you can extract. Use these standard field names when applicable:
|
|
251
|
+
|
|
252
|
+
REQUIRED (always include):
|
|
253
|
+
- "first_name": patient's first name
|
|
254
|
+
- "last_name": patient's last name
|
|
255
|
+
|
|
256
|
+
PATIENT INFO:
|
|
257
|
+
- "form_date": date form was filled (YYYY-MM-DD)
|
|
258
|
+
- "date_of_birth": YYYY-MM-DD format
|
|
259
|
+
- "age": patient's age if listed
|
|
260
|
+
- "gender": Male/Female/Other
|
|
261
|
+
- "preferred_pronouns": he/him, she/her, they/them if listed
|
|
262
|
+
- "ssn": Social Security Number (XXX-XX-XXXX)
|
|
263
|
+
- "marital_status": Single/Married/Divorced/Widowed/Partnered
|
|
264
|
+
- "spouse_name": spouse's name if listed
|
|
265
|
+
- "phone": home phone number
|
|
266
|
+
- "mobile_phone": cell/mobile phone number
|
|
267
|
+
- "work_phone": work phone number
|
|
268
|
+
- "email"
|
|
269
|
+
- "address": street address
|
|
270
|
+
- "city", "state", "zip_code"
|
|
271
|
+
- "preferred_language": English/Spanish/etc if listed
|
|
272
|
+
- "race", "ethnicity": if listed
|
|
273
|
+
- "contact_preference": preferred contact method if listed
|
|
274
|
+
|
|
275
|
+
EMERGENCY CONTACT:
|
|
276
|
+
- "emergency_contact_name": name of emergency contact person
|
|
277
|
+
- "emergency_contact_relationship": relationship to patient (e.g. Mom, Spouse, Friend)
|
|
278
|
+
- "emergency_contact_phone": emergency contact's phone number
|
|
279
|
+
|
|
280
|
+
PHYSICIANS:
|
|
281
|
+
- "referring_physician": name of referring physician/doctor
|
|
282
|
+
- "referring_physician_phone": phone number next to referring physician
|
|
283
|
+
- "primary_care_physician": PCP name if different from referring
|
|
284
|
+
- "preferred_pharmacy": pharmacy name if listed
|
|
285
|
+
|
|
286
|
+
EMPLOYMENT:
|
|
287
|
+
- "employment_status": Employed/Self Employed/Unemployed/Retired/Student/Disabled/Military
|
|
288
|
+
- "occupation": job title if listed
|
|
289
|
+
- "employer": employer/company name
|
|
290
|
+
- "employer_address": employer address if listed
|
|
291
|
+
|
|
292
|
+
PRIMARY INSURANCE:
|
|
293
|
+
- "insurance_provider": insurance company name
|
|
294
|
+
- "insurance_id": policy number
|
|
295
|
+
- "insurance_group_number": group number
|
|
296
|
+
- "insured_name": name of insured person (may differ from patient)
|
|
297
|
+
- "insured_dob": DOB of insured (YYYY-MM-DD)
|
|
298
|
+
- "insurance_phone": insurance contact number
|
|
299
|
+
- "billing_address": billing address if different from home
|
|
300
|
+
- "guarantor_name": person responsible for payment if listed
|
|
301
|
+
|
|
302
|
+
SECONDARY INSURANCE:
|
|
303
|
+
- "secondary_insurance_provider", "secondary_insurance_id"
|
|
304
|
+
|
|
305
|
+
MEDICAL/PAIN HISTORY:
|
|
306
|
+
- "reason_for_visit": chief complaint or reason for visit
|
|
307
|
+
- "date_of_injury": date of injury or onset of symptoms (YYYY-MM-DD)
|
|
308
|
+
- "pain_location": where pain is located if listed
|
|
309
|
+
- "pain_onset": when pain began (e.g. three months ago)
|
|
310
|
+
- "pain_cause": what caused the pain/condition
|
|
311
|
+
- "pain_progression": Improved/Worsened/Stayed the same
|
|
312
|
+
- "work_related_injury": Yes/No
|
|
313
|
+
- "car_accident": Yes/No
|
|
314
|
+
- "medical_conditions": existing medical conditions
|
|
315
|
+
- "allergies": known allergies
|
|
316
|
+
- "medications": current medications
|
|
317
|
+
|
|
318
|
+
SIGNATURE:
|
|
319
|
+
- "signature_date": date signed (YYYY-MM-DD)
|
|
320
|
+
|
|
321
|
+
ADDITIONAL FIELDS:
|
|
322
|
+
Extract ANY other fields visible on the form using descriptive snake_case names.
|
|
323
|
+
|
|
324
|
+
IMPORTANT:
|
|
325
|
+
- Extract EVERY field visible on the form
|
|
326
|
+
- Use null for fields that exist but are blank
|
|
327
|
+
- Omit fields not present on this specific form
|
|
328
|
+
- Return ONLY the JSON object, no other text
|
|
329
|
+
- Dates must be in YYYY-MM-DD format
|
|
330
|
+
- For checkboxes, use Yes/No values"""
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
# Standard columns that map to database schema
|
|
334
|
+
STANDARD_COLUMNS = [
|
|
335
|
+
# Patient info - basic
|
|
336
|
+
"first_name",
|
|
337
|
+
"last_name",
|
|
338
|
+
"date_of_birth",
|
|
339
|
+
"age",
|
|
340
|
+
"gender",
|
|
341
|
+
"preferred_pronouns",
|
|
342
|
+
"ssn",
|
|
343
|
+
"marital_status",
|
|
344
|
+
"spouse_name",
|
|
345
|
+
# Contact info
|
|
346
|
+
"phone", # home phone
|
|
347
|
+
"mobile_phone", # cell phone
|
|
348
|
+
"work_phone",
|
|
349
|
+
"email",
|
|
350
|
+
"address",
|
|
351
|
+
"city",
|
|
352
|
+
"state",
|
|
353
|
+
"zip_code",
|
|
354
|
+
# Demographics
|
|
355
|
+
"preferred_language",
|
|
356
|
+
"race",
|
|
357
|
+
"ethnicity",
|
|
358
|
+
"contact_preference",
|
|
359
|
+
# Emergency contact
|
|
360
|
+
"emergency_contact_name",
|
|
361
|
+
"emergency_contact_relationship",
|
|
362
|
+
"emergency_contact_phone",
|
|
363
|
+
# Physicians
|
|
364
|
+
"referring_physician",
|
|
365
|
+
"referring_physician_phone",
|
|
366
|
+
"primary_care_physician",
|
|
367
|
+
"preferred_pharmacy",
|
|
368
|
+
# Employment
|
|
369
|
+
"employment_status",
|
|
370
|
+
"occupation",
|
|
371
|
+
"employer",
|
|
372
|
+
"employer_address",
|
|
373
|
+
# Primary insurance
|
|
374
|
+
"insurance_provider",
|
|
375
|
+
"insurance_id",
|
|
376
|
+
"insurance_group_number",
|
|
377
|
+
"insured_name",
|
|
378
|
+
"insured_dob",
|
|
379
|
+
"insurance_phone",
|
|
380
|
+
"billing_address",
|
|
381
|
+
"guarantor_name",
|
|
382
|
+
# Secondary insurance
|
|
383
|
+
"secondary_insurance_provider",
|
|
384
|
+
"secondary_insurance_id",
|
|
385
|
+
# Medical/Pain history
|
|
386
|
+
"reason_for_visit",
|
|
387
|
+
"date_of_injury",
|
|
388
|
+
"pain_location",
|
|
389
|
+
"pain_onset",
|
|
390
|
+
"pain_cause",
|
|
391
|
+
"pain_progression",
|
|
392
|
+
"work_related_injury",
|
|
393
|
+
"car_accident",
|
|
394
|
+
"medical_conditions",
|
|
395
|
+
"allergies",
|
|
396
|
+
"medications",
|
|
397
|
+
# Form metadata
|
|
398
|
+
"form_date",
|
|
399
|
+
"signature_date",
|
|
400
|
+
# System fields
|
|
401
|
+
"source_file",
|
|
402
|
+
"raw_extraction",
|
|
403
|
+
"additional_fields",
|
|
404
|
+
"is_new_patient",
|
|
405
|
+
"processing_time_seconds",
|
|
406
|
+
"estimated_manual_seconds",
|
|
407
|
+
"file_hash",
|
|
408
|
+
"file_content",
|
|
409
|
+
]
|
|
410
|
+
|
|
411
|
+
# Columns that can be updated for returning patients
|
|
412
|
+
UPDATABLE_COLUMNS = [
|
|
413
|
+
# Contact info (can change)
|
|
414
|
+
"phone", # home phone
|
|
415
|
+
"mobile_phone", # cell phone
|
|
416
|
+
"work_phone",
|
|
417
|
+
"email",
|
|
418
|
+
"address",
|
|
419
|
+
"city",
|
|
420
|
+
"state",
|
|
421
|
+
"zip_code",
|
|
422
|
+
"contact_preference",
|
|
423
|
+
# Marital status (can change)
|
|
424
|
+
"marital_status",
|
|
425
|
+
"spouse_name",
|
|
426
|
+
# Emergency contact (can change)
|
|
427
|
+
"emergency_contact_name",
|
|
428
|
+
"emergency_contact_relationship",
|
|
429
|
+
"emergency_contact_phone",
|
|
430
|
+
# Physicians (can change)
|
|
431
|
+
"referring_physician",
|
|
432
|
+
"referring_physician_phone",
|
|
433
|
+
"primary_care_physician",
|
|
434
|
+
"preferred_pharmacy",
|
|
435
|
+
# Employment (can change)
|
|
436
|
+
"employment_status",
|
|
437
|
+
"occupation",
|
|
438
|
+
"employer",
|
|
439
|
+
"employer_address",
|
|
440
|
+
# Insurance (can change)
|
|
441
|
+
"insurance_provider",
|
|
442
|
+
"insurance_id",
|
|
443
|
+
"insurance_group_number",
|
|
444
|
+
"insured_name",
|
|
445
|
+
"insured_dob",
|
|
446
|
+
"insurance_phone",
|
|
447
|
+
"billing_address",
|
|
448
|
+
"guarantor_name",
|
|
449
|
+
"secondary_insurance_provider",
|
|
450
|
+
"secondary_insurance_id",
|
|
451
|
+
# Medical/Pain (can change each visit)
|
|
452
|
+
"reason_for_visit",
|
|
453
|
+
"date_of_injury",
|
|
454
|
+
"pain_location",
|
|
455
|
+
"pain_onset",
|
|
456
|
+
"pain_cause",
|
|
457
|
+
"pain_progression",
|
|
458
|
+
"work_related_injury",
|
|
459
|
+
"car_accident",
|
|
460
|
+
"medical_conditions",
|
|
461
|
+
"allergies",
|
|
462
|
+
"medications",
|
|
463
|
+
# Form metadata
|
|
464
|
+
"form_date",
|
|
465
|
+
"signature_date",
|
|
466
|
+
# System fields
|
|
467
|
+
"source_file",
|
|
468
|
+
"raw_extraction",
|
|
469
|
+
"additional_fields",
|
|
470
|
+
"is_new_patient",
|
|
471
|
+
"processing_time_seconds",
|
|
472
|
+
"estimated_manual_seconds",
|
|
473
|
+
"file_hash",
|
|
474
|
+
"file_content",
|
|
475
|
+
]
|