feat: update extraction engine logic and web UI workflow - #6
Merged
Merged
Conversation
- Update LLM extraction and rules engine in the extraction service - Revamp web UI styling, layout, and core page flows (upload, processing, results) - Add new logo components, app icons, and ClaimClear Audit Report PDF - Clean up unused msg.txt
SwastikKaushal1
requested
a lite review from Copilot
and removed request for
RawaldinhoJr
September 14, 2026 22:50
There was a problem hiding this comment.
🟡 Changes recommended
Critical extraction and bank-detail rule issues, retry behavior problems, and responsive UI defects remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
This PR updates backend extraction and audit rules while revamping the web UI, branding, and workflow presentation.
Changes:
- Adds LLM provider fallback and extraction validation.
- Updates chronology and bank-detail audit rules.
- Refreshes layouts, styling, branding, and workflow pages.
File summaries
| File | Summary |
|---|---|
msg.txt |
Removes stale repository file. |
apps/web/components/logo.tsx |
Adds shared logo component. |
apps/web/app/upload/page.tsx |
Updates branded upload flow. |
apps/web/app/results/page.tsx |
Updates branded results flow. |
apps/web/app/processing/page.tsx |
Updates branded processing flow. |
apps/web/app/page.tsx |
Revamps landing page. |
apps/web/app/layout.tsx |
Updates fonts and metadata. |
apps/web/app/globals.css |
Updates theme, layout, and responsive styles. |
apps/extraction-service/rules_engine.py |
Updates chronology and bank-detail rules. |
apps/extraction-service/llm_extract.py |
Adds provider retries, fallback, and output validation. |
Review details
Suppressed comments (5)
apps/extraction-service/llm_extract.py:17
- The new fallback key is not part of
apps/extraction-service/.env.example, even though setup copies that file and the README lists both provider keys. A standard setup therefore leavesGROQ_API_KEYunset and makes this fallback unavailable; document the variable in the example/configuration instructions.
GROQ_API_KEY = os.getenv("GROQ_API_KEY") # get a free key at https://console.groq.com/keys
apps/extraction-service/rules_engine.py:130
RULE_02_DATE_CHRONOLOGYtreats equal admission and discharge timestamps as invalid (claim_dis <= claim_adm), but this guard only filters negative durations. Equal timestamps therefore produce both the chronology finding and a second0.0 hourssub-24-hour finding. Use<= 0here to avoid reporting the same root cause twice.
if duration_hours < 0:
apps/extraction-service/rules_engine.py:183
- The configured RULE_18 description also requires bank branch details, but this implementation only reads
account_numberandifsc_code. Once Section F is supplied, a claim containing those two fields but no branch details will incorrectly pass the rule; either extract/check the branch field or align the rule metadata with the actual requirement.
bank_details = claim.get("section_f_bank_details", {}) or {}
account_no = bank_details.get("account_number")
ifsc_code = bank_details.get("ifsc_code")
missing = []
if not account_no or not str(account_no).strip():
missing.append("account number")
if not ifsc_code or not str(ifsc_code).strip():
missing.append("IFSC code")
apps/web/app/globals.css:57
- At mobile widths, the 320×92 asset is rendered at 68px high (about 236px wide), while the header remains a non-wrapping flex row. The 343px content area at a 375px viewport cannot fit the logo plus the upload/results header actions, so these pages overflow horizontally. Add a responsive wrap or size/reduction rule for the header and actions.
.site-header { display: flex; align-items: center; justify-content: space-between; padding: 22px 0; }
apps/web/app/globals.css:209
- The responsive filename constraints removed from the end of the stylesheet are still needed: the new
.file-name { display: inline-flex; }rule leaves the flex item at its automatic min-content width, so a long uploaded filename can push.file-rowand the dropzone beyond the viewport instead of shrinking/ellipsizing. Restoremin-width: 0/flex: 1 1 autoon.file-name(and keep the size/remove controls non-shrinking).
.flow-steps { display: flex; align-items: center; gap: 14px; margin-top: 52px; } .dropzone { min-height: 270px; border: 1px solid var(--line); border-radius: 18px; padding: 28px; cursor: pointer; transition: border-color 160ms ease, background 160ms ease, transform 160ms ease; } .dropzone:hover, .dropzone.is-dragging { border-color: var(--teal); background: color-mix(in srgb, var(--teal) 7%, var(--paper)); transform: translateY(-2px); } .upload-icon { display: grid; place-items: center; width: 48px; height: 48px; border: 1px solid var(--line); border-radius: 12px; color: var(--teal); } .dropzone-top { align-items: flex-start; } .dropzone h2 { margin-top: 28px; } .dropzone p { line-height: 1.7; } .dropzone p small { font-size: 12px; color: var(--muted); } .browse { color: var(--ink); font-weight: 600; } .file-name { display: inline-flex; align-items: center; gap: 7px; } .upload-note { display: flex; align-items: center; gap: 8px; color: var(--muted); font: 12px var(--font-plex-mono), monospace; margin-bottom: 24px; } .page-main:has(.results-head) { display: grid; grid-template-columns: minmax(280px, .7fr) minmax(0, 1.3fr); gap: 64px; align-items: start; } .results-head { display: block; align-items: center; padding-bottom: 0; border-bottom: 0; position: sticky; top: 24px; } .score-panel { min-width: 330px; } .score-circle { display: flex; align-items: baseline; justify-content: center; width: 190px; height: 190px; border: 10px solid var(--amber); border-radius: 50%; padding-top: 4px; } .score-circle strong { font-size: 68px; line-height: 1; letter-spacing: -.08em; } .score-circle span { color: var(--muted); font: 13px var(--font-plex-mono), monospace; margin-left: 3px; } .score-status { margin: 18px 0 20px; } .score-warning { display: flex; align-items: flex-start; gap: 9px; max-width: 320px; color: var(--muted); font-size: 13px; line-height: 1.45; } .score-warning svg { flex: 0 0 auto; color: var(--rust); margin-top: 2px; } .score-warning strong { color: var(--rust); } .report-meta { align-self: flex-end; text-align: right; color: var(--muted); font-size: 13px; } .report-meta p { margin: 0 0 8px; } .findings { min-width: 0; } .findings-heading { display: flex; align-items: end; justify-content: space-between; gap: 24px; margin-bottom: 30px; } .findings h2 { margin: 0; } .findings h2 span { color: var(--muted); font-weight: 400; } .findings-note { margin: 0; color: var(--muted); font-size: 13px; } .finding { display: grid; grid-template-columns: 28px 1fr; gap: 14px; padding-left: 16px; } .finding-icon { color: var(--amber); padding-top: 2px; } .finding-critical .finding-icon { color: var(--rust); } .finding-minor .finding-icon { color: var(--teal); } .finding h3 { margin-bottom: 7px; } .center-page { min-height: auto; padding: 84px 24px 100px; } .processing { width: min(100%, 560px); } .processing h1 { margin-bottom: 38px; } .site-footer { margin-top: auto; }
- Files reviewed: 10/14 changed files
- Comments generated: 7
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
243
to
+247
| client = genai.Client(api_key=GEMINI_API_KEY) | ||
|
|
||
|
|
||
| def _call_gemini(prompt: str) -> dict: | ||
| response = client.models.generate_content( |
| raise RuntimeError("GROQ_API_KEY not set in .env") | ||
|
|
||
| response = groq_client.chat.completions.create( | ||
| model="llama-3.3-70b-versatileL", |
Comment on lines
+175
to
+177
| bank_details = claim.get("section_f_bank_details", {}) or {} | ||
| account_no = bank_details.get("account_number") | ||
| ifsc_code = bank_details.get("ifsc_code") |
| gemini_error = e | ||
| print(f"[Gemini] attempt {attempt}/{GEMINI_MAX_RETRIES} failed: {e}") | ||
| if attempt < GEMINI_MAX_RETRIES: | ||
| time.sleep(GEMINI_RETRY_DELAY_SECONDS * attempt) |
Comment on lines
+316
to
+320
| if result is None: | ||
| raise RuntimeError( | ||
| f"All providers failed.\n" | ||
| f"Gemini error: {gemini_error}\n" | ||
| f"Groq error: {groq_error}" |
| export function Logo() { | ||
| return ( | ||
| <Link className="wordmark" href="/" style={{ display: 'inline-flex', alignItems: 'center' }}> | ||
| <Image src="/logo.png" alt="ClaimClear" width={320} height={92} priority style={{ height: 68, width: 'auto' }} /> </Link> |
| <div className="hero-content"> | ||
| <p className="mono-label">CLAIMS, MADE CLEAR</p> | ||
| <h1>Know what to fix before you <span className="accent-italic">submit</span>.</h1> | ||
| <p className="hero-copy">ClaimClear reviews your clinical record and draft claim in one calm, guided pass-so avoidable errors do not become delays.</p> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR introduces a full-stack update that enhances the LLM extraction logic and rules engine in the backend, while delivering a comprehensive UI revamp for the web frontend. It includes core layout updates, newly added branding assets (logos and app icons), and the addition of the ClaimClear Audit Report.
Type of Change
Changes
Backend (Extraction Service):
apps/extraction-service/llm_extract.pyto refine the LLM extraction logic.apps/extraction-service/rules_engine.pyto adjust processing rules.Frontend (Web UI):
globals.cssandlayout.tsx.page.tsx,upload/page.tsx,processing/page.tsx, andresults/page.tsx.logo.tsx) and visual assets (logo.png,icon.png).ClaimClear_Audit_Report.pdfto the public directory.Cleanup:
msg.txtfrom the root directory.Testing
llm_extract.pyandrules_engine.py.ClaimClear_Audit_Report.pdfis successfully accessible via its public route.