Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
177 commits
Select commit Hold shift + click to select a range
136664d
feat(kg-rag): port semantic-graph KG-RAG into new lamb-kb-server arch
AdriaGuilera May 17, 2026
e515224
fix(kg-rag): address review feedback from self-review
AdriaGuilera May 17, 2026
7ec425e
feat(kg-rag): wire Graph RAG into the Knowledge Store UI (locked-at-c…
AdriaGuilera May 17, 2026
229bd0b
fix(kg-rag): question-entity extractor uses per-collection model
AdriaGuilera May 18, 2026
029568e
feat(kg-rag): auto-route /query through KG-RAG plugin for graph-enabl…
AdriaGuilera May 24, 2026
23687fe
feat(graph): per-collection concept verification, drag/zoom graph, cu…
AdriaGuilera May 27, 2026
7df653e
Merge remote-tracking branch 'upstream/projects/refactor/kbserver-lam…
AdriaGuilera May 27, 2026
0d0266a
fix: resolve merge conflicts integrating KG-RAG features with upstrea…
AdriaGuilera May 27, 2026
63bbfc0
test: add single_file_rag tests for Library Manager support
Fr4n9 May 28, 2026
68e019f
feat: single_file_rag fetches content from Library Manager via HTTP
Fr4n9 May 28, 2026
7e83e28
feat: extract metadata validation to lightweight module, add single_f…
Fr4n9 May 28, 2026
9fc5d7f
feat: add LibraryItemSelector component for single_file_rag
Fr4n9 May 28, 2026
53871d1
feat: add library selection state and fetchers for single_file_rag
Fr4n9 May 28, 2026
5bdcb85
feat: wire LibraryItemSelector into assistant form, replacing SingleF…
Fr4n9 May 28, 2026
59eb89e
feat: assistant payload uses library_id+item_id instead of file_path
Fr4n9 May 28, 2026
e2276aa
feat: populate library_id+item_id in edit mode for single_file_rag
Fr4n9 May 28, 2026
74833d5
fix: library items not loading when selecting library in single_file_rag
Fr4n9 May 28, 2026
28e308e
chore: stop tracking changelog (already in .gitignore)
Fr4n9 May 28, 2026
943faa4
chore: fix .gitignore formatting (remove blank line, add final newline)
Fr4n9 May 28, 2026
6fa4963
test: add metadata validation tests for document_rag field
Fr4n9 May 29, 2026
dc60013
feat: metadata_validators validates document_rag field
Fr4n9 May 29, 2026
2ac5773
test: add simple_augment tests for document_context in system prompt
Fr4n9 May 29, 2026
ea6bf49
feat: simple_augment injects document_context into system prompt
Fr4n9 May 29, 2026
41b124c
test: add pipeline integration tests for document_rag
Fr4n9 May 29, 2026
ea429a8
feat: pipeline reads document_rag and passes document_context to PPS
Fr4n9 May 29, 2026
f481093
fix: add env vars to pipeline test for import chain
Fr4n9 May 29, 2026
9f59bab
test: add frontend tests for document_rag submit and state
Fr4n9 May 29, 2026
599c2cf
feat: frontend submit and state support document_rag field
Fr4n9 May 29, 2026
32d2890
feat: add independent Document Reference section, legacy single_file_…
Fr4n9 May 29, 2026
daeee0b
refactor: extract parse_plugin_config and process_completion_request …
Fr4n9 May 29, 2026
da8998d
fix: disable document_rag toggle in edit mode
Fr4n9 May 29, 2026
b043133
fix: remove empty options from LibraryItemSelector dropdowns
Fr4n9 May 29, 2026
1e9b4ff
Merge branch 'projects/refactor/kbserver-lamb-integration' into libra…
Fr4n9 May 31, 2026
deb37fd
fix:assistantform bug from merge
Fr4n9 May 31, 2026
119231a
sintax fix
Fr4n9 May 31, 2026
bbc611f
fix: KB server legacy auth and connectivity + KB server v2 HuggingFac…
Fr4n9 Jun 1, 2026
eb0a9ea
feat: extract shared KS query helpers into _ks_query_helpers.py
Fr4n9 Jun 1, 2026
deeff41
feat: extract shared query rewriting helper into _query_rewriting_hel…
Fr4n9 Jun 1, 2026
1f69aec
refactor: knowledge_store_rag uses shared _ks_query_helpers
Fr4n9 Jun 1, 2026
afc1b2f
refactor: context_aware_rag uses shared _query_rewriting_helper
Fr4n9 Jun 1, 2026
3c63612
feat: add query_rewriting_ks_rag processor with small-fast-model quer…
Fr4n9 Jun 1, 2026
5c7839a
feat: add KS_BASED RAG type classification for knowledge store proces…
Fr4n9 Jun 1, 2026
07faad8
feat: add Knowledge Store state fields to assistant form state
Fr4n9 Jun 1, 2026
b2b0159
feat: add fetchKnowledgeStores to assistant form fetchers
Fr4n9 Jun 1, 2026
7761dce
feat: include Knowledge Store IDs in assistant submission payload
Fr4n9 Jun 1, 2026
c18c2e8
feat: add KnowledgeStoreSelector component for assistant form
Fr4n9 Jun 1, 2026
7be4649
feat: wire KnowledgeStoreSelector into RagOptionsPanel with Top K sup…
Fr4n9 Jun 1, 2026
e0bc7f3
feat: pass Knowledge Store props through ConfigurationPanel
Fr4n9 Jun 1, 2026
1a83b60
feat: wire Knowledge Store fetcher and effects into AssistantForm orc…
Fr4n9 Jun 1, 2026
42b7ea4
feat: add query_rewriting_ks_rag to fallback capabilities and i18n keys
Fr4n9 Jun 1, 2026
e954a44
fix: add missing isKsBasedRag import and fix ConfigurationPanel prop …
Fr4n9 Jun 1, 2026
b5cc2ae
fix: remove remaining _KB_REDIRECTS reference in create_knowledgebase
Fr4n9 Jun 2, 2026
2503456
feat: wrap Document RAG content with descriptive REFERENCE DOCUMENT l…
Fr4n9 Jun 2, 2026
c90addf
feat: rename query_rewriting_ks_rag display to 'Context Aware Rag', h…
Fr4n9 Jun 2, 2026
d707fa3
feat: add missing i18n keys for Document RAG, Knowledge Stores, and s…
Fr4n9 Jun 2, 2026
d5eaa54
feat: translate Knowledge Bases and Knowledge Stores labels to Fuente…
Fr4n9 Jun 2, 2026
9c1b515
Add E2E Playwright test for query_rewriting_ks_rag with dual document…
Fr4n9 Jun 2, 2026
c382020
fix: add recency-bias reminder at end of Document RAG system prompt
Fr4n9 Jun 2, 2026
2e0ad26
refactor: revert simple_augment.py to dev state, remove document_cont…
Fr4n9 Jun 8, 2026
5f4bdd7
refactor: revert single_file_rag.py to dev state, keep only file_path…
Fr4n9 Jun 8, 2026
40964b7
feat: add kvcache_augment PPS with COMPATIBLE_RAG and document_contex…
Fr4n9 Jun 8, 2026
4ee1648
feat: add library_file_rag RAG processor with Library Manager HTTP in…
Fr4n9 Jun 8, 2026
e4bab03
feat: add COMPATIBLE_RAG declaration to simple_augment (legacy PPS)
Fr4n9 Jun 8, 2026
44ea1e1
feat: add COMPATIBLE_RAG validation in load_and_validate_plugins
Fr4n9 Jun 8, 2026
688d4ac
refactor: metadata_validators accepts library_file_rag for document_rag
Fr4n9 Jun 8, 2026
25d83ec
test: adapt document_rag pipeline tests to library_file_rag + kvcache…
Fr4n9 Jun 8, 2026
dcf2933
refactor: frontend sends document_rag=library_file_rag instead of sin…
Fr4n9 Jun 8, 2026
2a4000b
gitignore
Fr4n9 Jun 8, 2026
aed46c8
Merge branch 'library_manager_single_file_rag_integration_context_to_…
Fr4n9 Jun 8, 2026
4cc2a8e
feat: add DEFAULT_RAG_PROMPT_TEMPLATE to kvcache_augment #2
Fr4n9 Jun 8, 2026
148cfe6
feat: add D3 fallback with DEFAULT_RAG_PROMPT_TEMPLATE in kvcache_aug…
Fr4n9 Jun 8, 2026
2c130b9
feat: add labeled_doc wrapper with recency-bias in kvcache_augment #2
Fr4n9 Jun 8, 2026
62011f7
refactor: remove DEFAULT_RAG_PROMPT_TEMPLATE and document_context fro…
Fr4n9 Jun 8, 2026
d4f4390
feat: add PPS_COMPATIBLE_RAG and helpers to ragProcessorHelpers #2
Fr4n9 Jun 8, 2026
7e733df
feat: filter RAG processors by PPS compatibility in ConfigurationPane…
Fr4n9 Jun 8, 2026
e672d2d
fix: replace isHiddenInCreate with isDocumentRag filter in RAG dropdo…
Fr4n9 Jun 8, 2026
4f7be1f
fix: disable prompt processor in edit mode + clean RAG display names #2
Fr4n9 Jun 8, 2026
829ac08
fix: remove unused code
AdriaGuilera Jun 9, 2026
792a739
fix(#408): enforce ownership on assistant update; keep owner immutable
granludo Jun 11, 2026
6a5ea21
fix(#409): validate bearer token on OWI role-update endpoint
granludo Jun 11, 2026
4d81411
fix(#410,#412): validate get_current_user; warn (not fail) on default…
granludo Jun 11, 2026
f68b8cc
fix(#411): randomize OWI mirror-user passwords
granludo Jun 11, 2026
7b9a3b2
fix(#413): require LAMB_API_KEY in legacy KB server; stop advertising…
granludo Jun 11, 2026
6029fa6
fix(#414): fail-fast on unset secrets in docker-compose.next.yaml
granludo Jun 11, 2026
8e1e244
fix(#415): replace weak default admin password / tokens in env example
granludo Jun 11, 2026
4d72150
fix(#416): enforce admin role guard on the admin route
granludo Jun 11, 2026
fc03796
fix(#417): sanitize {@html} rendering of LLM/agent output (XSS)
granludo Jun 11, 2026
b9b7a08
fix(#413): keep backwards-compatible KB token default with warning
granludo Jun 11, 2026
740fb88
fix(#414): restore backwards-compatible compose secret defaults
granludo Jun 11, 2026
5d818e3
fix(#397,#325): add missing LambDatabaseManager methods, fix mismatch…
granludo Jun 11, 2026
b87c8b6
fix(#330): hierarchical_rag reads the KB 'results' key (dual-key fall…
granludo Jun 11, 2026
036544e
fix: add extra_hosts configuration for kb service to enable host access
juananpe Jun 11, 2026
a4836f1
fix: enhance KB server configuration to include embedding model and c…
juananpe Jun 11, 2026
63e1417
fix(#399): unshare now propagates to the OWI group
granludo Jun 11, 2026
9aa7269
fix(#405): self-healing system-admin bootstrap (no more silent failure)
granludo Jun 11, 2026
43e9553
fix(#302): reconcile session across browser tabs
granludo Jun 11, 2026
7a3103c
Merge branch 'dev' into library_manager_and_kv_cache_final_refactor_s…
Fr4n9 Jun 12, 2026
4344732
fix: update context_aware test for kvcache_augment pipeline + remove …
Fr4n9 Jun 12, 2026
04ead67
merge: integrate library_manager + kv-cache refactor work (#334)
NoveliaYuki Jun 14, 2026
19acb3c
fix(completions): simple_augment accepts document_context kwarg
NoveliaYuki Jun 15, 2026
2f26345
fix(sharing): get_group_users calls get_group_by_id on OwiGroupManager
NoveliaYuki Jun 15, 2026
800d261
fix(ui): give ConfirmationModal dialog an accessible name
NoveliaYuki Jun 15, 2026
b44502e
fix(ui): round Modal footer bottom corners
NoveliaYuki Jun 15, 2026
ba81be3
fix(ui): close 'Move to...' picker after a successful move
NoveliaYuki Jun 15, 2026
26790e0
feat(ui): stable testids for RAG-processor select and KS picker options
NoveliaYuki Jun 15, 2026
0fc8338
test(kb-server): run e2e on LM Studio + Qdrant, drop Ollama
NoveliaYuki Jun 15, 2026
7c7abda
chore(firecrawl): use prebuilt ghcr images instead of source build
NoveliaYuki Jun 15, 2026
88962bb
test(playwright): align specs with merged design-system/i18n UI
NoveliaYuki Jun 15, 2026
86d3b35
test(unit): fix pre-existing stale task_routing & rubric_rag tests
NoveliaYuki Jun 15, 2026
cf45a64
fix(knowledge-stores): resolve KS server URL/token from env for a par…
NoveliaYuki Jun 15, 2026
a1ca665
feat: docs
AdriaGuilera Jun 20, 2026
5947e7d
test(kb-server): cover graph schemas and llm_extraction backends #334
AdriaGuilera Jun 20, 2026
ef453c7
test(kb-server): cover concept_extraction service to 99% #334
AdriaGuilera Jun 20, 2026
3dfcdf3
test(kb-server): add neo4j fakes + cover graph_store core read/guard …
AdriaGuilera Jun 20, 2026
b7aa2ef
test(kb-server): cover graph_store get_collection_graph snapshot buil…
AdriaGuilera Jun 20, 2026
5268214
test(kb-server): cover graph_store revert_change paths #334
AdriaGuilera Jun 20, 2026
cf7dcef
test(kb-server): cover graph_store write/curation/ingest/revert paths…
AdriaGuilera Jun 20, 2026
9222255
test(kb-server): cover kg_rag_query plugin (99%) and query_service (1…
AdriaGuilera Jun 20, 2026
2c4cdcf
test(kb-server): cover graph_indexing service to 98% #334
AdriaGuilera Jun 20, 2026
a34db4b
test(kb-server): cover benchmark service to 99% #334
AdriaGuilera Jun 20, 2026
4af26eb
test(kb-server): cover graph + benchmark routers to 100% #334
AdriaGuilera Jun 20, 2026
d1d6274
test(library-manager): cover url_import, markitdown_plus, common sche…
AdriaGuilera Jun 20, 2026
86aec2b
test(library-manager): cover youtube transcript plugin to 97% #334
AdriaGuilera Jun 20, 2026
e7b28c7
test(backend): cover knowledge_store_rag RAG processor to 100% #334
AdriaGuilera Jun 20, 2026
d750fd5
test(backend): cover knowledge_store_graph_router proxy to 100% #334
AdriaGuilera Jun 20, 2026
248971f
test(backend): cover knowledge_store_client to 95% #334
AdriaGuilera Jun 20, 2026
875c4d5
test(backend): close knowledge_store_client gaps to 99% #334
AdriaGuilera Jun 20, 2026
2b3f83f
test(backend): cover knowledge_store_router error/edge branches to 99…
AdriaGuilera Jun 20, 2026
38ee1b7
test(library-manager): cover capabilities router dispatch/404 branche…
AdriaGuilera Jun 20, 2026
4deee19
fix(kb-server): idempotent chromadb delete + deterministic ollama end…
AdriaGuilera Jun 20, 2026
eb8d52f
test(kb-server): cover chromadb_backend lookup/query/iter methods to …
AdriaGuilera Jun 20, 2026
c2d1317
test(kb-server): cover jobs cancel endpoint + content schema validato…
AdriaGuilera Jun 20, 2026
d6286d6
test(kb-server): cover collection_service graph/extraction/chunking b…
AdriaGuilera Jun 20, 2026
caeac56
test(library-manager): drop test for pre-existing common.py (not part…
AdriaGuilera Jun 21, 2026
56521f1
test(backend): cover chunking 5xx wrap + mark shadowed dup route; 100…
AdriaGuilera Jun 21, 2026
9db7bd6
test(kb-server): cover all remaining branch-added lines; 100% diff co…
AdriaGuilera Jun 21, 2026
6f76fec
Feat: language keys
AdriaGuilera Jun 21, 2026
1aa4388
test(library-manager): cover all remaining branch-added lines; 100% d…
AdriaGuilera Jun 21, 2026
ca6b140
refactor: remove dead shadowed route + redundant pydantic validators …
AdriaGuilera Jun 21, 2026
3c8b71d
test(backend): cover all feature-added lines to 100% diff coverage #334
AdriaGuilera Jun 21, 2026
ff6009b
Merge branch 'feature/test-coverage' into feat/kg-rag-new-kbserver-arch
AdriaGuilera Jun 21, 2026
1d82a6c
Merge remote-tracking branch 'upstream/projects/refactor/kbserver-lam…
AdriaGuilera Jun 21, 2026
8c575d5
feat(completions): add opt-in include_eval_metadata to expose retriev…
NoveliaYuki Jun 23, 2026
0f0b290
feat(knowledge-stores): relabel 'Advanced' as 'Vector indexing' and s…
NoveliaYuki Jun 23, 2026
c3103d1
fix(knowledge-stores): use 'index' terminology in the add-content flow
NoveliaYuki Jun 23, 2026
c0f69a0
Merge pull request #426 from Lamb-Project/feat/eval-metadata-rag-context
NoveliaYuki Jun 23, 2026
8f6d81b
Merge pull request #427 from Lamb-Project/feat/ks-vector-indexing-label
NoveliaYuki Jun 23, 2026
5e47f9a
fix(knowledge-stores): say 'newly indexed content' instead of 'ingest…
NoveliaYuki Jun 23, 2026
5401fc2
feat(#430): emit inline [N] citations in Knowledge Store RAG answers
NoveliaYuki Jun 24, 2026
994d4b1
chore(#432): adopt Alembic for KB Server schema migrations
NoveliaYuki Jun 24, 2026
50eb431
chore(#434): adopt Alembic for Library Manager migrations
NoveliaYuki Jun 24, 2026
891d37c
refactor(#436): remove dead artifacts from the legacy Create Knowledg…
NoveliaYuki Jun 24, 2026
b949aa1
fix(#438): localize Create Knowledge wizard and KS UI (es/ca/eu)
NoveliaYuki Jun 24, 2026
9b917c4
feat(#440): implement KS indexing retry with in-memory credential ret…
NoveliaYuki Jun 24, 2026
0d9e669
test(#442): cover knowledge_store_rag _run() retrieval path
NoveliaYuki Jun 24, 2026
ade864a
Merge pull request #431 from Lamb-Project/feat/inline-citations-ks-rag
NoveliaYuki Jun 24, 2026
52d0648
Merge pull request #444 from Lamb-Project/test/knowledge-store-rag
NoveliaYuki Jun 24, 2026
773ed5d
Merge pull request #433 from Lamb-Project/chore/kb-server-alembic
NoveliaYuki Jun 24, 2026
358f189
Merge pull request #435 from Lamb-Project/chore/library-manager-alembic
NoveliaYuki Jun 24, 2026
99f1ed5
Merge pull request #437 from Lamb-Project/refactor/knowledge-wizard-c…
NoveliaYuki Jun 24, 2026
099bcfa
Merge pull request #439 from Lamb-Project/fix/i18n-knowledge-store-wi…
NoveliaYuki Jun 24, 2026
fc07fc5
Merge pull request #441 from Lamb-Project/feat/ks-indexing-retry
NoveliaYuki Jun 24, 2026
beace1b
feat(#445): clickable student citations via signed sources panel
NoveliaYuki Jun 24, 2026
d95c41b
fix(#445): deliver citations as a Markdown Sources section (OWI drops…
NoveliaYuki Jun 24, 2026
68d1a84
feat(#445): make student citation links opt-in per assistant (default…
NoveliaYuki Jun 24, 2026
0a32e49
fix(#445): suppress inline [N] markers too when sources are not exposed
NoveliaYuki Jun 24, 2026
d4f1269
Merge pull request #446 from Lamb-Project/feat/clickable-citation-links
NoveliaYuki Jun 24, 2026
80afe81
test(library-manager): add 3-tier test suite with 95% coverage gate
NoveliaYuki Jun 24, 2026
a394c66
fix(library-manager): dedupe reparented subfolder name before reassig…
NoveliaYuki Jun 24, 2026
42ad958
fix(library-manager): reject non-ASCII bearer tokens with 401 in veri…
NoveliaYuki Jun 24, 2026
70cf7c8
Merge pull request #449 from Lamb-Project/fix/447-delete-folder-repar…
NoveliaYuki Jun 24, 2026
d579c9e
Merge pull request #450 from Lamb-Project/fix/448-verify-token-non-ascii
NoveliaYuki Jun 24, 2026
5b4eae7
test(library-manager): commit YouTube cassettes so the suite runs off…
NoveliaYuki Jun 24, 2026
3f559da
fix(frontend): Libraries "Mine" filter excludes shared items
NoveliaYuki Jun 24, 2026
2de759f
Merge pull request #451 from Lamb-Project/fix/libraries-mine-filter
NoveliaYuki Jun 24, 2026
3710cce
docs(kb-server): correct combined coverage figure to ~94% (#453)
NoveliaYuki Jun 25, 2026
58fbef1
Merge remote-tracking branch 'upstream/integration/kbserver-lamb-dev-…
AdriaGuilera Jun 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
75 changes: 74 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,79 @@
# ============================================================================
# LAMB root Docker Compose environment (docker-compose.yaml)
# ============================================================================
# Copy this file to `.env` in the repository root (next to docker-compose.yaml).
# Docker Compose loads it automatically. Per-service application config still
# lives in backend/.env, lamb-kb-server/backend/.env, etc.

# Absolute path to this checkout on the host. REQUIRED — the dev compose
# bind-mounts it into every container, so it must be correct.
LAMB_PROJECT_PATH=/opt/lamb

# Open WebUI integration
OWI_BASE_URL=http://openwebui:8080
OWI_PUBLIC_BASE_URL=http://localhost:8080
OWI_PATH=/opt/lamb/open-webui/backend/data

# LAMB data + legacy KB server (port 9090)
LAMB_DB_PATH=/opt/lamb
LAMB_KB_SERVER=http://kb:9090
LAMB_KB_SERVER=http://kb:9090

# New KB server (Knowledge Stores, port 9092) — backs the KG-RAG feature.
# The backend reaches it at these values; the token must match the
# LAMB_API_TOKEN the kb-v2 service starts with (compose default: 0p3n-w3bu!).
LAMB_KB_SERVER_V2=http://kb-v2:9092
LAMB_KB_SERVER_V2_TOKEN=0p3n-w3bu!

# Library Manager (port 9091) bearer token — must match on backend + service.
LIBRARY_MANAGER_TOKEN=change-me

# ============================================================================
# KG-RAG / Semantic Graph (optional feature on this branch)
# ============================================================================
# KG-RAG adds a Neo4j-backed semantic graph on top of vector retrieval in the
# new KB server (kb-v2). It is OFF by default and fully isolated: with
# KG_RAG_ENABLED=false the /graph + /benchmarks endpoints are never mounted and
# every existing simple / hierarchical RAG flow behaves exactly as before.
#
# Neo4j only starts under the `kg-rag` compose profile, so the base stack stays
# unchanged unless you explicitly opt in:
#
# docker compose --profile kg-rag up -d
#
# See Documentation/kg-rag-deployment.md for the full walkthrough.

# Master switch. Set to true (and use --profile kg-rag) to enable KG-RAG.
KG_RAG_ENABLED=false

# Run LLM concept extraction + a Neo4j write on every ingestion job. When true,
# single-document ingestion grows from sub-second to several seconds. Set false
# to keep ingestion fast and back-populate the graph later via the migrate API.
KG_RAG_INDEX_ON_INGEST=false

# OpenAI key used for concept/entity extraction. Per-request keys (threaded
# from the LAMB org config) are preferred; this is the ingestion-time fallback.
KG_RAG_OPENAI_API_KEY=

# Models used for graph reasoning and concept extraction.
KG_RAG_CHAT_MODEL=gpt-4o-mini
# Leave empty to fall back to KG_RAG_CHAT_MODEL / gpt-4o-mini.
KG_RAG_EXTRACTION_MODEL=

# Neo4j connection. The neo4j service is created from these values too, so the
# password set here is the password the database is initialised with.
KG_RAG_NEO4J_URI=bolt://neo4j:7687
KG_RAG_NEO4J_USER=neo4j
KG_RAG_NEO4J_PASSWORD=lamb-kg-rag-password

# Graph traversal tuning (clamped server-side: depth 1-4, limit_factor 1-20).
KG_RAG_GRAPH_DEPTH=2
KG_RAG_LIMIT_FACTOR=4
KG_RAG_EXTRACTION_MAX_WORKERS=4

# kb-v2 query-plugin governance (ENABLE | ADVANCED | DISABLE).
PLUGIN_KG_RAG_QUERY=ADVANCED

# Neo4j JVM sizing (optional — raise for larger graphs).
# NEO4J_HEAP_INITIAL_SIZE=512m
# NEO4J_HEAP_MAX_SIZE=1G
# NEO4J_PAGECACHE_SIZE=512m
46 changes: 43 additions & 3 deletions .env.next.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ OWI_PATH=/data/openwebui
OWI_BASE_URL=http://openwebui:8080

# Auth/secrets required by current backend config
LAMB_BEARER_TOKEN=change-me
SIGNUP_SECRET_KEY=change-me
# Set each to a strong, unique, random value (e.g. `openssl rand -hex 32`).
# Do NOT deploy with these placeholders. (#415)
LAMB_BEARER_TOKEN=CHANGE_ME_strong_random_secret
SIGNUP_SECRET_KEY=CHANGE_ME_strong_random_secret

# OpenAI provider required by current backend config
OPENAI_BASE_URL=https://api.openai.com/v1
Expand All @@ -30,7 +32,7 @@ OPENAI_MODEL=gpt-4o-mini
# OpenWebUI bootstrap admin required by current backend config
OWI_ADMIN_NAME=Admin User
OWI_ADMIN_EMAIL=admin@owi.com
OWI_ADMIN_PASSWORD=admin
OWI_ADMIN_PASSWORD=CHANGE_ME_strong_admin_password

# ============================================================================
# OPTIONAL VARIABLES (uncomment to override defaults)
Expand Down Expand Up @@ -108,3 +110,41 @@ OWI_ADMIN_PASSWORD=admin
# CADDY_EMAIL=admin@yourdomain.com
# LAMB_PUBLIC_HOST=lamb.yourdomain.com
# OWI_PUBLIC_HOST=owi.lamb.yourdomain.com

# ============================================================================
# KG-RAG / Semantic Graph (optional)
# ============================================================================
# Enable Graph RAG / KG-RAG in the new KB server. Requires the ``kg-rag``
# Compose profile (starts Neo4j):
# docker compose -f docker-compose.next.yaml --profile kg-rag up -d
#
# When KG_RAG_ENABLED=false (default), graph endpoints are not registered
# and existing simple / hierarchical / parent-child RAG flows are unchanged.
#
# Per-collection opt-in: even with the flag on, a Knowledge Store only
# uses graph features when its ``graph_enabled`` field is true (set in
# create/migrate flow).
#
# OpenAI credentials for concept extraction can be sent per-request
# (preferred) via the X-OpenAI-Api-Key header on /graph endpoints. The
# server-level KG_RAG_OPENAI_API_KEY is a fallback used during ingestion
# when no per-request key has been threaded through.

# KG_RAG_ENABLED=false
# Note on KG_RAG_INDEX_ON_INGEST: when enabled, every ingestion job ALSO
# runs LLM concept extraction (1 OpenAI call per parent text) and a Neo4j
# write. Expect single-document ingestion latency to grow from sub-second
# to multiple seconds. Set to false to keep ingestion fast and run
# `/graph/.../migrate` manually instead.
# KG_RAG_INDEX_ON_INGEST=true
# KG_RAG_OPENAI_API_KEY=
# KG_RAG_CHAT_MODEL=gpt-4o-mini
# KG_RAG_EXTRACTION_MODEL=gpt-5-nano
# KG_RAG_NEO4J_URI=bolt://neo4j:7687
# KG_RAG_NEO4J_USER=neo4j
# KG_RAG_NEO4J_PASSWORD=change-this-password
# KG_RAG_GRAPH_DEPTH=2
# KG_RAG_LIMIT_FACTOR=4
# KG_RAG_EXTRACTION_MAX_WORKERS=4
# Per-request OpenAI timeout for extraction calls. Default 60s.
# KG_RAG_OPENAI_TIMEOUT_SECONDS=60
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,6 @@ docs/
frontend-architecture-diagrams.md
opencode.json
package-lock.json

.playwright-mcp

aac_logs/
Expand All @@ -211,4 +210,7 @@ aac_logs/
# Worktrees
.worktrees/
.agents/
skills-lock.json
skills-lock.json
test-results/
testing/load/document-cache-test/
testing/load/kv-cache-classroom/
12 changes: 7 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,14 @@ pytest -m "not slow" # skip slow tests
# Setup (first time only)
python3 -m venv .venv && source .venv/bin/activate && pip install -e ".[all,dev]"

# Run tests
pytest tests/ -v # all 52 tests
pytest tests/ --cov=backend # with coverage report
# Run tests (3 tiers: unit / integration / e2e — see tests/README.md)
./scripts/run_tests.sh # all tiers + the 95% line+branch coverage gate
pytest tests/unit/ -q # a single tier (unit | integration | e2e)
pytest -m "not slow" -q # skip subprocess/Docker tests
pytest tests/unit/ tests/integration/ --cov=backend --cov-branch --cov-fail-under=95
ruff check backend/ tests/ --select E,F,W,I,UP,SIM --target-version py311 # lint
```
Tests use an in-process ASGI client (no server needed). YouTube transcript test uses a cached response in `tests/.yt_cache/` to avoid rate limits.
Unit tests call modules directly; integration tests use an in-process ASGI client against the real DB + worker; e2e tests hit a `uvicorn` subprocess over real HTTP (plus a Docker smoke test that skips without a daemon). External SDKs (markitdown, Firecrawl, PyMuPDF, OpenAI) are mocked at their import boundary; YouTube uses a cached response in `tests/.yt_cache/`. Combined `backend/` line+branch coverage is enforced at ≥95%.

### Applying backend env changes in Docker
```bash
Expand Down Expand Up @@ -131,7 +133,7 @@ These terms are used consistently throughout the codebase and must not be confus
- Every imported document is stored in a common structured format: `metadata.json` + `source_ref.json` + `original/` + `content/full.md` + `content/pages/` + `content/images/`.
- Five import plugins (simple, markitdown, markitdown_plus, url, youtube), each governed by a tri-state env var (`DISABLE|SIMPLIFIED|ADVANCED`).
- Internal service: no CORS, no published ports, non-root Docker container, single-instance file lock.
- 52 tests, 80% coverage. Full README at `library-manager/README.md`.
- ~710 tests across unit/integration/e2e tiers; ≥95% line+branch coverage gate (currently ~98%). Full README at `library-manager/README.md`; tier contract at `library-manager/tests/README.md`.

**LAMB integration:** Creator Interface endpoints (`/creator/libraries/...`) validate ACL and proxy to the Library Manager. The `lamb-cli` commands (`lamb library ...`) are in `lamb-cli/src/lamb_cli/commands/library.py`. Svelte frontend at `/libraries` route with components in `frontend/svelte-app/src/lib/components/libraries/`.

Expand Down
157 changes: 157 additions & 0 deletions Documentation/kg-rag-deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# KG-RAG / Semantic-Graph Deployment Guide

This guide explains how to bring up the LAMB stack with the **KG-RAG (Knowledge-Graph RAG)** feature enabled — the Neo4j-backed semantic-graph layer that augments vector retrieval in the new KB server.

KG-RAG is **optional and off by default**. With `KG_RAG_ENABLED=false` the graph endpoints are never mounted and every existing RAG flow (simple, hierarchical, single-file, context-aware) behaves exactly as before. You only get the extra services and behaviour when you explicitly opt in as described below.

> Scope: this targets the development `docker-compose.yaml` at the repository root, which is the compose file that wires the new KB server (`kb-v2`, port 9092) and Neo4j. It bind-mounts the checkout into every container and installs dependencies on first start.

---

## What KG-RAG adds to the stack

| Service | Port | Role with KG-RAG | Started by |
|---|---|---|---|
| `kb-v2` (new KB server) | 9092 | Concept extraction, graph write, graph-augmented query | always (base stack) |
| `neo4j` | 7474 (HTTP), 7687 (Bolt) | Semantic graph + curation audit log | **only `--profile kg-rag`** |

`kb-v2` always runs, but it only mounts the `/graph` + `/benchmarks` routers and talks to Neo4j when `KG_RAG_ENABLED=true`. Neo4j itself sits behind the `kg-rag` Compose profile, so the base `docker compose up` never starts it.

---

## Prerequisites

- Docker Engine 24+ and the Docker Compose v2 plugin (`docker compose version`).
- This repository checked out on the **`feat/kg-rag-new-kbserver-arch`** branch.
- An OpenAI-compatible API key if you want concept extraction to actually run (extraction is an LLM call). Without a key the stack still starts; ingestion just skips graph writes / logs an extraction error.
- ~2 GB free RAM for Neo4j (default heap 1 GB + page cache).

---

## Step 1 — Create the root `.env`

From the repository root:

```bash
cp .env.example .env
```

Edit `.env` and set, at minimum:

```bash
# REQUIRED — absolute path to THIS checkout on the host
LAMB_PROJECT_PATH=/absolute/path/to/lamb

# Turn the feature on
KG_RAG_ENABLED=true

# Pick a Neo4j password (this initialises the database on first boot)
KG_RAG_NEO4J_PASSWORD=lamb-kg-rag-password

# Key used for concept extraction at ingest time (optional but recommended)
KG_RAG_OPENAI_API_KEY=sk-...
```

Everything else has working defaults (see the comments in `.env.example`). The KG-RAG block controls graph behaviour:

| Variable | Default | Meaning |
|---|---|---|
| `KG_RAG_ENABLED` | `false` | Master switch. Must be `true` for any graph behaviour. |
| `KG_RAG_INDEX_ON_INGEST` | `false` | If `true`, run extraction + graph write on every ingestion job (slower). If `false`, ingest fast and back-populate later via the migrate API. |
| `KG_RAG_OPENAI_API_KEY` | empty | Fallback key for extraction (per-request keys from LAMB are preferred). |
| `KG_RAG_CHAT_MODEL` | `gpt-4o-mini` | Model for graph reasoning. |
| `KG_RAG_EXTRACTION_MODEL` | empty → chat model | Model for concept/entity extraction. |
| `KG_RAG_NEO4J_URI` | `bolt://neo4j:7687` | Neo4j Bolt URI (service name inside the compose network). |
| `KG_RAG_NEO4J_USER` / `KG_RAG_NEO4J_PASSWORD` | `neo4j` / `lamb-kg-rag-password` | Neo4j credentials; the DB is initialised with these. |
| `KG_RAG_GRAPH_DEPTH` | `2` | Graph traversal depth (clamped 1–4). `.env.example` ships `2`; note the kb-v2 service's bare compose fallback is `1`, so keep this line set rather than deleting it. |
| `KG_RAG_LIMIT_FACTOR` | `4` | Candidate-expansion factor (clamped 1–20). |

The same file also sets `LAMB_KB_SERVER_V2_TOKEN` and `LIBRARY_MANAGER_TOKEN`; leave the defaults unless you change them on the services too.

## Step 2 — Create `backend/.env`

The backend container loads `backend/.env` directly (`env_file:`), so it must exist. From the **repository root**:

```bash
cp backend/.env.example backend/.env
```

Set a real `OPENAI_API_KEY` (and any other provider keys) inside `backend/.env`. No KG-RAG-specific edits are needed here — the backend learns the new KB server address from `LAMB_KB_SERVER_V2` / `LAMB_KB_SERVER_V2_TOKEN`, which the compose file injects from the root `.env`.

> You do **not** need to create a `.env` for the KB servers by hand. `kb-v2` (the KG-RAG server) takes all of its config from the compose `environment:` block — it never reads a `.env` file. The legacy `kb` service auto-creates `lamb-kb-server-stable/backend/.env` from its `.env.example` on first start. Either way, the KG-RAG settings come from compose environment variables sourced from the root `.env`.

## Step 3 — Start the stack with the `kg-rag` profile

```bash
docker compose --profile kg-rag up -d
```

The `--profile kg-rag` flag is what adds the `neo4j` service. Without it, `kb-v2` starts but has no graph database to talk to.

> This assumes a clean host: ports 9099, 9092, 9090, 9091, 8080, 5173, 7474 and 7687 must be free. If a LAMB stack is already running, `up` will fail on a port conflict — bring the existing one down first (`docker compose --profile kg-rag down`) or start the new one with a distinct `COMPOSE_PROJECT_NAME` and remapped ports.

First boot is slow: the containers `pip install` / `npm build` against the bind-mounted source. Watch progress with:

```bash
docker compose --profile kg-rag ps
docker compose logs -f kb-v2
```

You can also bring up just the feature-critical services to validate KG-RAG quickly without building the frontend/OpenWebUI:

```bash
docker compose --profile kg-rag up -d neo4j kb-v2
```

## Step 4 — Verify KG-RAG is live

1. **Neo4j is healthy:**
```bash
docker compose ps neo4j # STATUS shows "healthy" (ps lists running containers; no profile flag needed)
```
The Neo4j browser is at <http://localhost:7474> (log in with `KG_RAG_NEO4J_USER` / `KG_RAG_NEO4J_PASSWORD`).

2. **kb-v2 mounted the graph routers** — the startup log prints this line only when the feature is on:
```bash
docker compose logs kb-v2 | grep "KG-RAG enabled"
# → KG-RAG enabled: mounted /graph and /benchmarks routers
```

3. **kb-v2 is healthy and the graph surface exists:**
```bash
curl -s http://localhost:9092/health # {"status":"ok",...}
curl -s http://localhost:9092/openapi.json | grep -o '"/graph[^"]*"' | head
# → graph paths appear ONLY when KG_RAG_ENABLED=true
```
With the feature off, `/graph` paths are absent from the OpenAPI spec (callers get a clean 404).

## Step 5 — Use it from LAMB

1. Open the frontend at <http://localhost:9099> (or the Svelte dev server at <http://localhost:5173>).
2. Create a **Knowledge Store** via the "Create Knowledge" wizard. In the Setup step, enable the **graph / `graph_enabled`** toggle and pick the extraction vendor/model. This per-store opt-in is required *in addition* to `KG_RAG_ENABLED` — the flag enables the capability, the toggle enables it for that store. Store setup is locked after creation.
3. Link Library items into the store to ingest them. If `KG_RAG_INDEX_ON_INGEST=true`, concepts are extracted and written to Neo4j during ingestion; otherwise run the migrate/back-populate action from the store's graph view.
4. Inspect and curate the graph in the store's **Graph** view (Sigma.js): approve/reject/rename/merge concepts; every edit is recorded as an audit `ChangeEvent`.
5. Attach the store to an assistant whose RAG processor is `knowledge_store_rag` to use graph-augmented retrieval at query time.

## Turning KG-RAG off again

```bash
docker compose --profile kg-rag down # stop everything incl. Neo4j
```

Set `KG_RAG_ENABLED=false` in `.env` and start normally (`docker compose up -d`, no profile). The graph routers disappear, Neo4j is not started, and all vector RAG flows continue unchanged. Neo4j data persists in the `neo4j-data` volume for next time.

---

## Troubleshooting

| Symptom | Cause / fix |
|---|---|
| `kb-v2` log has no "KG-RAG enabled" line | `KG_RAG_ENABLED` not `true` in `.env`, or container not recreated — run `docker compose up -d --force-recreate kb-v2`. |
| `/graph` calls return 404 | Feature flag off, or you hit the legacy `kb` (9090) instead of `kb-v2` (9092). |
| kb-v2 logs Neo4j connection errors | Neo4j not started (missing `--profile kg-rag`), wrong `KG_RAG_NEO4J_URI`, or password mismatch. Confirm `docker compose ps neo4j` is healthy. |
| Ingestion is suddenly slow | `KG_RAG_INDEX_ON_INGEST=true` runs an LLM call per parent text. Set it `false` and back-populate via the migrate API. |
| Extraction silently does nothing | No OpenAI key reached the server — set `KG_RAG_OPENAI_API_KEY` or thread a per-request key from the LAMB org config. |
| `.env` changes not picked up | Compose only re-reads env on container (re)create: `docker compose up -d --force-recreate <service>` (a plain `restart` is not enough). |

See `lamb-kb-server/Documentation/` for the architecture decision records (ADR-KS-1…17) behind this design.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ For development or custom deployments:

📘 **[Complete Installation Guide](Documentation/installationguide.md)** - Step-by-step manual setup for all components

### Optional: KG-RAG (Semantic Graph)

To bring up the stack with the Neo4j-backed Knowledge-Graph RAG feature enabled:

📘 **[KG-RAG Deployment Guide](Documentation/kg-rag-deployment.md)** - Enable graph-augmented retrieval with the `kg-rag` Compose profile

### Quick Overview

LAMB requires four main services:
Expand Down
6 changes: 6 additions & 0 deletions backend/.coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[report]
exclude_lines =
pragma: no cover
if TYPE_CHECKING:
raise NotImplementedError
if __name__ == .__main__.:
7 changes: 7 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ LAMB_BACKEND_HOST=http://backend:9099
#PIPELINES_BEARER_TOKEN=0p3n-w3bu!
LAMB_BEARER_TOKEN=0p3n-w3bu!

# Secret used to HMAC-sign the public citation permalinks students click from
# chat. Per-org keys are derived from it, so rotating it revokes every signed
# link at once. MUST stay stable across restarts (changing it breaks links in
# existing chats). Defaults to LAMB_BEARER_TOKEN if unset; set a dedicated
# value in production.
#LAMB_PERMALINK_SIGNING_SECRET=change-me-to-a-long-random-string


# Signup Configuration
SIGNUP_ENABLED=true
Expand Down
Loading