单容器 Docker 架构的国土空间规划课程智能问答系统,集成 FastAPI 后端与 Next.js 前端。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
国土空间规划课程智能体 (Territorial Spatial Planning Course Agent) — an AI-powered Q&A system for a territorial spatial planning course. Single-container Docker deployment with supervisor managing a FastAPI backend and Next.js frontend.
Development Commands
Local Development
Backend (from project root):
cd backend
uv sync # install Python deps (requires uv >= 0.6.15, Python >= 3.12)
uv run main.py # start backend on :8000
Frontend (separate terminal):
cd web
pnpm install # install Node deps (pnpm 10.6.5)
pnpm dev # start Next.js on :8001 with Turbopack
pnpm build # production build
pnpm check # lint + typecheck
pnpm lint:fix # auto-fix lint issues
Docker
docker-compose up -d # build & start all services
docker-compose logs -f app # follow logs
docker-compose exec app bash # shell into container
docker-compose exec db psql -U user -d course_agent_db # database shell
Ports: backend API :8000, frontend :8001, PostgreSQL :5433 (mapped from container's 5432).
Environment Setup
Copy env.example to .env and configure. Critical variables:
SILICONFLOW_API_KEY— LLM provider API keyDATABASE_URL—sqlite:///...for local dev,postgresql+psycopg://...for DockerSECRET_KEY— JWT signing key
Architecture
Backend (backend/src/)
api/ FastAPI routers: auth, chat, document, image, knowledge_base,
course_content, forum, analytics
core/ config.py (pydantic-settings), database.py (SQLAlchemy, lazy engine),
security.py (JWT)
llm/ siliconflow.py — ChatOpenAI wrapper over SiliconFlow API
rag/ The RAG pipeline:
embeddings.py → SentenceTransformer (text2vec-base-chinese)
vector_store.py → Chroma singleton (langchain-chroma)
retrievers.py → KnowledgeBaseRetriever (BaseRetriever subclass,
filters by knowledge_base_id, distance→score conversion)
chains.py → RAGChain (LangChain Runnable API, supports
invoke/ainvoke/astream/astream_with_sources)
conversation_chains.py → non-RAG conversation chain
prompts.py → prompt templates
graph/ LangGraph workflow: qa_graph.py defines a linear pipeline
analyze → retrieve → generate → format
(nodes.py has the node implementations)
models/ SQLAlchemy ORM: User, ChatSession, ChatMessage, Document,
DocumentChunk, KnowledgeBase, Book/Chapter/Section/Subsection,
ForumCategory/Post/Reply, GeneratedImage, CourseModule
services/ Business logic: auth, document processing, knowledge base management,
LaTeX parser, file watcher, image generation (text-to-image, image-to-image)
migrations/ Database migration scripts
Frontend (web/src/)
Next.js 15 App Router + React 19 + TypeScript + TailwindCSS + shadcn/ui.
app/
(auth)/ login, register pages
(main)/ chat, knowledge, course-content, forum, analytics,
spatial (text-to-image, image-to-image), profile, settings
components/
chat/ chat-interface, message-list, sidebar, knowledge-selector,
model-selector, mode-selector, source-references
course-content/ knowledge-graph, node-detail-dialog
home/ landing page sections
ui/ shadcn/ui primitives
store/
auth.ts Zustand auth store
chat.ts Zustand chat store (session management, streaming SSE handling)
lib/
api.ts All API client functions (auth, chat, image, knowledgeBase,
document, forum, analytics, courseContent, book)
auth.ts NextAuth config
types/index.ts TypeScript type definitions
Key Data Flows
Chat modes:
normal— ConversationChain (LLM only, with chat history)rag— RAGChain: embed query → Chroma similarity search (filtered byknowledge_base_ids) → LLM answer generation
Streaming: Backend sends SSE events (data: {type: "thinking"|"chunk"|"sources"|"done", ...}). Frontend's Zustand store accumulates chunks via requestAnimationFrame updates.
Knowledge base pipeline: Upload PDF/DOCX/TXT/MD → document_service extracts text → text_splitters chunks → embeddings → stored in Chroma with knowledge_base_id metadata for filtering.
LLM integration: All LLM calls go through SiliconFlowLLM which wraps ChatOpenAI pointed at SiliconFlow API (https://api.siliconflow.cn/v1). Default model is configurable via SILICONFLOW_MODEL env var. Supports model selection per-request via model parameter.
Database
SQLAlchemy ORM with dual support:
- SQLite — local development default
- PostgreSQL — Docker deployment (lazy engine initialization with retry for DNS resolution)
Engine creation is deferred (lazy) to handle Docker startup ordering — the engine connects only on first actual use, with 10 retries.
Docker Deployment
Multi-stage Dockerfile: (1) builds Next.js frontend, (2) installs Python deps via uv, (3) final slim image with Node.js + supervisor. supervisord manages both uvicorn (backend) and next start (frontend) in a single container.
Persistent volumes: ./data, ./runtime (contains vector_store, logs, generated_images).
Code Conventions
- Backend Python code uses Chinese docstrings and log messages; variable/function names in English
- Ruff for Python linting (line-length 88, target Python 3.12)
- Frontend uses pnpm (not npm/yarn), ESLint + Prettier with Tailwind plugin
- API responses are JSON; streaming uses SSE (
text/plainwithdata: {...}\n\nlines) - All API endpoints require JWT auth except login/register; tokens stored in
localStorageasauth_token - Embedding model downloads go through
HF_ENDPOINT=https://hf-mirror.com(China mirror)