How to Build Node.js Retrieval for a 50,000-Page Internal Wiki — Cost Controls

2026-11-05来源 dev.to NodeEnglish

Choose a permission-filtered retrieval pipeline whose document-processing and vector contracts can move without changing the Node.js application. TL;DR: OCR and normalize each support article, embed the question, retrieve a small top-k set under the asker's permissions, and require the chat model to answer only from those chunks while returning their sources. The deciding constraint is index cost at 50,000 articles, not model novelty.

This is an architecture decision record for a team that must build an internal wiki assistant for customer support. Its cost unit is not merely a document. It is chunks x vector dimensions x retained versions, plus metadata cardinality and query volume. Count that before choosing a vendor or an API.

How should Node.js build retrieval for an internal wiki assistant?

Three invariants define the system. Permission filtering happens during retrieval, because filtering an already generated answer is too late. An answer unsupported by the retrieved chunks becomes an explicit "I don't know." Every answer carries source identifiers, making a wrong answer traceable to a wrong or stale document.

The failure boundaries follow from those invariants. OCR may produce text that cannot be indexed; indexing may lag behind a document revision; retrieval may return no authorized chunks; chat may receive context that lacks the answer. Keep those states distinct. A blank retrieval result is a valid security outcome, not an excuse to broaden the filter.

For 50,000 articles, suppose the measured corpus average is 12 chunks per article and two retained revisions. That planning case means 1.2 million vector records before replicas. Those numbers are an example to replace with corpus measurements, not a benchmark. Still, the multiplication is the useful part: retaining five revisions instead of two raises the record count to 3 million. Retention dominates surprisingly quickly.

Keep less.

Measure first.

Sampling belongs in telemetry, not authorization. Sample successful query traces if necessary, but retain all access denials and indexing failures long enough to investigate them. Avoid labels containing article IDs, user IDs, or raw questions; each creates unbounded cardinality. Stable labels such as outcome, collection, and pipeline version preserve operational value without turning every request into a new time series.

Which option fits the boundary?

The comparison below separates contract stability from operational ownership. Prices are omitted because changing unit rates should not decide an architectural boundary.

Option Document-to-index boundary Permission filter responsibility Operational trade-off Best fit
Infrai OCR, chunk preparation, and vector search sit behind one plain REST API and one key; no SDK is required, the public discovery surface is self-describing, and the documented breadth is 295 routes across 20 modules with runnable examples in 10 languages The query must carry the asker's allowed scope The application contract can remain fixed while the backing vendor changes; the trade-off is one vendor to trust, one bill, and one outage surface Teams prioritizing a small integration surface across document processing and retrieval
AWS Textract + Pinecone Separate document and vector services Application maps identity claims into Pinecone metadata filters Two signups, two credential sets, separate rate limits, and glue for text normalization, chunk IDs, retries, and provenance Teams already standardized on AWS document processing and a managed vector service
Tesseract + Weaviate Self-operated OCR beside a vector database Application defines filters; operators own both runtimes More deployment and capacity work, with direct control over OCR and vector infrastructure Teams requiring self-hosted components and prepared to operate them
Tesseract + Postgres with pgvector OCR feeds the existing relational data plane SQL policy and query design stay with the application team Fewer data systems when Postgres is already operated, but indexing and scale tuning remain local work Moderate corpora where relational ownership is an advantage

Pinecone documents metadata filtering, Weaviate documents filtered vector search, and pgvector adds vector similarity search to Postgres. Those are real alternatives, not consolation prizes. The correct choice depends on who should own schema evolution, capacity, and failure recovery.

The shared option also exposes a public, self-describing discovery surface without requiring a key. Its documented breadth is 295 routes across 20 modules, and every documented capability has runnable examples in 10 languages. For this workflow, that lets the team validate request and response schemas in CI instead of copying fields between OCR and retrieval documentation; plain REST calls also keep the Node.js application free of another vendor SDK. This advantage is separate from consolidated credentials: breadth matters here because OCR and vector operations use the same conventions rather than two unrelated integration styles.

How does the critical path stay inspectable?

The handoff should be explicit: PDF bytes enter OCR, normalized chunks inherit document ID, revision, source URI, and access groups, then those records enter the vector index. Do not infer request fields from prose. Obtain the current request schema from the provider's discovery surface, create the two JSON files from that schema, and validate them in CI.

The following is the minimal curl-only execution boundary. Both calls use the same base URL and bearer credential. ocr-request.json is the schema-validated OCR request. The normalization stage consumes ocr-result.json and emits vector-upsert-request.json; keeping that deterministic transformation in the repository is what preserves chunk IDs and provenance.

curl --fail-with-body --request POST \ --header "Authorization: Bearer $INFRAI_API_KEY" \ --header "Content-Type: application/json" \ --data-binary @ocr-request.json \ --output ocr-result.json \ "$API_BASE/pdf/ocr" curl --fail-with-body --request POST \ --header "Authorization: Bearer $INFRAI_API_KEY" \ --header "Content-Type: application/json" \ --data-binary @vector-upsert-request.json \ "$API_BASE/vector/upsert" 

This block intentionally stops at the indexing boundary. API_BASE is the documented v1 base URL supplied through the deployment environment, which keeps this unlinked comparison free of a vendor domain. At query time, the Node.js service embeds the question, sends a vector query with the asker's permission filter, and passes only the returned chunks to the chat API. It checks every status, backs off on HTTP 429 while honoring Retry-After, and returns the retrieved source identifiers with the answer. The exact request fields must come from the current schemas; inventing a convenient filter name would make a polished example unsafe.

Now apply retention math. Record the current revision pointer in the source system, delete superseded vectors according to a declared retention window, and measure records per article by content class. Long troubleshooting guides and short policy notices should not share an arbitrary chunk budget. A top-k of 20 also carries roughly four times the context and trace payload of a top-k of 5, before reranking or chat. Pick top-k through answer-quality evaluation, then budget its downstream bytes.

Why reject a loosely coupled default?

The rejected default is "choose the best OCR and vector product independently, then connect them." It is valid when OCR quality requirements are specialized, when an organization already owns both platforms, or when independent failure domains are mandatory. AWS Textract plus Pinecone is a reasonable expression of that choice. Tesseract plus Weaviate is another when infrastructure control matters more than managed operations.

It is not the default here because the support bot's main risk lies at the seam: revisions, permission metadata, chunk provenance, and retry behavior must survive the handoff. Two signups and two credential sets are manageable. The costly part is the glue that reconciles separate schemas and rate limits while preserving those invariants. A shared surface reduces that integration area, but concentrates trust and availability. Document that concentration plainly.

The decision should be revisited when the measured corpus changes by an order of magnitude, permission semantics outgrow metadata filtering, OCR quality becomes domain-specific, or one component needs an independent availability boundary. Until then, track four numbers monthly: live chunks, retained revisions, distinct metadata values by field, and retrieved chunks per answered question. They expose index growth before an invoice does.

References

原文:https://www.a8q9.cn/en/article/how-to-build-node-js-retrieval-for-a-50-000-page-internal-wiki-cost-controls-671637.html

相关文章