How to Build an AI-Powered Semantic Search API in ASP.NET Core 10 Using C#, Ollama and PostgreSQL pgvector – Complete Guide (2026)
How to Build an AI-Powered Semantic Search API in ASP.NET Core 10 Using C#, Ollama and PostgreSQL pgvector – Complete Guide (2026)
A customer searches for “a bag that keeps my laptop dry,” while your product record says “water-resistant computer backpack.” A literal term match may miss that connection. Semantic search gives an API a way to compare the intent of the question with the meaning represented by stored text, while PostgreSQL remains responsible for persistence and query execution.
This guide builds an AI-powered semantic search API in ASP.NET Core 10 using C#, Ollama and PostgreSQL pgvector. It indexes short documentation passages, generates embeddings locally and retrieves the closest stored records. There is no chat completion, agent or generated answer: the response contains the source documents and distance-based scores.
How do you build semantic search with Ollama and pgvector?
Generate document embeddings with Ollama’s current POST /api/embed endpoint, store the vectors in a PostgreSQL vector(768) column, and generate a compatible query vector at search time. Order database rows by cosine distance ascending and limit the result count. Use the same model weights, dimensions and preprocessing contract for indexing and querying.
1. Semantic search versus traditional SQL keyword search
Semantic search ranks records using a learned representation of their contents. An embedding model converts a string into a fixed-length numeric vector. Comparing vectors can help retrieve paraphrases, related concepts and multilingual wording that do not share the same literal tokens. The representation is useful evidence for relevance, not a guarantee that a document is correct or current.
SQL keyword search remains valuable. Equality, full-text search and carefully designed lexical ranking are often the right tools for exact error codes, SKUs and names. A search for “HTTP 500.30” should preserve those characters; a semantic model may consider several hosting errors related without understanding that the distinction is operationally important.
| Approach | Good fit | Limitation |
|---|---|---|
| SQL equality / exact matching | Product IDs, order numbers and exact error codes | Does not solve paraphrases |
| PostgreSQL full-text search | Token-aware document search with lexical ranking | Vocabulary mismatch still needs attention |
| Dense semantic search | Natural-language descriptions and related questions | Needs evaluation and compatible model vectors |
| Hybrid retrieval | Combining lexical evidence and vector candidates | Requires an explicit fusion/ranking design |
A documentation portal can retrieve a page about app pool configuration for a question about an API failing after IIS deployment. A product catalog can retrieve candidate backpacks for a functional description. In either case, structured filters such as stock, price, language, tenant and permissions still belong in the search design. A relevant document is not automatically an authorized document.
The API in this article indexes small supplied passages. It does not parse PDF files, crawl websites, split arbitrary uploads, generate answers or implement hybrid ranking. Those are separate application responsibilities. Keeping this boundary small makes the persistence and retrieval behavior easier to inspect.
2. Architecture, cosine similarity and cosine distance
The indexing path validates a title and a short passage, adds the model’s document prefix, calls Ollama and commits the text plus embedding to PostgreSQL. The query path validates the question, adds the query prefix, generates one vector and asks PostgreSQL for the nearest stored documents. Previously indexed documents are not embedded again on every search.
For nonzero vectors a and b, cosine similarity is dot(a,b) / (length(a) × length(b)). Cosine distance is 1 − cosineSimilarity. In pgvector, <=> is the cosine-distance operator. Smaller distance means closer direction; larger similarity means closer direction. A score of 0.8 is not “80% confidence.”
| pgvector operator | Measure | Matching index operator class |
|---|---|---|
| <=> | Cosine distance | vector_cosine_ops |
| <-> | Euclidean / L2 distance | vector_l2_ops |
| <#> | Negative inner product | vector_ip_ops |
The implementation orders by distance ascending inside SQL and computes the display similarity after retrieving the small result set. It does not rewrite SQL ordering as descending 1 - distance, which can make a nearest-neighbor index ineligible. See the official pgvector operator and indexing reference.
All vectors use 768 dimensions in this corpus. Dimension equality is necessary but insufficient: two unrelated 768-dimensional models do not share a useful coordinate space. Changing model weights, prefixes or preprocessing requires a reviewed migration and re-embedding plan. A model tag can move; record the pulled artifact identity in deployment records and do not update it independently of stored vectors.
3. Prerequisites, .NET 10 and current NuGet packages
Install the .NET 10 SDK, a compatible editor or Visual Studio version with .NET 10 support, Ollama, Docker with Linux-container support and Postman. Ensure you have enough disk and RAM for the selected model, PostgreSQL and its indexes. A GPU can change inference latency, but no particular throughput or minimum RAM figure is promised here.
The example runs the API and Ollama on the host, with PostgreSQL in Docker. On Windows, install Ollama from its official installer and follow the Windows installation documentation. The local API normally listens at port 11434. If you later containerize the API, localhost refers to that container rather than the host.
Use the complete project file below so the design-time dependency remains private. Microsoft EF Core runtime, design tooling and the local dotnet-ef tool use the same 10.0.14 patch. The Npgsql provider has its own version schedule: 10.0.3 accepts EF Core 10 within its documented dependency range. Pgvector.EntityFrameworkCore 0.3.0 explicitly supports EF Core 9 and 10. These are stable selections, not 11.x previews.
Compatibility was checked against Npgsql’s package dependencies, the pgvector EF integration package and Microsoft’s design package. Restore and commit a lock file in your own repository, and review updates rather than assuming any newer major version is interchangeable.
4. Install Ollama and start PostgreSQL pgvector with Docker
Pull and verify the selected embedding model
Use nomic-embed-text-v2-moe, not a chat model or an assumed alias for another Nomic release. Its published model information specifies 768-dimensional embeddings, a 512-token sequence limit and retrieval prefixes. This guide keeps full-size output and does not request dimension reduction.
The prefixes are search_document: for indexed content and search_query: for searches. They are applied in C#, so callers send plain text. The token limit includes prefixed input. Local character limits are payload safeguards, not exact tokenizer calculations.
The expected vector length is 768. Verify it before indexing; this is not an executed result from the authoring environment. The current Ollama embed API accepts input and returns an embeddings array. Older examples using /api/embeddings with prompt describe a different contract. Do not mix those request and response shapes.
Run a local PostgreSQL instance with pgvector installed
Run these commands in the directory containing compose.yaml and keep the password for the next step. The image installs extension binaries; the EF migration enables vector inside this database. The tag is listed in the official pgvector Docker instructions. Pin an approved image digest in production.
This development container uses its initial administrative role for convenience. Do not reuse that superuser-style role as the production API identity. Initialization variables apply to an empty data directory: restarting with a different environment password does not rotate credentials in an existing volume. The named volume preserves data; rotate credentials deliberately.
5. Configure connection strings and protect credentials
Keep connection credentials and both API keys outside committed JSON. Separate reader and writer keys prevent a search-only caller from indexing content. Shared keys are a teaching boundary, not a production identity provider or tenant-authorization system.
Use these values privately in your local Postman environment; do not share screenshots containing secrets. User Secrets keeps values outside the project tree but does not encrypt them. Read Microsoft’s development-secrets guidance. In deployment, use controlled secret injection. Environment names include ConnectionStrings__SearchDb and Demo__ReadKey.
SSL Mode=Disable is restricted to this loopback-only development database. For a remote database, configure TLS with certificate and hostname validation, for example Npgsql’s VerifyFull mode and the appropriate trusted CA. See Npgsql security and encryption. Never permanently disable certificate checks to hide a configuration error.
The Ollama URL is trusted server configuration, never caller input. This avoids making the API an arbitrary outbound-request proxy. Local inference needs no OpenAI API key, but hardware, maintenance, hosting and the model license still matter.
6. Define the model, DbContext and migrations
Create every C# file shown here inside the SemanticSearch.Api project. Each row represents one short passage and includes source text for displaying a result. The Space field records the application’s embedding contract; it is not an authorization field or a cryptographic verification of downloaded weights.
Two configuration steps are required: HasPostgresExtension("vector") tells migrations to enable the database extension, while UseVector() registers provider integration. The property uses Pgvector.Vector and an explicit 768-dimensional column. The official pgvector-dotnet examples document EF mapping and distance translation.
The HNSW index uses cosine operators to match the search query. It is optional for a tiny dataset but included so migrations express the intended index. The construction settings are examples, not benchmark-derived tuning. Change them after measuring your corpus and resources.
Keep design-time tooling independent of API keys
The factory loads the database connection without requiring the API’s reader/writer keys. Run tooling from the project directory so appsettings.json is found. This creates a DbContext for tooling; it does not migrate the running application automatically.
The migration should create vector, Documents, its HNSW index and EF migration history. Do not combine EnsureCreated with this workflow. In production, apply reviewed scripts or a migration bundle using a deployment identity rather than granting the API schema-alteration permissions. See EF Core migrations.
This excerpt explains the intended objects, not a second installation step after EF creates them. The generated script includes migration metadata and may differ in formatting. Use a fresh tutorial database rather than an unrelated database containing an existing Documents table.
7. Complete Ollama embedding client with validation and cancellation
The typed HttpClient uses a fixed relative route, no redirects and an explicit linked cancellation budget. It never returns an unvalidated vector: count, dimensions, finite coordinates and nonzero length must all match. The API does not assume a successful HTTP status guarantees a usable model result.
Sending truncate=false makes over-limit input fail rather than silently losing the end of a document. The selected model has a short token window, so even a passage within 600 characters can exceed the tokenizer’s limit in some languages or symbol-heavy inputs. The safe 422 response asks the caller to shorten or deliberately chunk it. The sample maps Ollama 400 responses to that general rejection; inspect private service diagnostics to distinguish a token limit from other model-side input problems.
Cancellation is propagated into the HTTP call and database operations. A 60-second application budget is cooperative; it is not a claim that model computation stops instantly. Cold model loading, CPU inference and resource contention may require a different measured budget in your environment. Avoid retrying inference indefinitely when the instance is overloaded.
For larger documents, introduce a separate ingestion process that splits on useful boundaries, preserves source IDs and chunk positions, and records preprocessing versions. Do not increase the database column size and assume the model can accept any text length. The Ollama embedding guide explains the generation boundary.
8. Store document vectors and implement top-K semantic search
Indexing calls the model before opening a database transaction, then SaveChangesAsync commits the record. If inference fails, no row is added. If the database write fails after inference, the request fails safely; the generated vector is not durable. This POST intentionally creates a new ID each time. Retrying after an uncertain response can create duplicate documents, so production ingestion needs a source identifier and an idempotent upsert/version policy.
Search uses AsNoTracking and projects only the fields returned to the caller. The vector itself is not returned. The database performs distance ordering and LIMIT; there is no ToList before ranking, and no application-side scan of the entire corpus. The score conversion happens after the bounded result set is materialized.
The Space filter prevents accidental mixing of application-defined corpora, but it cannot detect a silent model-tag update. Do not serve new query vectors against old weights without rebuilding or versioning the corpus. This sample holds one model and schema contract fixed; it is not a dynamic model selector.
TopK is a requested maximum, not a promise of exactly K matches. An empty corpus returns an empty array. Approximate indexing, filters and available documents can also reduce results. Ties need not have stable order. Add an evaluated secondary ordering strategy only after checking its effect on query plans.
9. Centralized errors, dependency injection and complete Program.cs
The startup code verifies mandatory configuration, registers EF with UseVector, configures the typed client and attaches a concurrency limiter to API endpoints. UseExceptionHandler wraps the pipeline. In .NET 10, handled exceptions can suppress framework diagnostics by default; this handler writes its own safe structured event with an error type, status and trace ID.
The reader key can call POST /api/search; the writer key can index and search. The check uses a case-insensitive search-path allowlist, so differently cased document URLs cannot bypass writer checks. This remains a deliberately small demonstration: production should attach identity and scope policies to endpoints, derive tenant access from trusted claims and implement revocation and audit requirements.
The concurrency limit admits four in-flight requests per application process and queues none. It is neither a distributed rate limit nor a per-user quota. Invalid or unauthorized requests should not consume inference capacity. Review Microsoft’s rate-limiting documentation before choosing production limits.
For the broader authentication design, see the existing JWT authentication in ASP.NET Core 10 guide. For centralized error-handling concepts, see global exception handling with IExceptionHandler. Those posts provide context; copying their configuration alone does not add tenant-aware search authorization.
Example safe error contract for a missing local model (the trace ID is illustrative):
10. Test document indexing and search with Postman
Build and start the local API
Local HTTP is used only on the developer machine. Configure HTTPS at the production ingress and restrict access to model and database ports. Create a Postman environment with baseUrl set to http://localhost:5093 and private readKey/writeKey values from setup. Set Content-Type: application/json on requests.
Index three short passages
Send POST {{baseUrl}}/api/documents with X-Api-Key: {{writeKey}}. Submit each JSON object below as a separate request; this endpoint does not accept a JSON array.
A successful insertion returns HTTP 200 and an IndexedDocument object. This API uses 200 for the completed operation because it does not define a separate GET resource URL. A 201 response with Location would be appropriate if a resolvable resource endpoint were added.
The UUID above is a placeholder. Your API generates a fresh UUID. It is not an observed database record.
Search with a paraphrase
Send POST {{baseUrl}}/api/search with X-Api-Key: {{readKey}}:
Expect HTTP 200 with space, requestedTopK and a results array. Each match contains id, title, content, cosineDistance and cosineSimilarity. Results are ordered by ascending distance. The IIS passage is a plausible relevance candidate, but no exact rank or score is guaranteed without running and evaluating the selected model. Do not hardcode invented embeddings or confidence scores into an expected-output screenshot.
An empty result is a normal contract only when no eligible rows are retrieved. The implementation does not disguise model or database failures as an empty array.
Negative tests worth performing
| Test | Expected behavior |
|---|---|
| No key or incorrect key | 401; no inference |
| Reader key sent to POST /api/documents | 403; no insert |
| Blank query, TopK=0 or TopK=21 | 400 before model work |
| Title above 120 characters or content above 600 | 400 |
| Unknown JSON property or malformed JSON | 400 binding/JSON failure |
| Model rejects over-token input with truncate=false | 422; no row inserted |
| Ollama unreachable or model not installed | 503 with safe detail |
| Wrong vector dimension or malformed model JSON | 502; no database write |
| Embedding budget exceeded | 504 unless caller already cancelled |
| Database unavailable | 503; failure is not an empty successful search |
| More admitted work than concurrency permits | 429; no queued inference |
For a controlled failure test, stop only your disposable development dependency and restart it afterward. Keep credentials out of captured output. Test client cancellation as well as timeout; a disconnected client may receive no JSON response at all. Use mocks for vector validation/unit tests and an actual PostgreSQL+pgvector integration environment for query translation and ordering. EF’s in-memory provider cannot validate pgvector SQL or HNSW behavior.
Useful integration assertions include: indexing persists one row, unauthorized indexing persists none, document/query prefixes differ correctly, an empty table returns no matches, model failure prevents insertion and database errors never leak credentials. For a deterministic database ordering test, seed known nonzero toy vectors and query directly, independently of the model’s semantic quality.
11. HNSW indexes, distance ordering and performance tradeoffs
pgvector can perform exact nearest-neighbor search without an approximate index. HNSW adds a graph-based approximate access path: it explores candidates rather than promising every true nearest neighbor. It can be useful as a corpus grows, but it consumes memory, increases write/index-maintenance work and requires retrieval-quality evaluation.
| Setting / choice | Effect to evaluate |
|---|---|
| m | Graph connectivity; affects index size and construction work |
| ef_construction | Candidate list during index construction; affects build cost and graph quality |
| hnsw.ef_search | Search candidate breadth; trades search work against recall |
| Exact baseline | Reference ranking for measuring approximate recall |
| Filters | Can reduce returned candidates and affect plans/recall |
| Model and chunking | Often change relevance more than index tuning alone |
Use the pgvector HNSW reference for supported types, dimensions and options. The sample’s vector(768) fits the documented vector index limit. Do not apply a high-dimensional model to an existing column or index without checking the type’s limits.
Inspect SQL and plans before tuning
Here $1 is a bound Pgvector.Vector parameter, $2 is the corpus identity and $3 is bounded TopK. This is an explanation of EF’s intended SQL shape, not a psql command with unset parameters. Inspect generated SQL using ToQueryString on the composed EF query in a safe development environment, then use EXPLAIN on an appropriately bound query. Never concatenate raw user text or vector strings into SQL.
Read PostgreSQL’s EXPLAIN documentation. EXPLAIN ANALYZE actually executes the statement. A sequential scan on three rows is reasonable and is not evidence that pgvector is broken. Do not force an index globally just to make a tutorial screenshot look impressive.
These optional settings are not enabled by the C# sample. SET LOCAL applies only inside its current transaction, not to an unrelated pooled API connection. Iterative scans are available in pgvector 0.8.0 and later; the selected image includes them. Even strict ordering does not mean exact recall: it orders the approximate candidates that are found.
With approximate indexes, filters can leave fewer than TopK eligible results. Increasing search breadth or using iterative scans may help, but does not remove every limit. For strong tenant isolation, consider partitioning or separate corpora/indexes and test the actual access pattern. See iterative index scan guidance.
Measure the system at the right boundaries
Record inference time, model cold-load behavior, database latency, failure rate and retrieval relevance separately. The sample logs vector dimensions and elapsed inference time without source text. Precompute document vectors once, bound TopK, project only required columns and use AsNoTracking for read-only results. Avoid running concurrent operations on one scoped DbContext.
An embedding cache must include model identity, dimensions, prefix/preprocessing version and permitted data scope. For a production catalog, use a durable indexing queue and a versioned source ID instead of repeatedly creating rows. Re-embed only changed content and ensure deleted or unauthorized documents are removed from retrieval. No measured latency, recall or cost numbers are claimed here.
12. Security, local inference and production operations
Local inference controls where this application sends text, but it is not a complete privacy policy. Model downloads, logs, backups, monitoring agents and misconfigured network bindings can still move or expose data. Review the actual deployment and the Ollama operational FAQ; do not advertise unconditional offline privacy merely because the provider URL contains localhost.
Protect both ingestion and retrieval
- Replace shared demo keys with authenticated identities and explicit read/write scopes.
- Derive tenant IDs and document permissions from trusted identity/context, not a caller-supplied “tenant” string.
- Apply authorization in the database retrieval boundary before returning text; never retrieve globally and hide forbidden records afterward.
- Restrict writer access to prevent corpus poisoning and misleading support content.
- Validate payload size, token limits and request concurrency. A four-request per-process limit is not fleet-wide abuse protection.
- Do not log submitted documents, queries, vectors, API keys or database connection strings by default.
- Use a least-privilege database identity for runtime; reserve migrations and extension installation for deployment roles.
- Protect backups, retention and deletion workflows for source text and derived vectors.
A malicious passage cannot make this search-only API execute arbitrary tools because there is no agent or chat model in the path. It can still influence search results. If you later add RAG, treat retrieved text as untrusted data and keep tool permissions and system instructions separate.
Deploy without exposing internal services
Keep Ollama on a private interface and PostgreSQL behind network controls. Do not expose unauthenticated inference ports to the public internet. If the API moves into a container, configure a permitted service/host address deliberately rather than broadening bindings as a shortcut. Use outbound allowlists, authenticated TLS gateways where appropriate and no caller-controlled model URLs.
For IIS hosting, publish the .NET API normally and ensure its process identity can access the private model/database services. An interactive Windows tray app is not automatically a reliable server service. Review restart behavior, model loading, readiness checks and dependency health. The existing ASP.NET Core 10 IIS deployment guide covers the web-hosting foundation.
Operational readiness means more than a successful single query. Test model absence, disk exhaustion, database restarts, slow inference, cancellation, malformed model output, unauthorized ingestion and recovery after partial failures. Define how model artifacts and corpus versions roll forward and backward together.
13. Common errors and troubleshooting
| Problem | Likely cause and correction |
|---|---|
| 404 from Ollama | Confirm the model is installed and the route is /api/embed. This sample maps a missing configured model to 503. Do not switch to a legacy endpoint without changing its contract. |
| No embeddings property in the response | Check that you called the current embed endpoint rather than generate, chat or the older singular-response API. |
| Expected 768 dimensions but received another length | Verify model identity and its output settings. Reject the vector; do not pad or truncate coordinates to satisfy the database. |
| Token-limit failure despite short-looking text | Characters and tokens differ. Include the retrieval prefix in your budget and chunk deliberately; truncate=false prevents silent loss. |
| type vector does not exist | Install extension binaries in the PostgreSQL server and enable vector in this database. A NuGet package alone cannot install a database extension. |
| UseVector or CosineDistance cannot be found | Restore Pgvector.EntityFrameworkCore and import its namespace. Keep the provider/package majors compatible with EF10. |
| EF migration tries to build HTTP configuration | Use the supplied IDesignTimeDbContextFactory and run commands from the project directory. |
| Database password authentication fails after restart | An initialized named volume keeps its original password. New container environment values do not rotate existing database roles. |
| HNSW index is not chosen | Check vector_cosine_ops, ascending raw distance ordering and LIMIT; inspect the plan and dataset size before changing planner settings. |
| Too few matches after adding HNSW | Evaluate candidate breadth, filters, dead tuples and iterative scans. TopK is a maximum, not a guarantee. |
| Scores look meaningful but results are poor | Check prefixes, model/corpus compatibility and passage quality. Build labeled relevance tests; there is no universal score threshold. |
| Repeated POST produces duplicate documents | This teaching endpoint creates a new UUID. Add an idempotent source-ID/version design for production ingestion. |
| API cannot reach localhost model inside Docker | Localhost is the API container itself. Configure trusted container networking or a supported host address. |
| 503 on database operations | Check PostgreSQL health, connection settings, privileges and migration completion. Inspect trace-linked private telemetry. |
| One user can see another user’s documents | The demo is a single authorized corpus. Implement trusted tenant/document permissions in retrieval before using it for multiple tenants. |
A useful troubleshooting sequence is: verify the model endpoint directly, verify returned dimensions, verify extension/schema state, then inspect generated SQL and the database plan. Changing all layers at once makes it difficult to identify whether the problem is inference, mapping, connectivity or retrieval quality.
14. Frequently asked questions
Do I need an OpenAI key?
No. This example calls a local Ollama embedding model. It still requires local compute and an appropriate model license; “no external API key” is not the same as “no operating cost.”
Is this a RAG chatbot?
No. It retrieves documents and returns their text and scores. RAG adds a separate generation stage that uses retrieved context to draft an answer. This guide deliberately stops at retrieval.
Why not use Microsoft.Extensions.AI here?
The raw typed HttpClient makes Ollama’s current JSON contract, truncate behavior and failure handling explicit. Microsoft.Extensions.AI can be a useful abstraction when you want interchangeable embedding providers, but it is not necessary to call this local REST endpoint.
Can I use a different Ollama embedding model?
Yes, with a reviewed new contract: model identity, prefixes, token limit, output dimensions and storage/index compatibility must all be checked. Rebuild or version the corpus; simply changing the model string is not safe.
Why store vector(768)?
The selected Nomic v2 MoE model produces 768-dimensional full-size embeddings. The application validates that length and the database enforces the column shape. Different models or reduced outputs require matching schema and data changes.
Is cosine similarity a confidence percentage?
No. It measures vector direction similarity. A high value does not prove factual correctness, authorization or answer quality. Choose thresholds only after evaluating representative queries and labeled documents.
Does HNSW guarantee the true nearest documents?
No. It is approximate. Evaluate recall against an exact baseline and inspect latency/resource use before choosing search parameters.
Should every document be one database row?
For short passages, that is a clear learning model. Longer documents usually need chunks with source IDs, positions and a deletion/update policy. Chunking should respect the model’s token window and preserve useful context.
Can the same database support keyword search?
Yes. PostgreSQL can store source text and support lexical search as well as vectors. Combining candidate lists needs an explicit hybrid-ranking design; this tutorial does not pretend cosine distance implements lexical matching.
Why can a successful search return fewer than TopK?
There may be fewer eligible documents, or approximate candidate scanning and filtering may reduce results. Return the actual count without inventing placeholder matches.
Was the implementation tested?
The code was reviewed against official APIs and package dependencies, but it was not compiled or executed. There was no local .NET, Docker, PostgreSQL or Ollama runtime available. Run the build, migration and positive/negative API checks before using it. All response examples are explicitly illustrative.
15. Conclusion and useful next steps
This API keeps the semantic-search boundary visible: validate input, generate a compatible local vector, store document embeddings durably and let PostgreSQL rank candidates with a matching distance operator. The practical details—prefixes, dimensions, failure handling, authorization and query shape—matter as much as adding a vector column.
Start with a small corpus you can judge manually. Verify the data path, add labeled relevance tests, then decide whether approximate indexing and more elaborate ingestion are justified. Preserve exact identifiers with lexical techniques where needed and treat model changes as data migrations.
Possible supporting tutorials
- Combining document freshness and semantic relevance for versioned API documentation.
- Testing document-level access rules in a PostgreSQL semantic-search endpoint.
- Designing restart-safe ingestion checkpoints for local embedding workloads.
These are future ideas only; no additional drafts were created.
16. References and further reading
- .NET 10 and EF Core 10 requirements
- Ollama Windows setup
- Ollama current embedding endpoint
- Ollama embedding capabilities
- Selected Nomic model, dimensions and prefixes
- Ollama operations and networking FAQ
- pgvector installation, Docker tags, operators and indexes
- pgvector-dotnet EF integration
- Pgvector.EntityFrameworkCore package
- Npgsql EF provider package and constraints
- Npgsql EF Core 10 release notes
- Npgsql TLS and security
- Microsoft EF Core design package
- dotnet-ef 10.0.14 tooling
- EF Core migrations
- ASP.NET Core development secrets
- ASP.NET Core rate limiting
- ASP.NET Core exception handling
- PostgreSQL EXPLAIN
- PostgreSQL full-text search
Research date: 4 November 2026. Package versions, model tags and operational defaults can change. Check the linked release/dependency pages when reproducing the project.
Developer questions about cosine indexes and descending score ordering were checked against the operator-class issue discussion and ordering discussion; the current project documentation is the implementation authority. A public .NET retrieval/RAG example was reviewed for scope comparison, not used as proof that this implementation was tested. This tutorial focuses on model contracts, failure boundaries and persistent retrieval. No search-volume, competition, benchmark or traffic figures are invented.
Comments
Post a Comment