How nitianji415/tj-sylva works
1. Overall shape
This repo is a single Python application that bundles a backend API and a static browser UI. The backend is a FastAPI service; the frontend is plain HTML/CSS/JS served from static/. The core product concept is a “left-side AI conversation + right-side growing knowledge tree” workflow.
2. Primary runtime boundary
Requests enter through FastAPI in app/main.py, with route modules in app/routers/ splitting the API by domain: auth, sessions, messages, nodes, prompts, settings, web search, and health. app.py / server.py are convenience entrypoints for local launch, while Docker runs the same app inside the app service.
3. Layering inside the backend
The backend is organized in a fairly standard API → service → persistence stack:
- app/routers/* handles HTTP/SSE endpoints and auth guards
- app/services/* contains business logic and external integrations
- app/db/models.py defines SQLAlchemy ORM entities
- app/schemas/* defines request/response contracts
- app/core/* holds config and SSE helpers
This is the main boundary to preserve if drawing the architecture.
4. Core domain subsystem: knowledge growth
app/services/knowledge.py is the central orchestration layer. It manages the learning loop that creates sessions, streams assistant replies, grows tree nodes, subdivides topics, and keeps messages/nodes in sync. The README and routes indicate that session creation can also generate an initial “knowledge map,” so the session is not just chat history; it is the root container for the tree.
5. Data model and persistence
The persistent model is PostgreSQL by default, with Alembic migrations under alembic/versions/. The main entities implied by the routes and migrations are sessions, messages, nodes, prompts, settings, peeks, and LLM usage/events. Structural evolution is important here: features like collapsed nodes, prerequisite IDs, highlights, search sources, context summary, and usage tracking were added incrementally via migrations.
6. LLM integration boundary
app/services/ai.py is the single LLM client wrapper. The project intentionally uses one OpenAI Chat Completions–compatible interface, so provider changes happen via LLM_BASE_URL rather than code changes. If the model call fails, the system falls back to local logic in app/services/topics.py, which is important architecturally because the app remains usable even when the LLM path is degraded.
7. Search subsystem
Web search is separate from the LLM path. app/services/web_search.py and app/services/web_search_daemon.py talk to a local open-webSearch daemon by default, with anysearch as an alternate provider and off as a full disable. This means search is an external capability with its own service boundary, not embedded in the main app process.
8. Authentication and settings
Auth is JWT-based through app/services/auth.py and app/routers/auth.py. Runtime settings are editable by admins via app/routers/settings.py, and sensitive values such as LLM API keys are encrypted before being stored in the database. SETTINGS_SECRET, JWT_SECRET, and ADMIN_PASSWORD are therefore architectural secrets, not just configuration details.
9. UI interaction model
The frontend is not a separate SPA framework; it is a server-served static client in static/ that talks to the API directly. The user experience depends heavily on streaming responses: app/core/sse.py and the message/session streaming routes support token-like live updates and progressive tree growth, rather than a request/response-only flow.
10. Domain features exposed through routes
The route surface maps closely to product features:
- sessions: create, list, preview topics, grow children, fetch tree/messages
- messages: stream answers, peeks, follow-up questions
- nodes: edit status, collapse state, and subdivision actions
- prompts/settings: tune model behavior and runtime defaults
- web search: query external search sources
This is useful for a diagram because each route group corresponds to a visible user workflow.
11. Deployment topology
The Docker Compose setup defines three services: app, postgres, and open-websearch. The app listens on port 8765 and serves both backend API and frontend assets. The search daemon is optional in development but is part of the default Docker-based production topology.
12. Testing and operational support
Tests under tests/ cover health, sessions, nodes, peeks, intent/search query behavior, and context optimization, indicating the system is organized around end-user learning flows rather than generic CRUD. There is also a migration script for moving an old SQLite dataset into Postgres, showing the project has a real persistence upgrade path and not just greenfield storage.
13. What to emphasize in a diagram
A good architecture diagram for this repo should center on: browser UI → FastAPI routes → service layer → PostgreSQL, with side integrations to the LLM provider and the search daemon. The most important internal seam is that the service layer owns business logic, while routers stay thin and schemas enforce the API contract.
Main entry points: main.py FastAPI App · knowledge.py Knowledge · models.py ORM Models · sessions.py Sessions
Components 24
Client
Static browser UI served by the app
- Browser UI · Served HTML entrypoint for the browser interface
static/index.html - UI Logic · Client-side interaction layer for the static UI
static/app.js
API
FastAPI entrypoint and route layer
- FastAPI App · Application startup and router wiring
app/main.py - Sessions · Session creation, tree access, and session workflow endpoints
app/routers/sessions.py - Messages · Streaming replies, peeks, and follow-up message endpoints
app/routers/messages.py - Nodes · Node editing, collapse state, and subdivision actions
app/routers/nodes.py - Prompts · Prompt template and model-behavior endpoints
app/routers/prompts.py - Settings · Admin runtime settings endpoints
app/routers/settings.py - Auth · JWT login and auth endpoints
app/routers/auth.py - Web Search · Search query endpoints and search-provider access
app/routers/web_search.py - Health · Service liveness and readiness endpoint
app/routers/health.py - API Schemas · Request and response contracts shared across routes
app/schemas/session.py - Config · Environment-backed settings and secrets
app/core/config.py - SSE · Server-sent events helpers for live response streaming
app/core/sse.py
Domain
Business logic and external capability adapters
- Knowledge · Core learning loop that streams answers and grows the tree
app/services/knowledge.py - LLM Client · Chat-completions compatible model wrapper
app/services/ai.py - Topic Fallback · Local topic and subdivision logic when LLM calls degrade
app/services/topics.py - Auth Service · JWT issuing and validation logic
app/services/auth.py - Search Service · Search orchestration and provider selection
app/services/web_search.py
Persistence
ORM models and database schema evolution
- ORM Models · Persistent entities for sessions, messages, nodes, prompts, settings, and usage
app/db/models.py - Migrations · Database evolution for new learning and search features
alembic/versions/20260517_0001_initial.py
Integrations
External providers and optional daemons
- Search Daemon · Client for the local open-websearch daemon
app/services/web_search_daemon.py
Deploy
Container and migration support
- Compose Stack · App, Postgres, and search daemon runtime topology
docker-compose.yml - SQLite Migrator · Utility for moving legacy SQLite data into PostgreSQL
scripts/migrate_sqlite_to_postgres.py
Connections 29
- Browser UI → UI Logic: loads · The browser shell is driven by client-side JavaScript
- UI Logic → FastAPI App: calls API · The UI talks directly to the FastAPI backend
- FastAPI App → Sessions: mounts · Session routes are registered under the application
- FastAPI App → Messages: mounts · Message routes are registered under the application
- FastAPI App → Nodes: mounts · Node routes are registered under the application
- FastAPI App → Prompts: mounts · Prompt routes are registered under the application
- FastAPI App → Settings: mounts · Settings routes are registered under the application
- FastAPI App → Auth: mounts · Auth routes are registered under the application
- FastAPI App → Web Search: mounts · Web search routes are registered under the application
- FastAPI App → Health: mounts · Health routes are registered under the application
- Sessions → Knowledge: orchestrates · Session endpoints delegate to the knowledge-growth workflow
- Messages → Knowledge: streams through · Message endpoints trigger the learning loop and live updates
- Nodes → Knowledge: mutates tree · Node actions are coordinated through the knowledge subsystem
- Prompts → API Schemas: validates · Prompt routes use shared API contracts
- Settings → API Schemas: validates · Settings routes use shared API contracts
- Auth → Auth Service: delegates · Auth routes delegate login and token handling
- Web Search → Search Service: delegates · Search routes forward queries to the search adapter
- Knowledge → LLM Client: uses · Primary path for model-driven responses
- Knowledge → Topic Fallback: fallbacks to · Local logic keeps the workflow usable when model calls fail
- Knowledge → ORM Models: persists · Knowledge growth reads and writes sessions, messages, and nodes
- Auth Service → ORM Models: stores users · Auth state depends on persisted account and secret data
- Search Service → Search Daemon: queries · Search service talks to the external daemon/provider boundary
- Sessions → SSE: streams · Session APIs use SSE for progressive updates
- Messages → SSE: streams · Message APIs emit live assistant events
- ORM Models → Migrations: evolved by · Schema changes are captured through migrations
- FastAPI App → Config: reads config · Application startup depends on runtime settings
- Compose Stack → FastAPI App: runs · Containerized app service launches the FastAPI process
- Compose Stack → Search Daemon: runs · Compose includes the optional search daemon
- SQLite Migrator → ORM Models: transfers data · Legacy SQLite data is reshaped into the current schema