Deliverables
What we've shipped
Architecture Diagram
Nora is a client-server web application with three tiers: a React app in the user's browser, a FastAPI server, and a PostgreSQL database. It works by request and response, and is not event-driven or real-time. The server answers questions with retrieval-augmented generation (RAG): it finds the relevant policy passages first, then has an LLM write an answer from them.
- Our work
- Existing UNC or third-party, which we adapt to
- Inside CloudApps (fast, internal network)
- Over the internet (much slower)
Scroll sideways to see the whole diagram.
Where Things Run
The user's browser
Researchers and admins are the outside world. Their browser, on any desktop or phone, runs the React app and sends every request across the internet.
Carolina CloudApps
UNC's servers run our web container, API container, and database. Traffic between them stays on CloudApps' internal network.
Third-party AI services
The LLM and embedding providers run on their own servers. Each call crosses the internet, which is why an answer takes seconds, not milliseconds (spec NF8).
Data Flow: Asking a Question
- 1
The researcher types a question in the browser, which sends it to /api over HTTPS.
- 2
The API turns the question into a vector with the embedding API.
- 3
pgvector finds the policy passages closest in meaning to the question.
- 4
If nothing relevant enough is found, Nora says so and points the researcher to the right compliance office, without calling the LLM.
- 5
Otherwise the API sends the question and those passages to the LLM, which writes a plain-language answer that cites them.
- 6
The API saves the question, whether it was answered, and later any feedback, which feed the admin dashboard, and returns the answer with its sources.
Components
Scaffolded means the piece exists in our repository as a working skeleton; Planned means we haven't connected to it yet.
Web container (nginx + React)
OursScaffoldedRuns in the user's browser once loaded: the researcher views (Browse, Search, Ask) and the admin portal. In production, an unprivileged nginx serves the built app on port 8080 and forwards /api/* to the API, so the browser only ever talks to one origin.
API container (FastAPI)
OursScaffoldedAll application logic, behind a JSON API under /api: resolving the user and their role, keyword search and topic browsing, the Ask pipeline, admin content management and analytics, and ingesting new documents. Only a health check exists so far.
PostgreSQL + pgvector
OursScaffoldedThe single data store: policy documents and their chunks with embeddings, users and roles, questions asked, and feedback. Our first migration enables pgvector; the tables come next.
UNC Shibboleth SSO
Existing (UNC)PlannedUNC's Onyen sign-in. We adapt to it rather than build it: in production it will likely sit in front of the app and pass the user's identity in, with the exact pattern still to confirm with UNC ITS. Until then we use a mock login that models it.
Carolina CloudApps
Existing (UNC)PlannedUNC's OpenShift platform, which runs our containers. It requires non-root images that work under any user ID, which ours already do.
UNC Policy Knowledge Base
Existing (UNC)PlannedThe source of Nora's content. There is no live connection: admins choose documents and upload them through the admin portal.
LLM and embedding APIs
Third-partyPlannedExternal AI services reached over the internet. Both sit behind interfaces in the API so the provider can change once UNC approves one, and so tests never call them.