Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Govi

Python FastAPI TypeScript Next.js JavaScript Chrome MV3

Terraform Ansible Docker Swarm PostgreSQL Google Cloud Keycloak OpenTelemetry

English · Tiếng Việt


English

An AI companion that walks citizens through every administrative procedure. Filed right the first time.

Vietnam AI Innovation Challenge, track AI-guided public service procedures.

Govi plugs straight into the real National Public Service Portal. A citizen opens the procedure page they already know, and Govi shows the filing form right there, checks it before they submit, reads their document photos for them and cross-checks the values. No portal clone, no app to install, no leaving the page.

Read this first: ONE-PAGER (5 min) · Storyboard of the real UI · Storyboard of the real Portal UI · Why we put the form inside the portal ← the question everyone asks · Architecture and system diagram · AI Safety and Grounding · Demo script · Integration roadmap

Storyboard of the real UI: 8 steps

8 steps: (I) one complete filing pass, from injecting the button, opening the form, two-layer validation and OCR cross-check, through to ready to submit; (II) the four remaining features that have a UI of their own: proactive suggestions, legal citation explanations, Govi Radar, smart search. The HTML/CSS is taken word for word from today's ui.js / insights.js / legal-explain.js / radar.js / search.js. Only the sample data and the portal frame around it are staged.

8-step storyboard of the real Govi extension UI

Interactive version (open it in any browser, nothing to install): docs/storyboard-ui.html

Portal storyboard: 8 screens for civil servants

Real screenshots from the running portal, not a rebuild: login, overview, form health, suggestion review, citizen submissions, policies.

8 Portal screens, captured from the running portal


Four components, all live in production

Component What it is Address
govi-widget/apps/extension/ The main product, an MV3 content script that puts the form into the portal, buildless Load unpacked
govi-backend/ FastAPI: OCR, AI validation, smart search, telemetry, policy radar https://api.vietnamaichallenge-govi.team
govi-portal/ Next.js dashboard for civil servants: Form Health, suggestion review, policy review, submission review https://portal.vietnamaichallenge-govi.team
govi-infra/ Terraform and Ansible: GCP, Docker Swarm, nginx/TLS, Keycloak, SigNoz (no public address)

Supporting infrastructure: auth.vietnamaichallenge-govi.team (Keycloak), obs.vietnamaichallenge-govi.team (SigNoz, for traces/logs/metrics).

Portal demo account: admin / admin.

Pushing to main deploys: GitHub Actions → Workload Identity Federation (no service-account keys) → Cloud Build → ssh over IAP → Docker Swarm rolling update.


Models and APIs in use

All inference runs through FPT AI Marketplace (OpenAI-compatible), not a foreign model provider. This is a deliberate choice: the administrative data of Vietnamese citizens is processed on infrastructure located in Vietnam and run by a Vietnamese company. That is very nearly a hard requirement for real integration into public services.

Task Model How the output is constrained
Semantic validation of a filing gpt-oss-120b forced tool call + closed enum of 15 error codes
Reading document images (OCR/VLM) Qwen2.5-VL-7B-Instruct prompt-JSON + a deterministic guardrail behind it
Two-VLM consensus Qwen2.5-VL-7B + gemma-3-27b-it pure-Python comparison; if they disagree, keep the primary and flag it
Search ranking self-hosted BM25 (runs locally) (not a model)
Search refusal gate bge-reranker-v2-m3 only decides "is this relevant", it does not re-rank
Pulling conditions out of legal texts gpt-oss-120b forced tool + closed attribute enum, fail-closed

Without an API key the backend degrades instead of dying: validation falls back to the deterministic rule layer, search falls back to plain BM25.


Honest status

This section says exactly what runs for real, what is simulated and what is not switched on, so nobody has to guess.

Real, with real data

  • Form injection and deterministic validation across 135 procedures (apps/extension/forms.js, about 2,660 declared fields).
  • OCR, semantic validation and document cross-checking through the backend.
  • Smart search over the 25 essential public services of Project 06 (108 knowledge chunks, 39 sources, 41 chunks eligible for citation).
  • Portal: Form Health, suggestion review, policy CRUD and review, submission review.
  • Real Keycloak login (ROPC), real SigNoz observability, real CI/CD.
  • 397 backend tests and 49 extension assertions (4 jsdom suites), all green.

Simulated on purpose, a demo of the idea rather than unfinished work

profile_service.py (7 hardcoded personas) is simulated data on purpose. It exists to prove something words cannot: once Govi is connected to citizen data, the interface is already able to receive it. The searchProfile contract runs for real, plugs straight into /ai/smart-search, and has tests locking its shape.

What is missing is access to the data, not the source code.

Govi aims to be integrated with the National Data Center. That is when this feature changes level: instead of citizens describing their own situation, Govi already understands their life context (a birth certificate just issued at home, an ID card about to expire, a child turning six) and offers the right procedure before they think to ask. That is an institutional condition, it needs a ministry-level agreement, not a technical one. See PILOT.md §3.

Until the data is real, smart search deliberately returns profileApplied: false: it accepts a correctly shaped profile but does not use it for ranking. Reporting true on simulated data would be an overclaim.

This personalization does not contradict the Radar module's principle of "Govi delivers the question, never receives the answer". They are two different data flows, told apart in AI-SAFETY.md §6.

Built, not switched on

  • Dense retrieval (smart_search/embed.py) is fully implemented but not wired into the production engine. The reason is a measurement, not an oversight: across 68 in-scope cases, letting the cross-encoder re-rank dropped Recall@1 from 0.933 to 0.844. BM25 plus the refusal gate does better at a 25-procedure scale. The code stays, together with its numbers, ready to switch on when the corpus grows.

Coverage: two overlapping sets, not nested ones

Count
Procedures with a filing form and validation 135
Procedures with a smart lookup card (Project 06) 25
Of those, at detailed level, with full legal citations 6
Procedures with both (fileable and searchable) 6

The two layers differ on purpose. Filing and validation only needs a form definition, so it scales fast. Smart lookup cites the legal basis, and once you quote the law for a citizen to read, the underlying data has to be verified first. So it only opens for the part where that work is done.

Not citing law for unverified content is a principle, not a technical limit. The engine is complete and data-driven: widening coverage means loading more verified data, without touching a single line of code.

We measured the gap between "the team grading itself" and "a stranger typing"

The original eval set was written by the team, so its questions and aliases share one source, which makes it optimistic. The team wrote a second, adversarial eval set (govi-backend/evals/, 53 cases) under the opposite rule: questions have to be phrased the way citizens actually speak, and reusing corpus aliases is forbidden.

Metric Original set Adversarial set
Correct refusal (out of scope) 1.000 1.000
Recall@1 0.933 0.684
Recall@5 1.000 0.763

A drop of about 0.24 on both recall metrics. The right-hand column is the number to trust.

This set caught a real trade-off on its very first run: the scope_exclusions fix took correct refusal from 0.800 to 1.000 but pulled recall down by 0.053, and the two cases it lost were genuine ones (đăng ký kết hôn cần giấy tờ gì is now refused, even though đăng ký kết hôn still works). Details and the plan: AI-SAFETY §9.1. tests/test_smart_search_eval.py locks it in as a regression net.

Not done

  • An eval set built from the portal's real search logs. The adversarial set is still team-written.
  • Legal-data verification for the 19 of 25 cards not yet at detailed level.

Try it

Extension (the main demo path)

# chrome://extensions → turn on Developer mode → Load unpacked → select:
govi-widget/apps/extension

Then open a real procedure page:

The extension already points at the production backend, so nothing needs to run locally. Click-by-click script: docs/DEMO.md.

cd govi-widget && pnpm install && pnpm test   # 4 jsdom suites

Backend

cd govi-backend
cp .env.example .env          # set FPT_MARKETPLACE_API_KEY to turn on the AI layer
python3.12 -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest -q
docker compose up -d postgres && .venv/bin/alembic upgrade head
.venv/bin/uvicorn app.main:app --reload    # Swagger at /docs

⚠️ Use Python 3.12, the same version the container runs. A dev machine once ran 3.14 and that gap took production down while CI stayed green. Details in CLAUDE.md.

Portal

cd govi-portal && pnpm install
cp .env.example .env.local    # point GOVI_API_URL at the backend
pnpm dev

Documentation

File Contents
docs/ONE-PAGER.md Problem, solution, target users, rollout plan
docs/storyboard-ui.html 8-step storyboard of the real extension UI. Download it and open in a browser, no install needed
Portal storyboard The 8 govi-portal screens
docs/WHY-EMBED.md Why we put the form inside the real portal instead of building a separate app, and why that is the shape of the future portal
docs/ARCHITECTURE.md System diagram, data flow, the reason behind each choice
docs/AI-SAFETY.md Anti-hallucination principles, grounding, human-in-the-loop, known limits
docs/DEMO.md Step-by-step demo script for judges
docs/PILOT.md Roadmap for integration into public services
docs/error-codes.md Error-code taxonomy, the source of truth
docs/telemetry-spec.md Form event collection (no PII)
docs/insight-spec.md The telemetry to suggestion loop that helps the next citizen
docs/policy-radar-spec.md "The law finds the person": new policies reaching the right beneficiaries
CLAUDE.md Engineering conventions, traps we hit, open work
govi-infra/README.md Infrastructure, deployment, operations

Tiếng Việt

Trợ lý AI đồng hành cùng người dân trong mọi thủ tục hành chính. Nộp đúng ngay lần đầu.

Vietnam AI Innovation Challenge, đề AI-guided public service procedures.

Govi chèn thẳng vào Cổng Dịch vụ công thật. Người dân mở trang thủ tục quen thuộc, Govi hiện form kê khai ngay tại chỗ, soát lỗi trước khi nộp, đọc giúp ảnh giấy tờ và đối chiếu chéo. Không clone cổng, không cài app, không rời trang.

Lấy gì đọc trước: ONE-PAGER (5 phút) · Storyboard UI thật · Storyboard Portal UI thật · Vì sao chèn form vào cổng ← câu hỏi ai cũng hỏi · Kiến trúc và sơ đồ hệ thống · AI Safety và Grounding · Kịch bản demo · Lộ trình tích hợp

Storyboard UI thật: 8 bước

8 bước: (I) một lượt kê khai đầy đủ, từ chèn nút, mở form, soát lỗi 2 tầng và đối chiếu OCR, cho tới lúc sẵn sàng nộp; (II) 4 tính năng còn lại có giao diện riêng: gợi ý chủ động, giải thích trích dẫn pháp lý, Govi Radar, tìm kiếm thông minh. HTML/CSS lấy nguyên văn từ ui.js / insights.js / legal-explain.js / radar.js / search.js hiện tại. Chỉ dữ liệu mẫu và khung cổng xung quanh là dàn dựng.

Storyboard 8 bước UI thật của Govi extension

Bản tương tác (mở bằng trình duyệt, không cần cài gì): docs/storyboard-ui.html

Storyboard Portal: 8 màn hình cán bộ

Ảnh chụp thật từ portal đang chạy, không phải dựng lại: đăng nhập, tổng quan, sức khoẻ biểu mẫu, duyệt gợi ý, hồ sơ người dân nộp về, chính sách.

8 màn hình Portal, chụp từ portal đang chạy


Hệ thống gồm 4 thành phần, đã chạy thật trên production

Thành phần Là gì Địa chỉ
govi-widget/apps/extension/ Sản phẩm chính, content script MV3 chèn form vào cổng, buildless cài Load unpacked
govi-backend/ FastAPI: OCR, soát lỗi AI, smart search, telemetry, radar chính sách https://api.vietnamaichallenge-govi.team
govi-portal/ Bảng điều khiển Next.js cho cán bộ: Form Health, duyệt gợi ý, duyệt chính sách, duyệt hồ sơ https://portal.vietnamaichallenge-govi.team
govi-infra/ Terraform và Ansible: GCP, Docker Swarm, nginx/TLS, Keycloak, SigNoz (không có địa chỉ công khai)

Hạ tầng phụ: auth.vietnamaichallenge-govi.team (Keycloak), obs.vietnamaichallenge-govi.team (SigNoz, lo trace/log/metric).

Tài khoản demo portal: admin / admin.

Push main là deploy: GitHub Actions → Workload Identity Federation (không có service-account key) → Cloud Build → ssh qua IAP → Docker Swarm rolling update.


Mô hình và API đang dùng

Toàn bộ suy luận chạy qua FPT AI Marketplace (OpenAI-compatible), không phải model nước ngoài. Đây là lựa chọn có chủ ý: dữ liệu hành chính của công dân Việt Nam được xử lý bởi hạ tầng đặt tại Việt Nam, do doanh nghiệp Việt Nam vận hành. Đó gần như là điều kiện bắt buộc nếu muốn tích hợp thật vào hệ thống dịch vụ công.

Việc Model Cách ràng buộc đầu ra
Soát lỗi ngữ nghĩa hồ sơ gpt-oss-120b forced tool call + enum đóng 15 mã lỗi
Đọc ảnh giấy tờ (OCR/VLM) Qwen2.5-VL-7B-Instruct prompt-JSON + hàng rào kiểm tất định phía sau
Đồng thuận hai VLM Qwen2.5-VL-7B + gemma-3-27b-it so khớp thuần Python; lệch thì giữ bản chính và ghi chú
Xếp hạng tìm kiếm BM25 tự cài (chạy tại chỗ) (không phải model)
Cổng từ chối tìm kiếm bge-reranker-v2-m3 chỉ phán "có liên quan không", không xếp lại
Trích điều kiện từ văn bản luật gpt-oss-120b forced tool + enum thuộc tính đóng, fail-closed

Thiếu khoá API thì backend giảm cấp chứ không chết: soát lỗi rơi về tầng luật tất định, tìm kiếm rơi về BM25 thuần.


Trạng thái trung thực

Phần này liệt kê đúng cái gì đã chạy thật, cái gì là mô phỏng, cái gì chưa bật, để không ai phải đoán.

Chạy thật, có dữ liệu thật

  • Chèn form và soát lỗi tầng thuần trên 135 thủ tục (apps/extension/forms.js, khoảng 2.660 ô khai báo).
  • OCR, soát ngữ nghĩa và đối chiếu chéo giấy tờ qua backend.
  • Smart search trên 25 dịch vụ công thiết yếu Đề án 06 (108 knowledge chunk, 39 nguồn, 41 chunk đủ điều kiện trích dẫn).
  • Portal: Form Health, duyệt gợi ý, CRUD và duyệt chính sách, duyệt hồ sơ nộp về.
  • Đăng nhập Keycloak thật (ROPC), quan trắc SigNoz thật, CI/CD thật.
  • 397 test backend và 49 assertion extension (4 bộ jsdom), tất cả xanh.

Mô phỏng có chủ đích, là demo tư tưởng chứ không phải chỗ làm dở

profile_service.py (7 persona hardcode) cố ý là dữ liệu mô phỏng. Nó tồn tại để chứng minh một điều không chứng minh được bằng lời: khi Govi được nối vào dữ liệu công dân, giao diện đã sẵn sàng nhận. Hợp đồng searchProfile đã chạy thật, cắm thẳng vào /ai/smart-search được, có test khoá shape.

Thứ còn thiếu là quyền truy cập dữ liệu, không phải mã nguồn.

Govi hướng tới được tích hợp với Trung tâm Dữ liệu Quốc gia. Đó là lúc tính năng này đổi bậc: thay vì người dân phải tự mô tả hoàn cảnh, Govi hiểu sẵn bối cảnh cuộc sống của họ (nhà vừa có giấy chứng sinh, căn cước sắp hết hạn, con đến tuổi vào lớp 1) và đưa đúng thủ tục lên trước khi họ kịp hỏi. Việc này thuộc nhóm điều kiện thể chế, cần thoả thuận cấp bộ, chứ không phải điều kiện kỹ thuật. Xem PILOT.md §3.

Chừng nào chưa có dữ liệu thật, smart search cố ý trả profileApplied: false: nhận hồ sơ đúng shape nhưng không dùng để xếp hạng. Báo true trên dữ liệu mô phỏng sẽ là nói quá.

Cá nhân hoá này không mâu thuẫn với nguyên tắc "Govi giao câu hỏi, không nhận câu trả lời" của module Radar. Đó là hai luồng dữ liệu khác nhau, phân biệt rõ ở AI-SAFETY.md §6.

Đã cài, chưa bật

  • Dense retrieval (smart_search/embed.py) đã cài đặt đầy đủ nhưng không được nối vào engine production. Lý do là số đo, không phải quên: trên 68 ca in-scope, để cross-encoder xếp lại làm Recall@1 tụt từ 0.933 xuống 0.844. BM25 cộng cổng từ chối cho kết quả tốt hơn ở quy mô 25 thủ tục. Code giữ lại kèm số đo, sẵn sàng bật khi corpus lớn hơn.

Độ phủ: hai tập giao nhau, không lồng nhau

Số lượng
Thủ tục có form kê khai và soát lỗi 135
Thủ tục có thẻ tra cứu thông minh (Đề án 06) 25
Trong đó đạt mức detailed, có trích dẫn pháp lý đầy đủ 6
Thủ tục có cả hai (vừa kê khai được vừa tra cứu được) 6

Hai tầng cố ý khác nhau. Kê khai và soát lỗi chỉ cần định nghĩa form, nên phủ rộng được nhanh. Tra cứu thông minh thì trích dẫn căn cứ pháp lý, mà đã trích luật cho người dân đọc thì dữ liệu phải được thẩm định trước. Nên nó chỉ mở cho phần đã làm xong việc đó.

Không trích dẫn luật cho thứ chưa thẩm định là nguyên tắc, không phải giới hạn kỹ thuật. Engine đã hoàn chỉnh và data-driven: mở rộng phạm vi là nạp thêm dữ liệu đã thẩm định, không đụng một dòng code nào.

Đã tự đo khoảng cách giữa "đội tự chấm" và "người lạ gõ"

Bộ eval gốc do chính đội soạn nên câu hỏi và alias cùng một nguồn, vì thế nó lạc quan. Đội soạn thêm một bộ eval đối kháng (govi-backend/evals/, 53 ca) theo luật ngược lại: câu hỏi phải diễn đạt như người dân nói, cấm tái dùng alias trong corpus.

Chỉ số Bộ gốc Bộ đối kháng
Từ chối đúng (ngoài phạm vi) 1.000 1.000
Recall@1 0.933 0.684
Recall@5 1.000 0.763

Chênh khoảng 0.24 ở hai chỉ số recall. Con số bên phải là con số đáng tin hơn.

Bộ này đã bắt được một đánh đổi thật ngay ngày đầu chạy: bản sửa scope_exclusions đưa từ chối đúng từ 0.800 lên 1.000 nhưng kéo recall xuống 0.053, và hai ca mất đi là ca thật (đăng ký kết hôn cần giấy tờ gì giờ bị từ chối, dù đăng ký kết hôn vẫn chạy). Chi tiết và hướng xử lý: AI-SAFETY §9.1. tests/test_smart_search_eval.py khoá lại làm lưới chặn hồi quy.

Chưa làm

  • Bộ eval từ log tra cứu thật của cổng. Bộ đối kháng vẫn do đội soạn.
  • Thẩm định dữ liệu pháp lý cho 19 trong 25 thẻ chưa đạt mức detailed.

Chạy thử

Extension (đường demo chính)

# chrome://extensions → bật Developer mode → Load unpacked → chọn:
govi-widget/apps/extension

Rồi mở một trang thủ tục thật:

Extension đã trỏ sẵn về backend production, nên không cần chạy gì ở máy. Kịch bản bấm từng bước: docs/DEMO.md.

cd govi-widget && pnpm install && pnpm test   # 4 bộ test jsdom

Backend

cd govi-backend
cp .env.example .env          # đặt FPT_MARKETPLACE_API_KEY nếu muốn bật tầng AI
python3.12 -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest -q
docker compose up -d postgres && .venv/bin/alembic upgrade head
.venv/bin/uvicorn app.main:app --reload    # /docs có Swagger

⚠️ Dùng đúng Python 3.12 như container. Máy dev từng chạy 3.14 và khoảng lệch đó đã làm production đổ một lần trong khi CI vẫn báo xanh. Chi tiết ở CLAUDE.md.

Portal

cd govi-portal && pnpm install
cp .env.example .env.local    # trỏ GOVI_API_URL về backend
pnpm dev

Tài liệu

File Nội dung
docs/ONE-PAGER.md Vấn đề, giải pháp, người dùng mục tiêu, lộ trình triển khai
docs/storyboard-ui.html Storyboard 8 bước UI thật (extension). Tải về mở bằng trình duyệt, không cần cài extension
Storyboard Portal 8 màn hình govi-portal
docs/WHY-EMBED.md Vì sao chèn form vào cổng thật thay vì dựng app riêng, và vì sao đó là hình dạng của cổng trong tương lai
docs/ARCHITECTURE.md Sơ đồ hệ thống, luồng dữ liệu, lý do từng lựa chọn
docs/AI-SAFETY.md Nguyên tắc chống bịa, grounding, human-in-the-loop, giới hạn đã biết
docs/DEMO.md Kịch bản demo từng bước cho người chấm
docs/PILOT.md Lộ trình tích hợp vào hệ thống dịch vụ công
docs/error-codes.md Taxonomy mã lỗi, nguồn sự thật
docs/telemetry-spec.md Thu thập sự kiện form (không PII)
docs/insight-spec.md Vòng lặp telemetry thành gợi ý, cứu người dân kế tiếp
docs/policy-radar-spec.md "Luật đi tìm người": chính sách mới tìm đúng người thụ hưởng
CLAUDE.md Quy ước kỹ thuật, bẫy đã gặp, việc đang mở
govi-infra/README.md Hạ tầng, deploy, vận hành

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages