Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@ ADMIN_PASSWORD=admin123
DB_PATH=./data/customer-service.db
DOCUMENT_UPLOAD_DIR=./data/uploads

# Optional local PaddleOCR/PP-StructureV3 worker. Existing FAQ/text document
# features keep working when this is empty.
OCR_SERVICE_URL=
OCR_SERVICE_TOKEN=
OCR_ENGINE_VERSION=3.0.3
OCR_TIMEOUT_MS=120000
OCR_BACKGROUND_ENABLED=true
OCR_POLL_INTERVAL_MS=1000

# Optional comparison-only worker. Its output never creates review drafts or
# replaces PaddleOCR authoritative content.
OCR_SHADOW_SERVICE_URL=
OCR_SHADOW_SERVICE_TOKEN=
OCR_SHADOW_ENGINE_VERSION=2.0.0

# CORS
ALLOWED_ORIGINS=http://localhost:5173

Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ jobs:
node-version: 20
cache: npm

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.10"

- name: Run OCR worker contract tests
run: (cd ocr-worker && python -m unittest discover -s tests)

- name: Install dependencies
run: npm ci

Expand All @@ -34,6 +42,7 @@ jobs:
EMBED_PROVIDER=other npm run eval:document
EMBED_PROVIDER=other npm run eval:mixed
EMBED_PROVIDER=other npm run eval:quality
EMBED_PROVIDER=other npm run eval:ocr
env:
JWT_SECRET: test-secret-123

Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ data/
.DS_Store
*.log
npm-debug.log*
__pycache__/
*.py[cod]
.playwright-cli/
.npm-cache/
playwright-report/
Expand Down
45 changes: 34 additions & 11 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ fields are optional in the final `done` event.
## Knowledge Ingestion And Consistency

FAQ writes and document ingestion update both durable rows and the process
index through application services. Document uploads run synchronously through
the fixed, versioned pipeline:
index through application services. Text document uploads run synchronously
through the fixed, versioned pipeline:

```text
validate → parse → normalize → clean → quality_gate → chunk → embed → publish
Expand All @@ -110,8 +110,23 @@ representations, safe Block payloads, processing tasks, and per-stage counts
are stored additively in SQLite. The original uploaded file remains source
truth and its binary content is not duplicated in the representation tables.

PNG, JPEG, WebP, and scan-only PDF sources take a separate reviewed OCR path:

```text
validate/store → queue authoritative Paddle job → extract → immutable result
→ revisioned review draft → validate/clean/quality/chunk/embed → atomic publish
└→ optional DeepSeek shadow job → comparison only
```

Extraction jobs, retry relationships, engine versions, safe errors, timestamps,
and immutable results are additive SQLite records. A single-process scheduler
recovers interrupted `running` jobs to `queued`, claims one job transactionally,
and executes through the project-owned HTTP contract. PaddleOCR PP-StructureV3
is authoritative; optional DeepSeek-OCR-2 output is stored separately and
cannot create or overwrite the review draft.

Chunks retain source Block ids, heading path, page range, representation
version, and chunker version. Embeddings include title and section metadata and
version, chunker version, extraction job, and OCR engine/version. Embeddings include title and section metadata and
carry a profile derived from the active provider, model, endpoint, and input
schema, while user-visible excerpts preserve source text.

Expand All @@ -135,6 +150,12 @@ aligned.
APIs expose configured status, never key material.
- Upload APIs enforce type and resource limits and do not return storage paths,
hashes, embeddings, or parser exceptions.
- OCR sources are checked against extension, MIME type, binary signature,
request size, and SHA-256 at both the API and worker boundaries. Worker
responses are schema-validated and bounded before persistence.
- OCR output remains untrusted and non-searchable until an administrator
publishes the complete validated draft. Shadow output has no publication
authority.
- The model has no business-operation tools. Deterministic rules recognize
common private order, logistics, account, address, cancellation, and refund
action requests, then refuse and route them to human support.
Expand Down Expand Up @@ -169,7 +190,8 @@ New infrastructure should follow measurements, not portfolio optics:

| Signal | Likely evolution |
| --- | --- |
| Upload parsing or embedding causes visible request latency/timeouts | Move ingestion behind a durable job boundary and idempotent worker |
| Text parsing or embedding causes visible request latency/timeouts | Extend the proven OCR job boundary to other fixed ingestion stages |
| OCR throughput or multiple replicas exceed single-process polling | Introduce a distributed claim/lease queue without changing the extraction contract |
| Index rebuild time or memory materially affects startup/availability | Add a persistent vector adapter and asynchronous index lifecycle |
| Multiple API replicas are required | Externalize process-local index/config/rate-limit state and define cache invalidation |
| SQLite write contention, backup, or tenant isolation becomes limiting | Introduce explicit migrations and a server database |
Expand All @@ -183,13 +205,14 @@ switch today.
## Known Limits

- One deployment-wide knowledge base; no tenant isolation or fine-grained RBAC.
- Document parsing and embedding remain inside the API request process.
- Scan-only PDFs and image-only DOCX files are identified but not interpreted;
OCR, VLM extraction, web ingestion, and source-file version history are not
implemented.
- Processing is synchronous with explicit retry/reprocess only. Durable
background recovery, schedules, and manual review approval remain future
work.
- Text-document parsing and embedding remain inside the API request process.
- OCR scheduling is durable but deployment-local: one application process polls
SQLite, and there is no distributed lease coordination across replicas.
- PNG/JPEG/WebP and scan-only PDFs can be reviewed through OCR. Image-only DOCX,
free-form VLM extraction, multimodal embeddings, web ingestion, and
source-file version history are not implemented.
- The local Paddle worker has a heavy first-start model download and should be
isolated on a trusted private network.
- Conflict detection is intentionally narrow: it detects duplicate normalized
direct-FAQ questions with different answers, not arbitrary contradictions
across prose documents.
Expand Down
55 changes: 39 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

**Chinese version**: [README_CN.md](README_CN.md)

Development version: **v0.3.0 (pre-1.0)**. The latest published release is
v0.2.9; APIs and persisted data remain subject to change before 1.0.
Development version: **v0.3.1 (pre-1.0)**. The latest published release is
v0.3.1; APIs and persisted data remain subject to change before 1.0.

<p align="center">
<a href="https://github.com/Rcloudso/smart-customer-service-ai/releases/download/v0.2.6/smart-customer-service-v0.2.6-demo.mp4">
Expand All @@ -27,7 +27,7 @@ v0.2.9; APIs and persisted data remain subject to change before 1.0.
<p align="center">
<a href="https://github.com/Rcloudso/smart-customer-service-ai/releases/download/v0.2.6/smart-customer-service-v0.2.6-demo.mp4">Watch the document RAG demo (v0.2.6)</a>
· <a href="docs/case-studies/ai-assisted-development-v0.2.6.md">AI-assisted development case study</a>
· <a href="docs/releases/v0.3.0.md">v0.3.0 release notes</a>
· <a href="docs/releases/v0.3.1.md">v0.3.1 release notes</a>
· <a href="docs/releases/v0.2.9-evidence.md">v0.2.9 release evidence</a>
</p>

Expand Down Expand Up @@ -104,9 +104,9 @@ into one accountable customer-resolution flow.
bounded Agentic Retrieval are planned as separately testable releases rather
than one framework rewrite.

| Implemented on v0.3.0 branch | Next — v0.3.1+ |
| Implemented on v0.3.1 branch | Next — v0.3.2+ |
| --- | --- |
| Versioned structure-aware ingestion plus the v0.2.9 FAQ/RAG, Quality Lab and structured escalation baseline | OCR/image knowledge, optional Qdrant, retrieval traces, bounded Agentic Retrieval, then mock-first business tools |
| Versioned structure-aware ingestion, durable PaddleOCR review workflow, optional DeepSeek shadow comparison, and the v0.2.9 FAQ/RAG baseline | Optional Qdrant, retrieval traces, bounded Agentic Retrieval, then mock-first business tools |

See [ROADMAP.md](ROADMAP.md) for release boundaries and non-goals.

Expand All @@ -129,6 +129,7 @@ flowchart LR
- **Admin console** - FAQ management, conversation list, dashboard analytics, and runtime model configuration.
- **Knowledge gap feedback loop** - no-match, low-score, and negatively rated answers become review items that admins can edit, dismiss, or convert into indexed FAQs.
- **Structure-aware document ingestion** - upload TXT, Markdown, text-layer PDF, and DOCX files into a versioned `DocumentIR`; preserve headings, paragraphs, lists, tables, page and block provenance; inspect quality and processing stages; then publish structure-aware chunks atomically.
- **Reviewed OCR ingestion** - route PNG, JPEG, WebP, and scan-only PDF sources to a durable PaddleOCR PP-StructureV3 queue; inspect and edit extracted Blocks before atomic publication, with optional non-authoritative DeepSeek-OCR-2 shadow comparison.
- **Hybrid multi-source retrieval** - FAQ and document candidates use per-source vector recall plus field-aware keyword recall, then merge with score-aware reciprocal-rank fusion (RRF), deduplicate, and apply source-aware diversity.
- **Compatible intent classification** - structured intent output negotiates `json_schema`, then `json_object`, then validated plain-text JSON before the deterministic keyword fallback.
- **Open vector-store interface** - `VectorStore` keeps the default deployment simple while leaving room for Qdrant or pgvector later.
Expand Down Expand Up @@ -232,6 +233,16 @@ Docker exposes:

The compose example uses `EMBED_PROVIDER=other`, so the project can start without paid model keys. The deterministic local path supports FAQ and document retrieval; document answers fall back to the highest-ranked source excerpt instead of inventing a summary.

Start the optional CPU OCR worker with the Compose profile:

```bash
OCR_SERVICE_URL=http://ocr-worker:8001 docker compose --profile ocr up --build
```

The first worker start downloads Paddle models. See
[ocr-worker/README.md](ocr-worker/README.md) for the local Python path, worker
contract, and Paddle installation references.

Compose uses the `resolve-weave` project name and builds the local image as
`resolve-weave:local`. New installations store data in the
`resolve-weave-data` volume. Existing Docker users should identify the previous
Expand All @@ -256,6 +267,11 @@ Copy `.env.example` to `.env`, then configure the values you need:
| `LLM_API_BASE` / `LLM_API_KEY` / `LLM_MODEL` | Chat model endpoint, environment-only credential, and model |
| `EMBED_API_BASE` / `EMBED_API_KEY` / `EMBED_MODEL` | OpenAI-compatible embedding model |
| `DOCUMENT_UPLOAD_DIR` | Private document file directory; defaults to `./data/uploads` |
| `OCR_SERVICE_URL` | Optional PaddleOCR/PP-StructureV3 worker base URL; when empty, existing FAQ and text-document features still work |
| `OCR_SERVICE_TOKEN` | Optional bearer token sent only to the configured OCR worker |
| `OCR_ENGINE_VERSION` / `OCR_TIMEOUT_MS` | Required worker version match and request timeout; defaults to `3.0.3` / `120000` ms |
| `OCR_BACKGROUND_ENABLED` / `OCR_POLL_INTERVAL_MS` | Durable SQLite queue polling; defaults to `true` / `1000` ms |
| `OCR_SHADOW_SERVICE_URL` / `OCR_SHADOW_SERVICE_TOKEN` / `OCR_SHADOW_ENGINE_VERSION` | Optional comparison-only DeepSeek-OCR-2-compatible worker; never replaces Paddle review content |
| `RATE_LIMIT_CHAT` / `RATE_LIMIT_ADMIN` / `RATE_LIMIT_LOGIN` | API rate limits |
| `SESSION_INACTIVITY_MINUTES` | Minutes without activity before an active conversation is closed; defaults to `30` |
| `CONVERSATION_EXPORT_MAX_MESSAGES` | Maximum complete message rows in one synchronous filtered CSV export; defaults to `5000` |
Expand All @@ -273,18 +289,20 @@ EMBED_PROVIDER=other npm run eval:faq
EMBED_PROVIDER=other npm run eval:document
EMBED_PROVIDER=other npm run eval:mixed
EMBED_PROVIDER=other npm run eval:quality
EMBED_PROVIDER=other npm run eval:ocr
npm run eval:triage
```

The reports include FAQ Top1/Top3/no-match metrics, a 12-case document benchmark across TXT, Markdown, PDF, and DOCX, and deterministic triage coverage for bilingual security, complaint, refund, order, technical, explicit-human, knowledge-conflict, private-operation, and prompt-injection cases. The document report compares `semantic-v1` with a structure-only baseline and requires 100% Top3 recall without MRR regression.
The reports include FAQ Top1/Top3/no-match metrics, a 12-case document benchmark across TXT, Markdown, PDF, and DOCX, a six-case OCR contract benchmark covering screenshots, scan PDFs, tables, rotation/noise and low-quality gating, and deterministic triage coverage. The document report compares `semantic-v1` with a structure-only baseline and requires 100% Top3 recall without MRR regression.

Document management is available at **Admin Console → Documents**. The detail
dialog exposes quality/index status, structure metrics, warnings, a paginated
Block inspector, the eight processing stages, and published chunks. Uploads are
limited to 10 MB, extracted text to 200,000 characters, `DocumentIR` to 2 MiB
and 2,000 Blocks, and final chunks to 300. Exact duplicate content is rejected
by SHA-256; storage paths, hashes, embeddings, and parser exceptions are not
returned by the API.
returned by the API. OCR documents also expose queue/retry history, engine
versions, optional shadow agreement, and reviewed Block provenance.

The FAQ report includes:

Expand Down Expand Up @@ -317,6 +335,7 @@ EMBED_PROVIDER=other npm run eval:faq
EMBED_PROVIDER=other npm run eval:document
EMBED_PROVIDER=other npm run eval:mixed
EMBED_PROVIDER=other npm run eval:quality
EMBED_PROVIDER=other npm run eval:ocr
npm run eval:triage
PLAYWRIGHT_CHANNEL=chromium npm run test:e2e
EMBED_PROVIDER=other npm run build
Expand All @@ -331,7 +350,8 @@ GitHub Actions runs `npm ci`, regression tests, Playwright E2E, and production b
```text
client/ React + Vite frontend
server/ Express API, services, AI adapters, SQLite repositories
eval/ FAQ and document retrieval evaluation cases
ocr-worker/ Optional FastAPI PaddleOCR PP-StructureV3 CPU worker
eval/ FAQ, document, quality, and OCR evaluation cases
tests/e2e/ Playwright end-to-end tests
ARCHITECTURE.md Runtime topology, trust boundaries, and scaling triggers
data/ Local SQLite database files
Expand All @@ -343,14 +363,17 @@ data/ Local SQLite database files

- The default vector index is process-local memory and scans FAQ plus document-chunk embeddings, so it is suitable for demos and small knowledge collections.
- Embeddings are stored as JSON in SQLite, not in a dedicated vector database.
- Document parsing remains synchronous inside the Express process. Encrypted
and damaged files are rejected; scan-only PDFs and image-only DOCX files are
marked for review and are not indexed. OCR, VLM extraction, web ingestion,
citation links, and page jumps are not included.
- v0.3.0 stores structured representations and processing history but keeps the
original file as source truth. It has explicit retry/reprocess only—no
background worker, scheduler, or manual force-publish flow.
- Document files remain global to the deployment; v0.3.0 does not add
- Text-document parsing remains synchronous inside the Express process.
Encrypted and damaged files are rejected. PNG, JPEG, WebP, and scan-only PDF
sources use an optional external PaddleOCR worker through a durable SQLite
queue. Review drafts are never indexed until an administrator publishes the
complete document.
- The scheduler is deliberately single-process and polls SQLite; it is not a
distributed multi-replica queue. The Paddle worker downloads large models on
first start and should remain on a trusted private network.
- OCR extracts text and table structure only. VLM descriptions, raw-image
answering, web ingestion, citation links, and page jumps are not included.
- Document files remain global to the deployment; v0.3.1 does not add
tenant-separated knowledge bases or external vector storage.
- `VectorStore` isolates local vector operations, but a network vector database still requires asynchronous contracts, health handling, and consistency tests.
- Conflict detection is deliberately narrow: duplicate normalized direct-FAQ questions with different answers. Grounding thresholds are governed through the versioned Quality Lab rather than changed automatically.
Expand Down
Loading
Loading