prescient 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a54256e23ba55fc2492fae38d687b275dcb2362df73449d3212bd03659150717
4
- data.tar.gz: 73ab805b7a5781a1d03488605ae8d7890feda7344b41b1ac550343484b3b597a
3
+ metadata.gz: 53a88a152c9fb689789c06dc11612905e30d76e997dbdcc1ca9906870bb01899
4
+ data.tar.gz: 4dba29dd0ad5ae0edbccd0f9d50d8e1eeb8815ba1aeadda838b327ec124111d6
5
5
  SHA512:
6
- metadata.gz: e918a87b3e09affe9d5a002a3955051e7729ee565f84c42c534c99dc3fc70371fda930e63cc90801da07b4c4f5e48031c41e952088dfc3de24f0f38b579e9567
7
- data.tar.gz: feb707947b7cc0b67d8bff933b4c584a69595b9b5e1dd3f214b4c4aa2d48c0577c996b542c238fbcef337f0f276a1bb995acc9653e8fad32262a6f6fa17caaf4
6
+ metadata.gz: 0beee5d0fc6ca63e1d2f881055402a18ab374d8ec71f17c6e706bba7a0ec8f565bbd77ff4f1b337f100597d357a07ffcc45b37e080429199603ce3147e292579
7
+ data.tar.gz: 2d8214bfb8d5f61536e5c79462d560cd4d6f83215dae54cffed821fe0f23d2959adbe02ec94f522d69bd2e04adb37b52087ba364752a98e093e6605ce204abfb
data/CHANGELOG.md CHANGED
@@ -2,6 +2,40 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## [0.5.0] - 2025-08-14
6
+
7
+ ### Added
8
+
9
+ - Added a versioned YAML configuration loader with environment-variable references,
10
+ configuration validation, precedence rules, and a packaged JSON Schema.
11
+ - Added YAML-configurable prompt templates and CLI prompt overrides, including
12
+ support for loading multiline templates from a file.
13
+ - Added `prescient config example` for generating an annotated schema-backed YAML configuration starter.
14
+ - Added Google Gemini provider support for text generation, embeddings, health checks, and model listing.
15
+ - Added Gemini environment-variable defaults and YAML configuration support.
16
+ - Added Mistral provider support for text generation, embeddings, health checks, and model listing.
17
+ - Added Mistral environment-variable defaults and YAML configuration support.
18
+ - Added DeepSeek provider support for text generation, health checks, and model listing.
19
+ - Documented DeepSeek's unsupported embedding capability explicitly.
20
+ - Added xAI provider support for text generation, health checks, and model listing.
21
+ - Documented xAI's unsupported embedding capability explicitly.
22
+
23
+ ### Changed
24
+
25
+ - Raised YARD documentation coverage enforcement from 99% to 100%.
26
+
27
+ ## [0.4.0] - 2025-08-14
28
+
29
+ ### Added
30
+
31
+ - Added the `prescient` CLI with provider listing, health checks, configuration validation, generation, embeddings, JSON output, stdin input, and exit-status handling.
32
+
33
+ ### Changed
34
+
35
+ - Added CLI model overrides to provider generation and embedding operations.
36
+ - Added secure CLI credential sourcing with `--api-key-env`, alongside direct `--api-key` support for ephemeral automation.
37
+ - Documented all CLI automation overrides, including provider selection, generic and task-specific models, API keys, environment-backed credentials, and JSON output.
38
+
5
39
  ## [0.3.0] - 2025-08-14
6
40
 
7
41
  ### Added
data/INTEGRATION_GUIDE.md CHANGED
@@ -13,7 +13,7 @@ and [examples guide](examples/README.md).
13
13
  # Add to your Gemfile
14
14
  gem 'prescient', path: './prescient_gem' # Local development
15
15
  # OR when published:
16
- # gem 'prescient', '~> 0.3.0'
16
+ # gem 'prescient', '~> 0.5.0'
17
17
  ```
18
18
 
19
19
  ### 2. Replace Existing AI Service
@@ -117,6 +117,17 @@ end
117
117
  Rails.application.config.default_ai_provider = :ollama
118
118
  ```
119
119
 
120
+ For YAML-based deployments, use the versioned configuration format and keep
121
+ credentials in environment variables:
122
+
123
+ ```ruby
124
+ Prescient.load_configuration('prescient.yml')
125
+ ```
126
+
127
+ Configuration precedence is CLI overrides, environment defaults and
128
+ references, YAML values, then built-in defaults. The generated
129
+ `prescient config example` file includes the current JSON Schema URL.
130
+
120
131
  ### 4. Update Environment Variables
121
132
 
122
133
  ```bash
data/README.md CHANGED
@@ -1,10 +1,16 @@
1
1
  # Prescient
2
2
 
3
- Prescient is a boring AI provider abstraction for Ruby. Configure your AI providers once, then use the same interface regardless of whether the request is handled by OpenAI, Anthropic, Ollama, or Hugging Face. Prescient handles provider selection, retries, health checks, and fallback.
3
+ [![Gem Version](https://img.shields.io/gem/v/prescient?logo=rubygems&logoColor=white)](https://rubygems.org/gems/prescient)
4
+ [![Requires Ruby 3.1+](https://img.shields.io/badge/Requires-Ruby%203.1%2B-CC342D?logo=ruby&logoColor=white)](https://www.ruby-lang.org/)
5
+ [![CI](https://github.com/kanutocd/prescient/actions/workflows/ci.yml/badge.svg)](https://github.com/kanutocd/prescient/actions/workflows/ci.yml)
6
+ [![Security](https://img.shields.io/github/actions/workflow/status/kanutocd/prescient/security.yml?branch=main&event=push&label=Security)](https://github.com/kanutocd/prescient/actions/workflows/security.yml)
7
+ [![License](https://img.shields.io/badge/License-MIT-22C55E)](LICENSE.txt)
4
8
 
5
- For focused guidance, see the [examples guide](examples/README.md),
6
- [Rails integration guide](INTEGRATION_GUIDE.md), and
7
- [pgvector guide](VECTOR_SEARCH_GUIDE.md).
9
+ Prescient is a boring AI provider abstraction for Ruby. Configure your AI providers once, then use the same interface regardless of whether the request is handled by OpenAI, Anthropic, Ollama, Hugging Face, Google Gemini, Mistral, DeepSeek, or xAI. Prescient handles provider selection, retries, health checks, and fallback.
10
+
11
+ For focused guidance, see the **[examples guide](https://github.com/kanutocd/prescient/tree/main/examples)**,
12
+ **[Rails integration guide](https://github.com/kanutocd/prescient/blob/main/INTEGRATION_GUIDE.md)**, and
13
+ **[pgvector guide](https://github.com/kanutocd/prescient/blob/main/VECTOR_SEARCH_GUIDE.md)**.
8
14
 
9
15
  ## Features
10
16
 
@@ -14,7 +20,7 @@ For focused guidance, see the [examples guide](examples/README.md),
14
20
  - **Text Completion**: Chat completions with context support
15
21
  - **Error Handling**: Robust error handling with automatic retries
16
22
  - **Health Monitoring**: Built-in health checks for all providers
17
- - **Flexible Configuration**: Environment variable and programmatic configuration
23
+ - **Flexible Configuration**: YAML, environment variable, and programmatic configuration
18
24
 
19
25
  ## Supported Providers
20
26
 
@@ -42,6 +48,30 @@ For focused guidance, see the [examples guide](examples/README.md),
42
48
  - **Capabilities**: Embeddings, Text Generation
43
49
  - **Use Case**: Open-source models, research
44
50
 
51
+ ### Google Gemini
52
+
53
+ - **Models**: Gemini generation and embedding models
54
+ - **Capabilities**: Embeddings, Text Generation, Model Listing
55
+ - **Use Case**: Google AI hosted models
56
+
57
+ ### Mistral
58
+
59
+ - **Models**: Mistral chat and embedding models
60
+ - **Capabilities**: Embeddings, Text Generation, Model Listing
61
+ - **Use Case**: Mistral AI hosted models
62
+
63
+ ### DeepSeek
64
+
65
+ - **Models**: DeepSeek chat models
66
+ - **Capabilities**: Text Generation, Model Listing (no embeddings)
67
+ - **Use Case**: DeepSeek hosted reasoning and chat models
68
+
69
+ ### xAI
70
+
71
+ - **Models**: Grok chat models
72
+ - **Capabilities**: Text Generation, Model Listing (no embeddings)
73
+ - **Use Case**: xAI hosted reasoning and chat models
74
+
45
75
  ## Installation
46
76
 
47
77
  Add this line to your application's Gemfile:
@@ -62,6 +92,137 @@ Or install it yourself as:
62
92
  gem install prescient
63
93
  ```
64
94
 
95
+ ## Command-Line Interface
96
+
97
+ Prescient includes a thin CLI for provider inspection and common operations:
98
+
99
+ ```bash
100
+ prescient providers
101
+ prescient health
102
+ prescient config validate
103
+ prescient config example
104
+ prescient generate "Explain Ruby Ractors"
105
+ prescient embed "Ruby is a programming language"
106
+ ```
107
+
108
+ Supported options include:
109
+
110
+ ```text
111
+ --provider NAME Select a provider
112
+ --model NAME Override the selected operation's model
113
+ --chat-model NAME Override the chat model for generation
114
+ --embedding-model NAME Override the embedding model
115
+ --system-prompt TEXT Override the system prompt
116
+ --no-context-template TEXT
117
+ Override the no-context prompt template
118
+ --with-context-template TEXT
119
+ Override the with-context prompt template
120
+ --prompt-templates-file PATH
121
+ Load prompt templates from a YAML file
122
+ --api-key KEY Use an API key for the operation
123
+ --api-key-env NAME Read the API key from an environment variable
124
+ --format FORMAT Select text or json output
125
+ ```
126
+
127
+ Use `--api-key-env` to source credentials from an environment variable. The
128
+ direct `--api-key` option is available for ephemeral automation but may be
129
+ visible in shell history or process listings. Use `--format json` for
130
+ machine-readable output and stdin for shell pipelines:
131
+
132
+ ```bash
133
+ printf '%s' "Explain PostgreSQL logical replication" | \
134
+ prescient generate --provider openai --format json
135
+ ```
136
+
137
+ OpenAI example JSON output:
138
+
139
+ ```json
140
+ {
141
+ "response": "PostgreSQL logical replication is a method of replicating data between PostgreSQL databases at a logical level, allowing fine-grained control over which data is replicated and how. Unlike physical replication, which copies the entire database cluster’s data files at the storage level, logical replication works by sending changes to data (such as INSERT, UPDATE, DELETE operations) based on logical changes in the database.\n\n### Key Features of PostgreSQL Logical Replication\n\n1. **Row-Level Replication:** Logical replication replicates data changes at the row level. It streams changes to individual tables rather than the entire database.\n\n2. **Selective Replication:** You can choose specific tables to replicate rather than the whole database. This makes it useful for replicating subsets of data.\n\n3. **Asynchronous Replication:** Changes are sent asynchronously from the publisher (source) to the subscriber (target). This means there may be a slight delay between when changes are made and when they appear on the subscriber.\n\n4. **Supports Heterogeneous Setups:** Logical replication can be used between different major versions of PostgreSQL, allowing upgrades with minimal downtime. It can also be used for replication between different architectures or operating systems.\n\n5. **Bidirectional Replication:** By configuring multiple publishers and subscribers, logical replication can support multi-master setups, although care must be taken to avoid conflicts.\n\n### How Logical Replication Works\n\n- **Publisher:** The database that sends data changes. It defines one or more publications, which specify which tables and changes (inserts, updates, deletes) to replicate.\n \n- **Subscriber:** The database that receives and applies the changes. It subscribes to one or more publications from the publisher.\n\nWhen a change occurs on the publisher's table, the change is captured and sent to the subscriber, where it is applied to the corresponding table.\n\n### Setting Up Logical Replication (Basic Steps)\n\n1. **Enable required settings:** Ensure the PostgreSQL server has `wal_level` set to `logical`, and configure `max_replication_slots` and `max_wal_senders` appropriately.\n\n2. **Create a publication on the publisher:**\n\n ```sql\n CREATE PUBLICATION my_publication FOR TABLE my_table;\n ```\n\n3. **Create a subscription on the subscriber:**\n\n ```sql\n CREATE SUBSCRIPTION my_subscription\n CONNECTION 'host=publisher_host dbname=publisher_db user=replicator password=secret'\n PUBLICATION my_publication;\n ```\n\nOnce set up, changes to `my_table` on the publisher will be replicated to the subscriber.\n\n### Use Cases\n\n- **Selective data replication:** Replicating only certain tables or rows.\n- **Data integration:** Feeding data from multiple sources into a central database.\n- **Upgrading PostgreSQL versions:** Using logical replication to migrate data with minimal downtime.\n- **Multi-datacenter replication:** Replicating data across geographically distributed systems.\n\n---\n\nIn summary, PostgreSQL logical replication is a flexible, table-level replication mechanism that allows selective, asynchronous replication of data changes between PostgreSQL databases, useful for upgrades, distributed architectures, and data integration scenarios.",
142
+ "model": "gpt-4.1-mini",
143
+ "provider": "openai",
144
+ "processing_time": null,
145
+ "metadata": {
146
+ "usage": {
147
+ "prompt_tokens": 38,
148
+ "completion_tokens": 632,
149
+ "total_tokens": 670,
150
+ "prompt_tokens_details": {
151
+ "cached_tokens": 0,
152
+ "audio_tokens": 0
153
+ },
154
+ "completion_tokens_details": {
155
+ "reasoning_tokens": 0,
156
+ "audio_tokens": 0,
157
+ "accepted_prediction_tokens": 0,
158
+ "rejected_prediction_tokens": 0
159
+ }
160
+ },
161
+ "finish_reason": "stop"
162
+ }
163
+ }
164
+ ```
165
+
166
+ Anthropic example JSON output:
167
+
168
+ ```json
169
+ {
170
+ "response": "PostgreSQL logical replication is a method of replicating data between PostgreSQL databases that allows fine-grained control over which data is replicated and how it is applied. Unlike physical replication, which copies the entire database cluster at the storage level, logical replication works at the level of individual database changes, such as INSERT, UPDATE, and DELETE operations.\n\n### Key Features of PostgreSQL Logical Replication:\n\n1. **Row-Level Changes:** Logical replication replicates changes at the row level, meaning only the actual data changes are sent to the subscriber.\n\n2. **Selective Replication:** You can replicate specific tables rather than the entire database. This allows partial replication tailored to your needs.\n\n3. **Asynchronous Replication:** Logical replication is asynchronous, so there might be a slight delay between the publisher and subscriber.\n\n4. **Bidirectional Replication (with care):** While PostgreSQL does not natively support multi-master replication, logical replication can be configured to allow bidirectional replication setups with caution to avoid conflicts.\n\n5. **Decoupling of Replication:** Logical replication decouples the replication from the physical storage, enabling replication across different PostgreSQL versions (within compatibility limits).\n\n### How Logical Replication Works:\n\n- **Publisher:** The source database that sends changes. It publishes a set of changes based on one or more publications.\n- **Publication:** A set of changes (typically from specific tables) that the publisher makes available to subscribers.\n- **Subscriber:** The target database that receives changes and applies them.\n- **Subscription:** A configuration on the subscriber that connects to a publication and applies changes.\n\n### Use Cases:\n\n- Replicating specific tables or subsets of data.\n- Migrating data between PostgreSQL versions or clusters.\n- Distributing data geographically.\n- Implementing data warehousing or reporting solutions with up-to-date data.\n- Supporting microservices architectures where different services own different parts of the data.\n\n### Basic Setup Example:\n\n1. **On the Publisher:**\n\n```sql\nCREATE PUBLICATION my_publication FOR TABLE my_table;\n```\n\n2. **On the Subscriber:**\n\n```sql\nCREATE SUBSCRIPTION my_subscription\nCONNECTION 'host=publisher_host dbname=mydb user=replicator password=secret'\nPUBLICATION my_publication;\n```\n\nOnce set up, changes to `my_table` on the publisher will be sent and applied to the subscriber.\n\n### Important Notes:\n\n- Logical replication requires WAL (Write-Ahead Logging) to be configured properly with `wal_level = logical`.\n- Some DDL changes (like adding columns) need careful handling as logical replication primarily replicates DML changes.\n- Logical replication does not replicate sequences, large objects, or certain system catalogs automatically.\n- Conflict resolution is mostly manual; the subscriber applies changes as received.\n\n---\n\nIn summary, PostgreSQL logical replication provides a flexible, table-level replication mechanism that supports selective and version-independent replication of data changes, suitable for many modern replication and data distribution scenarios.",
171
+ "model": "gpt-4.1-mini",
172
+ "provider": "openai",
173
+ "processing_time": null,
174
+ "metadata": {
175
+ "usage": {
176
+ "prompt_tokens": 38,
177
+ "completion_tokens": 597,
178
+ "total_tokens": 635,
179
+ "prompt_tokens_details": {
180
+ "cached_tokens": 0,
181
+ "audio_tokens": 0
182
+ },
183
+ "completion_tokens_details": {
184
+ "reasoning_tokens": 0,
185
+ "audio_tokens": 0,
186
+ "accepted_prediction_tokens": 0,
187
+ "rejected_prediction_tokens": 0
188
+ }
189
+ },
190
+ "finish_reason": "stop"
191
+ }
192
+ }
193
+ ```
194
+
195
+ For automated model and credential overrides:
196
+
197
+ ```bash
198
+ prescient generate \
199
+ --provider openai \
200
+ --chat-model gpt-4.1-mini \
201
+ --api-key-env OPENAI_API_KEY \
202
+ --format json \
203
+ "Explain PostgreSQL logical replication"
204
+
205
+ prescient embed \
206
+ --provider openai \
207
+ --embedding-model text-embedding-3-small \
208
+ --api-key-env OPENAI_API_KEY \
209
+ "Ruby is a programming language"
210
+ ```
211
+
212
+ The CLI writes results to stdout, diagnostics to stderr, and returns a
213
+ non-zero status for invalid usage, provider errors, or unreachable health
214
+ checks. It uses the same `Prescient::Client` execution path as Ruby callers.
215
+
216
+ Generate a schema-backed, annotated starter configuration with:
217
+
218
+ ```bash
219
+ prescient config example > prescient.yml
220
+ ```
221
+
222
+ The generated file points YAML language servers at the latest schema on the
223
+ main branch. Pin the schema URL to a release tag when reproducible tooling is
224
+ required.
225
+
65
226
  ## Configuration
66
227
 
67
228
  ### Environment Variables
@@ -85,6 +246,68 @@ OPENAI_CHAT_MODEL=gpt-4.1-mini
85
246
  HUGGINGFACE_API_KEY=your_api_key
86
247
  HUGGINGFACE_EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
87
248
  HUGGINGFACE_CHAT_MODEL=google/gemma-2-2b-it
249
+
250
+ # Google Gemini
251
+ GEMINI_API_KEY=your_api_key
252
+ GEMINI_EMBEDDING_MODEL=gemini-embedding-001
253
+ GEMINI_CHAT_MODEL=gemini-2.5-flash
254
+
255
+ # Mistral
256
+ MISTRAL_API_KEY=your_api_key
257
+ MISTRAL_EMBEDDING_MODEL=mistral-embed
258
+ MISTRAL_CHAT_MODEL=mistral-large-latest
259
+
260
+ # DeepSeek
261
+ DEEPSEEK_API_KEY=your_api_key
262
+ DEEPSEEK_CHAT_MODEL=deepseek-v4-flash
263
+
264
+ # xAI
265
+ XAI_API_KEY=your_api_key
266
+ XAI_CHAT_MODEL=grok-4.5
267
+ ```
268
+
269
+ ### YAML Configuration
270
+
271
+ Load a versioned YAML configuration with environment-backed credentials:
272
+
273
+ ```yaml
274
+ # yaml-language-server: $schema=https://raw.githubusercontent.com/kanutocd/prescient/refs/heads/main/schema/prescient.configuration.schema.json
275
+ version: 1
276
+ default_provider: openai
277
+ providers:
278
+ openai:
279
+ type: openai
280
+ api_key_env: OPENAI_API_KEY
281
+ embedding_model: text-embedding-3-small
282
+ chat_model: gpt-4.1-mini
283
+ ```
284
+
285
+ ```ruby
286
+ Prescient.load_configuration('prescient.yml')
287
+ ```
288
+
289
+ Configuration precedence is CLI overrides, environment defaults and references,
290
+ YAML values, then built-in defaults. Use `prescient config validate` to check a
291
+ configuration before running an operation, or `prescient config example` to
292
+ generate an annotated starter file.
293
+
294
+ Prompt templates can also be configured per provider. Use the YAML mapping for
295
+ multiline templates, or pass a template file to a single CLI operation:
296
+
297
+ ```yaml
298
+ providers:
299
+ openai:
300
+ type: openai
301
+ api_key_env: OPENAI_API_KEY
302
+ chat_model: gpt-4.1-mini
303
+ prompt_templates:
304
+ system_prompt: You are a concise assistant.
305
+ no_context_template: "%{system_prompt}\n\nUser: %{query}"
306
+ with_context_template: "%{system_prompt}\n\nContext:\n%{context}\n\nUser: %{query}"
307
+ ```
308
+
309
+ ```bash
310
+ prescient generate --prompt-templates-file prompts.yml "Summarize this"
88
311
  ```
89
312
 
90
313
  ### Programmatic Configuration
@@ -118,6 +341,32 @@ Prescient.configure do |config|
118
341
  embedding_model: 'text-embedding-3-small',
119
342
  chat_model: 'gpt-4.1-mini'
120
343
  )
344
+
345
+ # Add Google Gemini
346
+ config.add_provider(:gemini, Prescient::Provider::Gemini,
347
+ api_key: ENV['GEMINI_API_KEY'],
348
+ embedding_model: 'gemini-embedding-001',
349
+ chat_model: 'gemini-2.5-flash'
350
+ )
351
+
352
+ # Add Mistral
353
+ config.add_provider(:mistral, Prescient::Provider::Mistral,
354
+ api_key: ENV['MISTRAL_API_KEY'],
355
+ embedding_model: 'mistral-embed',
356
+ chat_model: 'mistral-large-latest'
357
+ )
358
+
359
+ # Add DeepSeek
360
+ config.add_provider(:deepseek, Prescient::Provider::DeepSeek,
361
+ api_key: ENV['DEEPSEEK_API_KEY'],
362
+ chat_model: 'deepseek-v4-flash'
363
+ )
364
+
365
+ # Add xAI
366
+ config.add_provider(:xai, Prescient::Provider::XAI,
367
+ api_key: ENV['XAI_API_KEY'],
368
+ chat_model: 'grok-4.5'
369
+ )
121
370
  end
122
371
  ```
123
372
 
@@ -273,14 +522,14 @@ Prescient.configure do |config|
273
522
  prompt_templates: {
274
523
  system_prompt: 'You are a friendly customer service representative.',
275
524
  no_context_template: <<~TEMPLATE.strip,
276
- %{ system_prompt }
525
+ %{system_prompt}
277
526
 
278
527
  Customer Question: %{query}
279
528
 
280
529
  Please provide a helpful response.
281
530
  TEMPLATE
282
531
  with_context_template: <<~TEMPLATE.strip
283
- %{ system_prompt } Use the company info below to help answer.
532
+ %{system_prompt} Use the company info below to help answer.
284
533
 
285
534
  Company Information:
286
535
  %{context}
@@ -450,8 +699,9 @@ results = store.search(embedding:, provider: :openai, model: 'text-embedding-3-s
450
699
  ```
451
700
 
452
701
  Every vector must exactly match the store's configured dimensions; Prescient
453
- never pads or truncates vectors. The existing application-schema example below
454
- remains available for projects that need documents, chunks, and custom metadata.
702
+ never pads or truncates vectors. The application-schema example below is
703
+ optional integration material for projects that need documents, chunks, and
704
+ custom metadata; it is not managed by `Prescient::Pgvector::Store`.
455
705
 
456
706
  ### Setup with Docker
457
707
 
@@ -470,7 +720,7 @@ docker compose up -d postgres
470
720
 
471
721
  ### Database Schema
472
722
 
473
- The setup creates these key tables:
723
+ The optional Docker demo creates these application-owned tables:
474
724
 
475
725
  - **`documents`** - Store original content and metadata
476
726
  - **`document_embeddings`** - Store vector embeddings for documents
@@ -652,10 +902,9 @@ DB_HOST=localhost ruby examples/vector_search.rb
652
902
 
653
903
  The example demonstrates:
654
904
 
655
- - Document embedding generation and storage
656
- - Similarity search with different distance functions
657
- - Metadata filtering and advanced queries
658
- - Performance comparison between approaches
905
+ - Embedding generation through `Prescient::Client`
906
+ - Dimension-validated storage through `Prescient::Pgvector::Store`
907
+ - Similarity search with provider and model filters
659
908
 
660
909
  ## Advanced Usage
661
910
 
data/Rakefile CHANGED
@@ -32,7 +32,7 @@ namespace :yard do
32
32
  abort("Unable to determine YARD coverage") unless match
33
33
 
34
34
  coverage = match[1].to_f
35
- minimum = 99.0
35
+ minimum = 100.0
36
36
  if coverage < minimum
37
37
  message = format(
38
38
  "YARD coverage %<coverage>.2f%% is below %<minimum>.2f%%",
@@ -27,6 +27,10 @@ store.create_index!(metric: :cosine)
27
27
  or chunk tables, connections, migrations outside that table, or the `pg` gem.
28
28
  Use `#upsert` and `#search` with embeddings of exactly the configured dimension.
29
29
 
30
+ The remaining sections describe an optional application-owned document schema
31
+ used by the repository's Docker demo. They are not tables created or managed
32
+ by `Prescient::Pgvector::Store`.
33
+
30
34
  ### 1. Start Services
31
35
 
32
36
  ```bash
@@ -55,12 +59,12 @@ export DB_HOST=localhost
55
59
  export OLLAMA_URL=http://localhost:11434
56
60
 
57
61
  # Run the example
58
- ruby examples/vector_search.rb
62
+ bundle exec ruby examples/vector_search.rb
59
63
  ```
60
64
 
61
65
  ## Architecture Overview
62
66
 
63
- ### Database Schema
67
+ ### Application-Owned Example Schema
64
68
 
65
69
  ```
66
70
  documents
@@ -103,7 +107,7 @@ chunk_embeddings
103
107
 
104
108
  ### Vector Indexes
105
109
 
106
- The setup automatically creates HNSW indexes for optimal performance:
110
+ The optional Docker demo creates HNSW indexes for the application-owned tables:
107
111
 
108
112
  - **Cosine Distance**: `embedding <=> query_vector`
109
113
  - **L2 Distance**: `embedding <-> query_vector`
data/examples/README.md CHANGED
@@ -15,7 +15,8 @@ bundle install
15
15
  - `custom_prompts.rb` — system prompts and no-context/with-context templates.
16
16
  - `custom_contexts.rb` — explicit context types, field matching, formatting,
17
17
  and embedding field selection.
18
- - `vector_search.rb` — PostgreSQL/pgvector storage and similarity search.
18
+ - `vector_search.rb` — `Prescient::Pgvector::Store` PostgreSQL/pgvector storage
19
+ and similarity search.
19
20
 
20
21
  The first three examples use Ollama by default. Start Ollama and pull the
21
22
  current local models before running them:
@@ -67,7 +67,7 @@ end
67
67
  # Example 3: Provider comparison (if multiple providers configured)
68
68
  puts "\n=== Example 3: Provider Health Check ==="
69
69
 
70
- providers = [:ollama, :anthropic, :openai, :huggingface]
70
+ providers = %i[ollama anthropic openai huggingface gemini mistral deepseek xai]
71
71
 
72
72
  providers.each do |provider_name|
73
73
  begin
@@ -228,8 +228,8 @@ rescue Prescient::Error => e
228
228
  puts "❌ Error: #{e.message}"
229
229
  end
230
230
 
231
- # Example 4: Embedding Text Extraction
232
- puts "\n--- Example 4: Embedding Text Extraction ---"
231
+ # Example 4: Embedding Text Selection
232
+ puts "\n--- Example 4: Embedding Text Selection ---"
233
233
 
234
234
  begin
235
235
  # Configure a provider with context configs
@@ -251,7 +251,7 @@ begin
251
251
  client = Prescient.client(:embedding_demo)
252
252
 
253
253
  if client.available?
254
- # Test embedding text extraction
254
+ # The configured embedding_fields select title, content, and tags.
255
255
  blog_post = {
256
256
  'type' => 'blog_post',
257
257
  'title' => 'Getting Started with AI',
@@ -262,12 +262,10 @@ begin
262
262
  'publish_date' => '2024-01-15'
263
263
  }
264
264
 
265
- # The extract_embedding_text method will only use title, content, and tags
266
- # This demonstrates how embedding generation can focus on specific fields
267
- embedding_text = client.provider.send(:extract_embedding_text, blog_post)
268
- puts "📊 Embedding Text Extracted:"
265
+ embedding_text = [blog_post['title'], blog_post['content'], blog_post['tags']].join(' ')
266
+ puts "📊 Embedding Text Selected:"
269
267
  puts "\"#{embedding_text}\""
270
- puts "\n(Notice how only title, content, and tags are included - not author, category, or date)"
268
+ puts "\n(Only title, content, and tags are included in the embedding input)"
271
269
 
272
270
  # Generate actual embedding
273
271
  puts "\n🔢 Generating embedding..."
@@ -317,19 +315,6 @@ begin
317
315
  puts "🔧 Raw data (no context config):"
318
316
  random_data.each { |item| puts " #{item}" }
319
317
 
320
- puts "\n📄 How items are formatted without context config:"
321
- random_data.each do |item|
322
- formatted = client.provider.send(:format_context_item, item)
323
- puts " #{formatted}"
324
- end
325
-
326
- puts "\n🔤 Embedding text extraction (automatic field filtering):"
327
- random_data.each do |item|
328
- embedding_text = client.provider.send(:extract_embedding_text, item)
329
- puts " \"#{embedding_text}\""
330
- puts " (Notice: excludes 'created_at', 'timestamp' - common metadata fields)"
331
- end
332
-
333
318
  response = client.generate_response("Summarize the key issues", random_data)
334
319
  puts "\n🤖 AI Response (using default formatting):"
335
320
  puts response[:response]