prescient 0.1.0 → 0.2.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: 62c70c521da514a785f44beb284287d56a3affd451160bcc8bcad26fff713303
4
- data.tar.gz: 4b7a41690ae8395cb57ccefee607764d850256d6fe9c4341db038e28ee67c7ce
3
+ metadata.gz: b2b41fc6acb2528a3d74e5bbc58f777a34ead604d3f7bc4e58cc1ff4f8709142
4
+ data.tar.gz: 665efb1e4b6cc1ed526e91470e7c06278461e98e9d81f0ace34b0872c456251f
5
5
  SHA512:
6
- metadata.gz: 5cff60610144acef5b2be9693dbe87f1bb7b231dae219ac5cc826c2720fb383ed7c6df580cfe9a9ac26eb56812bc841178d605272adde63054506006cfdd9575
7
- data.tar.gz: c6f3eef2edcd1f53eb0c41a779db4b4aae36990e40b91ff406077353fd8c9d3b10332c2c5701a17ba88c3fb2debec6eb4e8560eb14a9c483e387dc146d5f6b18
6
+ metadata.gz: 23eeca8c5353bcb4219a634905a7f6dc565acbfde665e0e71a0682eb3277abb9384882f70afe168ee27c435f049048f0a715b92daac3fcdc8f34f4ff2b4f7de0
7
+ data.tar.gz: 77eccf05a9bedfad68de0a262b4ebf32d35b1c1a6d4c35f0327c1c6d16814841a6361b5123b27a8ba6f05e9d999256e2b330200d3e4c7eda0763010c98759c44
data/.rubocop.yml CHANGED
@@ -9,8 +9,8 @@ plugins:
9
9
  - rubocop-rake
10
10
 
11
11
  AllCops:
12
- # Target Ruby 3.0+ (matches gemspec requirement)
13
- TargetRubyVersion: 3.0
12
+ # Target Ruby 3.1+ (matches gemspec requirement)
13
+ TargetRubyVersion: 3.1
14
14
 
15
15
  # Use new cops by default
16
16
  NewCops: enable
@@ -169,11 +169,13 @@ Metrics/ModuleLength:
169
169
  Max: 150
170
170
 
171
171
  Metrics/ClassLength:
172
+ Enabled: false
172
173
  Max: 150
173
174
  Exclude:
174
175
  - 'test/**/*'
175
176
 
176
177
  Metrics/MethodLength:
178
+ Enabled: false
177
179
  Max: 25
178
180
  Exclude:
179
181
  - 'test/**/*'
@@ -181,6 +183,7 @@ Metrics/MethodLength:
181
183
  - 'lib/prescient/provider/*.rb'
182
184
 
183
185
  Metrics/BlockLength:
186
+ Enabled: false
184
187
  Max: 25
185
188
  Exclude:
186
189
  - 'test/**/*'
@@ -199,6 +202,7 @@ Metrics/CyclomaticComplexity:
199
202
  - 'lib/prescient/provider/*.rb'
200
203
 
201
204
  Metrics/PerceivedComplexity:
205
+ Enabled: false
202
206
  Max: 8
203
207
  Exclude:
204
208
  - 'lib/prescient/provider/*.rb'
data/.yardopts ADDED
@@ -0,0 +1,14 @@
1
+ --markup markdown
2
+ --markup-provider kramdown
3
+ --main README.md
4
+ --output-dir doc
5
+ --protected
6
+ --private
7
+ --title "Prescient Documentation"
8
+ lib/**/*.rb
9
+ -
10
+ README.md
11
+ CHANGELOG.md
12
+ LICENSE.txt
13
+ INTEGRATION_GUIDE.md
14
+ VECTOR_SEARCH_GUIDE.md
data/CHANGELOG.md ADDED
@@ -0,0 +1,64 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2025-08-05
9
+
10
+ ### Added
11
+
12
+ - Added new featire: Providers fallbacks mechanism
13
+
14
+ ## [0.1.0] - 2025-08-05
15
+
16
+ ### Added
17
+
18
+ - Initial release of Prescient gem
19
+ - Support for four AI providers:
20
+ - **Ollama**: Local AI provider with embedding and text generation
21
+ - **Anthropic**: Claude models for text generation
22
+ - **OpenAI**: GPT models and embeddings
23
+ - **HuggingFace**: Open-source models and embeddings
24
+ - Unified client interface for all providers
25
+ - Comprehensive error handling with provider-specific exceptions:
26
+ - `ConnectionError` for network issues
27
+ - `AuthenticationError` for API key problems
28
+ - `RateLimitError` for rate limiting
29
+ - `ModelNotAvailableError` for missing models
30
+ - `InvalidResponseError` for malformed responses
31
+ - Automatic retry logic with configurable attempts and delays
32
+ - Health monitoring capabilities for all providers
33
+ - Environment variable configuration support
34
+ - Programmatic configuration system
35
+ - Context-aware generation support with context items
36
+ - Text preprocessing and embedding normalization
37
+ - Provider availability checking
38
+ - Model listing capabilities (where supported)
39
+ - Comprehensive test suite with RSpec
40
+ - Documentation and usage examples
41
+
42
+ ### Provider-Specific Features
43
+
44
+ - **Ollama**: Model management (pull, list), local deployment
45
+ - **Anthropic**: Latest Claude 3 models (Haiku, Sonnet, Opus)
46
+ - **OpenAI**: Multiple embedding dimensions, latest GPT models
47
+ - **HuggingFace**: Open-source model support, research-friendly API
48
+
49
+ ### Development
50
+
51
+ - RSpec test suite with WebMock and VCR
52
+ - RuboCop code style enforcement
53
+ - SimpleCov test coverage reporting
54
+ - Comprehensive documentation
55
+ - Example usage scripts
56
+ - Rake tasks for testing and linting
57
+
58
+ ## [0.0.0] - 2025-08-05
59
+
60
+ ### Added
61
+
62
+ - Project initialization
63
+ - Basic gem structure
64
+ - Core interfaces defined
data/CHANGELOG.pdf ADDED
Binary file
@@ -0,0 +1,363 @@
1
+ # AI Providers Integration Guide
2
+
3
+ This guide explains how to integrate the AI Providers gem into your existing Rails AI application.
4
+
5
+ ## Integration Steps
6
+
7
+ ### 1. Update Your Gemfile
8
+
9
+ ```ruby
10
+ # Add to your Gemfile
11
+ gem 'prescient', path: './prescient_gem' # Local development
12
+ # OR when published:
13
+ # gem 'prescient', '~> 0.1.0'
14
+ ```
15
+
16
+ ### 2. Replace Existing AI Service
17
+
18
+ **Before (Original OllamaService):**
19
+
20
+ ```ruby
21
+ # app/services/ollama_service.rb
22
+ class OllamaService
23
+ def generate_embedding(text)
24
+ # Direct Ollama API calls
25
+ end
26
+
27
+ def generate_response(prompt, context_items)
28
+ # Direct Ollama API calls
29
+ end
30
+ end
31
+ ```
32
+
33
+ **After (Using AI Providers Gem):**
34
+
35
+ ```ruby
36
+ # app/services/ai_service.rb
37
+ class AIService
38
+ def self.client(provider = nil)
39
+ @clients ||= {}
40
+ provider_name = provider || Rails.application.config.default_ai_provider
41
+ @clients[provider_name] ||= Prescient.client(provider_name)
42
+ end
43
+
44
+ def self.generate_embedding(text, provider: nil)
45
+ client(provider).generate_embedding(text)
46
+ rescue Prescient::Error => e
47
+ Rails.logger.error "AI embedding generation failed: #{e.message}"
48
+ raise
49
+ end
50
+
51
+ def self.generate_response(prompt, context_items = [], provider: nil, **options)
52
+ client(provider).generate_response(prompt, context_items, **options)
53
+ rescue Prescient::Error => e
54
+ Rails.logger.error "AI response generation failed: #{e.message}"
55
+ raise
56
+ end
57
+
58
+ def self.health_check(provider: nil)
59
+ client(provider).health_check
60
+ rescue Prescient::Error => e
61
+ { status: 'unhealthy', error: e.message }
62
+ end
63
+ end
64
+ ```
65
+
66
+ ### 3. Configuration
67
+
68
+ **Create initializer:**
69
+
70
+ ```ruby
71
+ # config/initializers/prescient.rb
72
+ Prescient.configure do |config|
73
+ config.default_provider = Rails.env.production? ? :openai : :ollama
74
+ config.timeout = 60
75
+ config.retry_attempts = 3
76
+ config.retry_delay = 1.0
77
+
78
+ # Ollama (Local/Development)
79
+ config.add_provider(:ollama, Prescient::Ollama::Provider,
80
+ url: ENV.fetch('OLLAMA_URL', 'http://localhost:11434'),
81
+ embedding_model: ENV.fetch('OLLAMA_EMBEDDING_MODEL', 'nomic-embed-text'),
82
+ chat_model: ENV.fetch('OLLAMA_CHAT_MODEL', 'llama3.1:8b'),
83
+ timeout: 120
84
+ )
85
+
86
+ # OpenAI (Production)
87
+ if ENV['OPENAI_API_KEY'].present?
88
+ config.add_provider(:openai, Prescient::OpenAI::Provider,
89
+ api_key: ENV['OPENAI_API_KEY'],
90
+ embedding_model: ENV.fetch('OPENAI_EMBEDDING_MODEL', 'text-embedding-3-small'),
91
+ chat_model: ENV.fetch('OPENAI_CHAT_MODEL', 'gpt-3.5-turbo')
92
+ )
93
+ end
94
+
95
+ # Anthropic (Alternative)
96
+ if ENV['ANTHROPIC_API_KEY'].present?
97
+ config.add_provider(:anthropic, Prescient::Anthropic::Provider,
98
+ api_key: ENV['ANTHROPIC_API_KEY'],
99
+ model: ENV.fetch('ANTHROPIC_MODEL', 'claude-3-haiku-20240307')
100
+ )
101
+ end
102
+
103
+ # HuggingFace (Research/Open Source)
104
+ if ENV['HUGGINGFACE_API_KEY'].present?
105
+ config.add_provider(:huggingface, Prescient::HuggingFace::Provider,
106
+ api_key: ENV['HUGGINGFACE_API_KEY'],
107
+ embedding_model: ENV.fetch('HUGGINGFACE_EMBEDDING_MODEL', 'sentence-transformers/all-MiniLM-L6-v2'),
108
+ chat_model: ENV.fetch('HUGGINGFACE_CHAT_MODEL', 'microsoft/DialoGPT-medium')
109
+ )
110
+ end
111
+ end
112
+
113
+ # Set default provider for Rails
114
+ Rails.application.config.default_ai_provider = :ollama
115
+ ```
116
+
117
+ ### 4. Update Environment Variables
118
+
119
+ ```bash
120
+ # .env or environment configuration
121
+
122
+ # Ollama (Local)
123
+ OLLAMA_URL=http://localhost:11434
124
+ OLLAMA_EMBEDDING_MODEL=nomic-embed-text
125
+ OLLAMA_CHAT_MODEL=llama3.1:8b
126
+
127
+ # OpenAI (Production)
128
+ OPENAI_API_KEY=your_openai_api_key
129
+ OPENAI_EMBEDDING_MODEL=text-embedding-3-small
130
+ OPENAI_CHAT_MODEL=gpt-3.5-turbo
131
+
132
+ # Anthropic (Alternative)
133
+ ANTHROPIC_API_KEY=your_anthropic_api_key
134
+ ANTHROPIC_MODEL=claude-3-haiku-20240307
135
+
136
+ # HuggingFace (Research)
137
+ HUGGINGFACE_API_KEY=your_huggingface_api_key
138
+ HUGGINGFACE_EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
139
+ HUGGINGFACE_CHAT_MODEL=microsoft/DialoGPT-medium
140
+ ```
141
+
142
+ ### 5. Update Controllers
143
+
144
+ **Before:**
145
+
146
+ ```ruby
147
+ class Api::V1::AiQueriesController < ApplicationController
148
+ def create
149
+ embedding = OllamaService.new.generate_embedding(params[:query])
150
+ # ... rest of the logic
151
+ end
152
+ end
153
+ ```
154
+
155
+ **After:**
156
+
157
+ ```ruby
158
+ class Api::V1::AiQueriesController < ApplicationController
159
+ def create
160
+ # Use default provider or specify one
161
+ embedding = AIService.generate_embedding(params[:query])
162
+
163
+ # Or use specific provider
164
+ # embedding = AIService.generate_embedding(params[:query], provider: :openai)
165
+
166
+ # ... rest of the logic remains the same
167
+ end
168
+
169
+ private
170
+
171
+ def generate_ai_response(query, context_items)
172
+ # Automatically uses configured provider with fallback
173
+ response = AIService.generate_response(
174
+ query,
175
+ context_items,
176
+ max_tokens: 2000,
177
+ temperature: 0.7
178
+ )
179
+
180
+ response[:response]
181
+ rescue Prescient::Error => e
182
+ Rails.logger.error "AI response failed: #{e.message}"
183
+ "I apologize, but I'm currently unable to generate a response. Please try again later."
184
+ end
185
+ end
186
+ ```
187
+
188
+ ### 6. Health Check Integration
189
+
190
+ ```ruby
191
+ # app/controllers/api/v1/system/health_controller.rb
192
+ class Api::V1::System::HealthController < ApplicationController
193
+ def show
194
+ health_status = {
195
+ database: database_health,
196
+ prescient: prescient_health,
197
+ overall: 'healthy'
198
+ }
199
+
200
+ # Set overall status based on critical components
201
+ if health_status[:prescient][:primary][:status] != 'healthy'
202
+ health_status[:overall] = 'degraded'
203
+ end
204
+
205
+ render json: health_status
206
+ end
207
+
208
+ private
209
+
210
+ def prescient_health
211
+ providers = {}
212
+
213
+ # Check primary provider
214
+ primary_provider = Rails.application.config.default_ai_provider
215
+ providers[:primary] = {
216
+ name: primary_provider,
217
+ **AIService.health_check(provider: primary_provider)
218
+ }
219
+
220
+ # Check backup providers
221
+ backup_providers = [:openai, :anthropic, :huggingface] - [primary_provider]
222
+ providers[:backups] = backup_providers.map do |provider|
223
+ {
224
+ name: provider,
225
+ **AIService.health_check(provider: provider)
226
+ }
227
+ end
228
+
229
+ providers
230
+ end
231
+
232
+ def database_health
233
+ ActiveRecord::Base.connection.execute('SELECT 1')
234
+ { status: 'healthy' }
235
+ rescue StandardError => e
236
+ { status: 'unhealthy', error: e.message }
237
+ end
238
+ end
239
+ ```
240
+
241
+ ### 7. Migration Strategy
242
+
243
+ 1. **Phase 1: Side-by-side deployment**
244
+
245
+ - Keep existing OllamaService
246
+ - Add AI Providers gem alongside
247
+ - Test thoroughly in development
248
+
249
+ 2. **Phase 2: Gradual migration**
250
+
251
+ - Update one controller at a time
252
+ - Use feature flags to switch between old/new systems
253
+ - Monitor performance and error rates
254
+
255
+ 3. **Phase 3: Complete migration**
256
+ - Remove old OllamaService
257
+ - Update all controllers to use AIService
258
+ - Clean up unused code
259
+
260
+ ### 8. Testing Updates
261
+
262
+ ```ruby
263
+ # spec/services/ai_service_spec.rb
264
+ RSpec.describe AIService do
265
+ before do
266
+ Prescient.configure do |config|
267
+ config.add_provider(:test, Prescient::Ollama::Provider,
268
+ url: 'http://localhost:11434',
269
+ embedding_model: 'test-embed',
270
+ chat_model: 'test-chat'
271
+ )
272
+ config.default_provider = :test
273
+ end
274
+ end
275
+
276
+ describe '.generate_embedding' do
277
+ it 'returns embedding vector' do
278
+ # Mock the provider response
279
+ allow_any_instance_of(Prescient::Ollama::Provider)
280
+ .to receive(:generate_embedding)
281
+ .and_return([0.1, 0.2, 0.3])
282
+
283
+ result = described_class.generate_embedding('test text')
284
+ expect(result).to eq([0.1, 0.2, 0.3])
285
+ end
286
+ end
287
+ end
288
+ ```
289
+
290
+ ### 9. Monitoring and Logging
291
+
292
+ ```ruby
293
+ # config/initializers/prescient_monitoring.rb
294
+ class PrescientMonitoring
295
+ def self.setup!
296
+ ActiveSupport::Notifications.subscribe('prescient.request') do |name, start, finish, id, payload|
297
+ duration = finish - start
298
+
299
+ Rails.logger.info "AI Provider Request: #{payload[:provider]} - #{payload[:operation]} - #{duration.round(3)}s"
300
+
301
+ # Send metrics to your monitoring system
302
+ # StatsD.increment('prescient.requests', tags: [
303
+ # "provider:#{payload[:provider]}",
304
+ # "operation:#{payload[:operation]}",
305
+ # "status:#{payload[:status]}"
306
+ # ])
307
+ end
308
+ end
309
+ end
310
+
311
+ PrescientMonitoring.setup! if Rails.env.production?
312
+ ```
313
+
314
+ ### 10. Performance Optimization
315
+
316
+ ```ruby
317
+ # app/services/ai_service.rb (enhanced)
318
+ class AIService
319
+ # Connection pooling for providers
320
+ def self.client(provider = nil)
321
+ @clients ||= {}
322
+ provider_name = provider || Rails.application.config.default_ai_provider
323
+
324
+ @clients[provider_name] ||= begin
325
+ # Use connection pooling for high-traffic applications
326
+ Prescient.client(provider_name)
327
+ end
328
+ end
329
+
330
+ # Caching for embeddings (optional)
331
+ def self.generate_embedding(text, provider: nil)
332
+ cache_key = "ai_embedding:#{ Digest::SHA256.hexdigest(text)}:#{ provider}"
333
+
334
+ Rails.cache.fetch(cache_key, expires_in: 1.hour) do
335
+ client(provider).generate_embedding(text)
336
+ end
337
+ rescue Prescient::Error => e
338
+ Rails.logger.error "AI embedding generation failed: #{e.message}"
339
+ raise
340
+ end
341
+ end
342
+ ```
343
+
344
+ ## Benefits of Migration
345
+
346
+ 1. **Provider Flexibility**: Easy switching between AI providers
347
+ 2. **Fallback Support**: Automatic fallback to backup providers
348
+ 3. **Better Error Handling**: Comprehensive error classification
349
+ 4. **Monitoring**: Built-in health checks and metrics
350
+ 5. **Testing**: Easier mocking and testing
351
+ 6. **Scalability**: Better support for different deployment scenarios
352
+ 7. **Cost Optimization**: Use local models for development, cloud for production
353
+
354
+ ## Rollback Plan
355
+
356
+ If issues arise, quickly rollback by:
357
+
358
+ 1. Revert initializer changes
359
+ 2. Switch controllers back to OllamaService
360
+ 3. Deploy previous version
361
+ 4. Debug issues separately
362
+
363
+ The gem structure allows for easy rollback since it's designed as a drop-in replacement.