prescient 0.4.0 → 0.6.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: 3f12c7d49067ef7917aa1f674f83e4ff8111a5606fa62edcbb7c97b8791dfbee
4
- data.tar.gz: 4bf6ad2a1a8988ec7eb77cb5a2e278f902ceaa2cfc30d0de3c303c4fa1017168
3
+ metadata.gz: 167f50351b78b35d1ae63d3487285db48c07799ad015b5d49f46dd3c451afa49
4
+ data.tar.gz: 91e1895635015120c75b0b461fea017d8ec7c4b5ebd81f1d2b0c86ba37690e1d
5
5
  SHA512:
6
- metadata.gz: b0fd6efd2a47ce4ffd2766d32706b4b852bfb4e47b62b10ca5e39b50698281048d15be905cfcace617185958194bd1fccde939fd4bac1d83d617cf72707a54c5
7
- data.tar.gz: dfeb2ac6ed61f430730c589a42853b0d118cb425871784dc481e6ea781fedbfd6fcd3582cdadf89718b01c97a2da234898b8bbd868fc709ce3582c02e0662bee
6
+ metadata.gz: 6cdf4ed9b05525692898cdd88153f092c23f5caac1d422962bdc768055bb225e960e45a9fb877adb17a7c686e8bf608db09dea1b3e24ebc15767071255910285
7
+ data.tar.gz: ecec27b8c215dfe5fb92e00f68fd6a5ae66c8284342525c9ae635214318032fc4970a72d2944679e455915f2ba8de8425a07706530ca6c309bedc5d5d4ff114a
data/.dockerignore ADDED
@@ -0,0 +1,18 @@
1
+ .git
2
+ .github
3
+ .ignoreme
4
+ .bundle
5
+ .yardoc
6
+ _yardoc
7
+ coverage
8
+ doc
9
+ tmp
10
+ test
11
+ spec
12
+ examples/*.rb
13
+ *.gem
14
+ .env*
15
+ AGENTS.md
16
+ Dockerfile.example
17
+ docker-compose.yml
18
+ docker-compose.api.yml
data/CHANGELOG.md CHANGED
@@ -2,6 +2,48 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## [0.6.0] - 2025-08-15
6
+
7
+ ### Added
8
+
9
+ - Added a dependency-free Rack-compatible REST API with generation, embeddings,
10
+ bounded batch embeddings, provider/model discovery, capabilities, health,
11
+ liveness, readiness, version, request IDs, authentication hooks, and JSON
12
+ error envelopes.
13
+ - Added a small Rack example that lists the REST API endpoints and delegates
14
+ requests to `Prescient::API`.
15
+ - Added an optional `rack_example` bundle group with Rack, Rackup, and Puma for
16
+ running the example application without adding web-server dependencies to
17
+ the library.
18
+ - Added a non-root, healthchecked Docker image and Compose example for the REST
19
+ API, with optional GHCR publication on version tags.
20
+ - Documented mounting `Prescient::API` in Rails routes with its endpoint
21
+ catalog and authentication example.
22
+ - Made the CLI and REST API optional lazy-loaded entry points so library users
23
+ requiring only `prescient` do not load either interface eagerly.
24
+
25
+ ## [0.5.0] - 2025-08-14
26
+
27
+ ### Added
28
+
29
+ - Added a versioned YAML configuration loader with environment-variable references,
30
+ configuration validation, precedence rules, and a packaged JSON Schema.
31
+ - Added YAML-configurable prompt templates and CLI prompt overrides, including
32
+ support for loading multiline templates from a file.
33
+ - Added `prescient config example` for generating an annotated schema-backed YAML configuration starter.
34
+ - Added Google Gemini provider support for text generation, embeddings, health checks, and model listing.
35
+ - Added Gemini environment-variable defaults and YAML configuration support.
36
+ - Added Mistral provider support for text generation, embeddings, health checks, and model listing.
37
+ - Added Mistral environment-variable defaults and YAML configuration support.
38
+ - Added DeepSeek provider support for text generation, health checks, and model listing.
39
+ - Documented DeepSeek's unsupported embedding capability explicitly.
40
+ - Added xAI provider support for text generation, health checks, and model listing.
41
+ - Documented xAI's unsupported embedding capability explicitly.
42
+
43
+ ### Changed
44
+
45
+ - Raised YARD documentation coverage enforcement from 99% to 100%.
46
+
5
47
  ## [0.4.0] - 2025-08-14
6
48
 
7
49
  ### Added
data/Dockerfile ADDED
@@ -0,0 +1,45 @@
1
+ # syntax=docker/dockerfile:1
2
+
3
+ FROM ruby:3.3-alpine AS builder
4
+
5
+ WORKDIR /app
6
+
7
+ RUN apk add --no-cache build-base git
8
+
9
+ ENV BUNDLE_WITH=rack_example \
10
+ BUNDLE_WITHOUT=development:test \
11
+ BUNDLE_PATH=/usr/local/bundle
12
+
13
+ COPY Gemfile prescient.gemspec ./
14
+ COPY lib ./lib
15
+
16
+ RUN bundle install --jobs 4 --retry 3
17
+
18
+ FROM ruby:3.3-alpine
19
+
20
+ WORKDIR /app
21
+
22
+ RUN apk add --no-cache curl tzdata && \
23
+ addgroup -S -g 1000 prescient && \
24
+ adduser -S -u 1000 -G prescient prescient
25
+
26
+ ENV BUNDLE_WITH=rack_example \
27
+ BUNDLE_WITHOUT=development:test \
28
+ BUNDLE_PATH=/usr/local/bundle \
29
+ GEM_HOME=/usr/local/bundle/ruby/3.3.0 \
30
+ GEM_PATH=/usr/local/bundle/ruby/3.3.0 \
31
+ PATH=/usr/local/bundle/ruby/3.3.0/bin:/usr/local/bundle/bin:$PATH \
32
+ RACK_ENV=production
33
+
34
+ COPY --from=builder /usr/local/bundle /usr/local/bundle
35
+ COPY --chown=prescient:prescient lib ./lib
36
+ COPY --chown=prescient:prescient examples/rest_api.ru ./examples/rest_api.ru
37
+
38
+ USER prescient
39
+
40
+ EXPOSE 9292
41
+
42
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
43
+ CMD curl --fail --silent http://127.0.0.1:9292/healthz || exit 1
44
+
45
+ CMD ["rackup", "-s", "puma", "-o", "0.0.0.0", "-p", "9292", "/app/examples/rest_api.ru"]
data/INTEGRATION_GUIDE.md CHANGED
@@ -11,9 +11,7 @@ and [examples guide](examples/README.md).
11
11
 
12
12
  ```ruby
13
13
  # Add to your Gemfile
14
- gem 'prescient', path: './prescient_gem' # Local development
15
- # OR when published:
16
- # gem 'prescient', '~> 0.4.0'
14
+ gem 'prescient', '~> 0.6.0'
17
15
  ```
18
16
 
19
17
  ### 2. Replace Existing AI Service
@@ -111,13 +109,107 @@ Prescient.configure do |config|
111
109
  chat_model: ENV.fetch('HUGGINGFACE_CHAT_MODEL', 'google/gemma-2-2b-it')
112
110
  )
113
111
  end
112
+
113
+ # Google Gemini
114
+ if ENV['GEMINI_API_KEY'].present?
115
+ config.add_provider(:gemini, Prescient::Provider::Gemini,
116
+ api_key: ENV['GEMINI_API_KEY'],
117
+ embedding_model: ENV.fetch('GEMINI_EMBEDDING_MODEL', 'gemini-embedding-001'),
118
+ chat_model: ENV.fetch('GEMINI_CHAT_MODEL', 'gemini-2.5-flash')
119
+ )
120
+ end
121
+
122
+ # Mistral
123
+ if ENV['MISTRAL_API_KEY'].present?
124
+ config.add_provider(:mistral, Prescient::Provider::Mistral,
125
+ api_key: ENV['MISTRAL_API_KEY'],
126
+ embedding_model: ENV.fetch('MISTRAL_EMBEDDING_MODEL', 'mistral-embed'),
127
+ chat_model: ENV.fetch('MISTRAL_CHAT_MODEL', 'mistral-large-latest')
128
+ )
129
+ end
130
+
131
+ # DeepSeek supports generation, but not embeddings.
132
+ if ENV['DEEPSEEK_API_KEY'].present?
133
+ config.add_provider(:deepseek, Prescient::Provider::DeepSeek,
134
+ api_key: ENV['DEEPSEEK_API_KEY'],
135
+ chat_model: ENV.fetch('DEEPSEEK_CHAT_MODEL', 'deepseek-v4-flash')
136
+ )
137
+ end
138
+
139
+ # xAI supports generation, but not embeddings.
140
+ if ENV['XAI_API_KEY'].present?
141
+ config.add_provider(:xai, Prescient::Provider::XAI,
142
+ api_key: ENV['XAI_API_KEY'],
143
+ chat_model: ENV.fetch('XAI_CHAT_MODEL', 'grok-4.5')
144
+ )
145
+ end
114
146
  end
115
147
 
116
148
  # Set default provider for Rails
117
149
  Rails.application.config.default_ai_provider = :ollama
118
150
  ```
119
151
 
120
- ### 4. Update Environment Variables
152
+ For YAML-based deployments, use the versioned configuration format and keep
153
+ credentials in environment variables:
154
+
155
+ ```ruby
156
+ Prescient.load_configuration('prescient.yml')
157
+ ```
158
+
159
+ Configuration precedence is CLI overrides, environment defaults and
160
+ references, YAML values, then built-in defaults. The generated
161
+ `prescient config example` file includes the current JSON Schema URL.
162
+
163
+ ### 4. Mount the REST API
164
+
165
+ `Prescient::API` is Rack-compatible and can be mounted directly in a Rails
166
+ route set. The API keeps provider execution on `Prescient::Client` and exposes
167
+ only generic operations:
168
+
169
+ ```ruby
170
+ # config/routes.rb
171
+ prescient_api = Prescient::API.new(
172
+ authentication: lambda { |env|
173
+ expected_token = ENV.fetch('PRESCIENT_API_TOKEN', nil)
174
+ expected_token && env['HTTP_AUTHORIZATION'] == "Bearer #{expected_token}"
175
+ }
176
+ )
177
+
178
+ mount prescient_api => '/prescient', as: :prescient_api
179
+ ```
180
+
181
+ This makes the following routes available under `/prescient`:
182
+
183
+ | Method | Path | Purpose |
184
+ | --- | --- | --- |
185
+ | `GET` | `/healthz` | Liveness check |
186
+ | `GET` | `/readyz` | Readiness check |
187
+ | `GET` | `/v1/version` | Library and API versions |
188
+ | `GET` | `/v1/providers` | Configured providers |
189
+ | `GET` | `/v1/models` | Available models, optionally filtered by provider |
190
+ | `GET` | `/v1/capabilities` | Provider capabilities |
191
+ | `GET` | `/v1/health` | Provider health |
192
+ | `POST` | `/v1/generate` | Text generation |
193
+ | `POST` | `/v1/embeddings` | Single embedding |
194
+ | `POST` | `/v1/embeddings/batch` | Bounded batch embeddings |
195
+
196
+ For example:
197
+
198
+ ```bash
199
+ curl http://localhost:3000/prescient/healthz
200
+
201
+ curl -X POST http://localhost:3000/prescient/v1/generate \
202
+ -H "Authorization: Bearer ${PRESCIENT_API_TOKEN}" \
203
+ -H 'Content-Type: application/json' \
204
+ -d '{"prompt":"Explain Ruby fibers"}'
205
+ ```
206
+
207
+ Responses include a request ID. Request bodies are size-limited, batch inputs
208
+ are bounded, and JSON errors do not expose raw provider response bodies. Keep
209
+ the API behind the application’s normal TLS, authentication, rate-limiting,
210
+ and observability controls.
211
+
212
+ ### 5. Update Environment Variables
121
213
 
122
214
  ```bash
123
215
  # .env or environment configuration
@@ -140,9 +232,27 @@ ANTHROPIC_MODEL=claude-sonnet-4-20250514
140
232
  HUGGINGFACE_API_KEY=your_huggingface_api_key
141
233
  HUGGINGFACE_EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
142
234
  HUGGINGFACE_CHAT_MODEL=google/gemma-2-2b-it
235
+
236
+ # Google Gemini
237
+ GEMINI_API_KEY=your_gemini_api_key
238
+ GEMINI_EMBEDDING_MODEL=gemini-embedding-001
239
+ GEMINI_CHAT_MODEL=gemini-2.5-flash
240
+
241
+ # Mistral
242
+ MISTRAL_API_KEY=your_mistral_api_key
243
+ MISTRAL_EMBEDDING_MODEL=mistral-embed
244
+ MISTRAL_CHAT_MODEL=mistral-large-latest
245
+
246
+ # DeepSeek (generation only)
247
+ DEEPSEEK_API_KEY=your_deepseek_api_key
248
+ DEEPSEEK_CHAT_MODEL=deepseek-v4-flash
249
+
250
+ # xAI (generation only)
251
+ XAI_API_KEY=your_xai_api_key
252
+ XAI_CHAT_MODEL=grok-4.5
143
253
  ```
144
254
 
145
- ### 5. Update Controllers
255
+ ### 6. Update Controllers
146
256
 
147
257
  **Before:**
148
258
 
@@ -188,7 +298,7 @@ class Api::V1::AiQueriesController < ApplicationController
188
298
  end
189
299
  ```
190
300
 
191
- ### 6. Health Check Integration
301
+ ### 7. Health Check Integration
192
302
 
193
303
  ```ruby
194
304
  # app/controllers/api/v1/system/health_controller.rb
@@ -221,7 +331,7 @@ class Api::V1::System::HealthController < ApplicationController
221
331
  }
222
332
 
223
333
  # Check backup providers
224
- backup_providers = [:openai, :anthropic, :huggingface] - [primary_provider]
334
+ backup_providers = %i[openai anthropic huggingface gemini mistral deepseek xai] - [primary_provider]
225
335
  providers[:backups] = backup_providers.map do |provider|
226
336
  {
227
337
  name: provider,
@@ -241,7 +351,7 @@ class Api::V1::System::HealthController < ApplicationController
241
351
  end
242
352
  ```
243
353
 
244
- ### 7. Migration Strategy
354
+ ### 8. Migration Strategy
245
355
 
246
356
  1. **Phase 1: Side-by-side deployment**
247
357
 
@@ -260,7 +370,7 @@ end
260
370
  - Update all controllers to use AIService
261
371
  - Clean up unused code
262
372
 
263
- ### 8. Testing Updates
373
+ ### 9. Testing Updates
264
374
 
265
375
  ```ruby
266
376
  # test/services/ai_service_test.rb
@@ -285,7 +395,7 @@ class AIServiceTest < ActiveSupport::TestCase
285
395
  end
286
396
  ```
287
397
 
288
- ### 9. Monitoring and Logging
398
+ ### 10. Monitoring and Logging
289
399
 
290
400
  ```ruby
291
401
  # config/initializers/prescient_monitoring.rb
@@ -309,7 +419,7 @@ end
309
419
  PrescientMonitoring.setup! if Rails.env.production?
310
420
  ```
311
421
 
312
- ### 10. Performance Optimization
422
+ ### 11. Performance Optimization
313
423
 
314
424
  ```ruby
315
425
  # app/services/ai_service.rb (enhanced)