rack-ai 0.1.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +55 -0
- data/CHANGELOG.md +65 -0
- data/LICENSE +21 -0
- data/README.md +687 -0
- data/ROADMAP.md +203 -0
- data/Rakefile +40 -0
- data/benchmarks/performance_benchmark.rb +283 -0
- data/examples/rails_integration.rb +301 -0
- data/examples/sinatra_integration.rb +458 -0
- data/lib/rack/ai/configuration.rb +208 -0
- data/lib/rack/ai/features/caching.rb +278 -0
- data/lib/rack/ai/features/classification.rb +67 -0
- data/lib/rack/ai/features/enhancement.rb +219 -0
- data/lib/rack/ai/features/logging.rb +238 -0
- data/lib/rack/ai/features/moderation.rb +104 -0
- data/lib/rack/ai/features/routing.rb +143 -0
- data/lib/rack/ai/features/security.rb +275 -0
- data/lib/rack/ai/middleware.rb +268 -0
- data/lib/rack/ai/providers/base.rb +107 -0
- data/lib/rack/ai/providers/huggingface.rb +259 -0
- data/lib/rack/ai/providers/local.rb +152 -0
- data/lib/rack/ai/providers/openai.rb +246 -0
- data/lib/rack/ai/utils/logger.rb +111 -0
- data/lib/rack/ai/utils/metrics.rb +220 -0
- data/lib/rack/ai/utils/sanitizer.rb +200 -0
- data/lib/rack/ai/version.rb +7 -0
- data/lib/rack/ai.rb +48 -0
- data/rack-ai.gemspec +51 -0
- metadata +290 -0
@@ -0,0 +1,301 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Rails Integration Example for Rack::AI
|
4
|
+
#
|
5
|
+
# This example shows how to integrate Rack::AI with a Rails application
|
6
|
+
# for AI-powered request processing, security, and content enhancement.
|
7
|
+
|
8
|
+
require "rails"
|
9
|
+
require "rack/ai"
|
10
|
+
|
11
|
+
class Application < Rails::Application
|
12
|
+
# Basic Rack::AI configuration
|
13
|
+
config.middleware.use Rack::AI::Middleware,
|
14
|
+
provider: :openai,
|
15
|
+
api_key: ENV["OPENAI_API_KEY"],
|
16
|
+
features: [:classification, :moderation, :security, :caching],
|
17
|
+
fail_safe: true,
|
18
|
+
async_processing: true
|
19
|
+
|
20
|
+
# Configure AI features
|
21
|
+
config.before_initialize do
|
22
|
+
Rack::AI.configure do |config|
|
23
|
+
# Provider settings
|
24
|
+
config.provider = :openai
|
25
|
+
config.api_key = ENV["OPENAI_API_KEY"]
|
26
|
+
config.timeout = 30
|
27
|
+
config.retries = 3
|
28
|
+
|
29
|
+
# Feature configuration
|
30
|
+
config.features = [:classification, :moderation, :security, :caching, :logging]
|
31
|
+
config.fail_safe = true
|
32
|
+
config.async_processing = true
|
33
|
+
|
34
|
+
# Security settings
|
35
|
+
config.sanitize_logs = true
|
36
|
+
config.allowed_data_types = [:headers, :query_params]
|
37
|
+
|
38
|
+
# Classification settings
|
39
|
+
config.classification.confidence_threshold = 0.8
|
40
|
+
config.classification.categories = [:spam, :bot, :human, :suspicious]
|
41
|
+
|
42
|
+
# Moderation settings
|
43
|
+
config.moderation.toxicity_threshold = 0.7
|
44
|
+
config.moderation.check_response = false
|
45
|
+
config.moderation.block_on_violation = true
|
46
|
+
|
47
|
+
# Caching settings
|
48
|
+
config.caching.predictive_enabled = true
|
49
|
+
config.caching.redis_url = ENV["REDIS_URL"] || "redis://localhost:6379"
|
50
|
+
|
51
|
+
# Routing settings
|
52
|
+
config.routing.smart_routing_enabled = true
|
53
|
+
config.routing.suspicious_route = "/security/verify"
|
54
|
+
config.routing.bot_route = "/api/bot"
|
55
|
+
|
56
|
+
# Logging and monitoring
|
57
|
+
config.log_level = :info
|
58
|
+
config.metrics_enabled = true
|
59
|
+
config.explain_decisions = Rails.env.development?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Example Rails controller that uses AI results
|
65
|
+
class ApplicationController < ActionController::Base
|
66
|
+
before_action :check_ai_results
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def check_ai_results
|
71
|
+
ai_results = request.env["rack.ai"]&.dig(:results) || {}
|
72
|
+
|
73
|
+
# Handle classification results
|
74
|
+
if ai_results[:classification]
|
75
|
+
classification = ai_results[:classification]
|
76
|
+
|
77
|
+
case classification[:classification]
|
78
|
+
when :spam
|
79
|
+
render json: { error: "Request blocked as spam" }, status: 403
|
80
|
+
return
|
81
|
+
when :suspicious
|
82
|
+
# Log suspicious activity
|
83
|
+
Rails.logger.warn("Suspicious request detected", {
|
84
|
+
ip: request.remote_ip,
|
85
|
+
path: request.path,
|
86
|
+
confidence: classification[:confidence]
|
87
|
+
})
|
88
|
+
when :bot
|
89
|
+
# Set special headers for bot requests
|
90
|
+
response.headers["X-Bot-Detected"] = "true"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Handle security results
|
95
|
+
if ai_results[:security]
|
96
|
+
security = ai_results[:security]
|
97
|
+
|
98
|
+
if security[:threat_level] == :high
|
99
|
+
render json: { error: "Security threat detected" }, status: 403
|
100
|
+
return
|
101
|
+
elsif security[:threat_level] == :medium
|
102
|
+
# Add security headers
|
103
|
+
response.headers["X-Security-Alert"] = "medium"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Handle moderation results
|
108
|
+
if ai_results[:moderation] && ai_results[:moderation][:flagged]
|
109
|
+
render json: { error: "Content moderation violation" }, status: 400
|
110
|
+
return
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Example API controller with AI-enhanced responses
|
116
|
+
class Api::V1::BaseController < ApplicationController
|
117
|
+
before_action :authenticate_api_key
|
118
|
+
after_action :add_ai_headers
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def authenticate_api_key
|
123
|
+
api_key = request.headers["X-API-Key"]
|
124
|
+
|
125
|
+
# Use AI classification to detect suspicious API usage
|
126
|
+
ai_results = request.env["rack.ai"]&.dig(:results) || {}
|
127
|
+
|
128
|
+
if ai_results[:classification]&.dig(:classification) == :suspicious
|
129
|
+
# Require additional verification for suspicious requests
|
130
|
+
head :unauthorized unless verify_additional_auth
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def add_ai_headers
|
135
|
+
ai_results = request.env["rack.ai"]&.dig(:results) || {}
|
136
|
+
|
137
|
+
if ai_results[:classification]
|
138
|
+
response.headers["X-AI-Classification"] = ai_results[:classification][:classification].to_s
|
139
|
+
response.headers["X-AI-Confidence"] = ai_results[:classification][:confidence].to_s
|
140
|
+
end
|
141
|
+
|
142
|
+
if ai_results[:caching] && ai_results[:caching][:should_prefetch]
|
143
|
+
response.headers["X-AI-Prefetch-Recommended"] = "true"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def verify_additional_auth
|
148
|
+
# Additional authentication logic for suspicious requests
|
149
|
+
true
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Example model that uses AI insights for analytics
|
154
|
+
class RequestAnalytics
|
155
|
+
def self.process_ai_insights(env)
|
156
|
+
ai_results = env["rack.ai"]&.dig(:results) || {}
|
157
|
+
|
158
|
+
# Store classification data
|
159
|
+
if ai_results[:classification]
|
160
|
+
create_classification_record(env, ai_results[:classification])
|
161
|
+
end
|
162
|
+
|
163
|
+
# Store security events
|
164
|
+
if ai_results[:security] && ai_results[:security][:threat_level] != :low
|
165
|
+
create_security_event(env, ai_results[:security])
|
166
|
+
end
|
167
|
+
|
168
|
+
# Update traffic patterns for caching optimization
|
169
|
+
if ai_results[:caching]
|
170
|
+
update_traffic_patterns(env, ai_results[:caching])
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
private
|
175
|
+
|
176
|
+
def self.create_classification_record(env, classification)
|
177
|
+
# Store in database for analytics
|
178
|
+
ClassificationLog.create!(
|
179
|
+
ip_address: env["REMOTE_ADDR"],
|
180
|
+
path: env["PATH_INFO"],
|
181
|
+
classification: classification[:classification],
|
182
|
+
confidence: classification[:confidence],
|
183
|
+
user_agent: env["HTTP_USER_AGENT"],
|
184
|
+
timestamp: Time.current
|
185
|
+
)
|
186
|
+
end
|
187
|
+
|
188
|
+
def self.create_security_event(env, security)
|
189
|
+
SecurityEvent.create!(
|
190
|
+
ip_address: env["REMOTE_ADDR"],
|
191
|
+
path: env["PATH_INFO"],
|
192
|
+
threat_level: security[:threat_level],
|
193
|
+
threats: security[:injection_detection][:threats],
|
194
|
+
timestamp: Time.current
|
195
|
+
)
|
196
|
+
end
|
197
|
+
|
198
|
+
def self.update_traffic_patterns(env, caching)
|
199
|
+
# Update Redis with traffic patterns for AI caching
|
200
|
+
pattern_key = "traffic_pattern:#{env['PATH_INFO']}"
|
201
|
+
|
202
|
+
Redis.current.hincrby(pattern_key, "requests", 1)
|
203
|
+
Redis.current.hset(pattern_key, "last_access", Time.current.to_i)
|
204
|
+
|
205
|
+
if caching[:should_prefetch]
|
206
|
+
Redis.current.sadd("prefetch_candidates", env["PATH_INFO"])
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Example middleware for custom AI processing
|
212
|
+
class CustomAIMiddleware
|
213
|
+
def initialize(app)
|
214
|
+
@app = app
|
215
|
+
end
|
216
|
+
|
217
|
+
def call(env)
|
218
|
+
# Custom pre-processing
|
219
|
+
add_custom_ai_context(env)
|
220
|
+
|
221
|
+
status, headers, body = @app.call(env)
|
222
|
+
|
223
|
+
# Custom post-processing with AI results
|
224
|
+
process_ai_results(env)
|
225
|
+
|
226
|
+
[status, headers, body]
|
227
|
+
end
|
228
|
+
|
229
|
+
private
|
230
|
+
|
231
|
+
def add_custom_ai_context(env)
|
232
|
+
# Add custom context for AI processing
|
233
|
+
env["rack.ai.custom"] = {
|
234
|
+
user_tier: extract_user_tier(env),
|
235
|
+
api_version: extract_api_version(env),
|
236
|
+
client_type: detect_client_type(env)
|
237
|
+
}
|
238
|
+
end
|
239
|
+
|
240
|
+
def process_ai_results(env)
|
241
|
+
ai_results = env["rack.ai"]&.dig(:results) || {}
|
242
|
+
|
243
|
+
# Custom business logic based on AI results
|
244
|
+
if ai_results[:classification]&.dig(:classification) == :bot
|
245
|
+
# Track bot usage for billing
|
246
|
+
BotUsageTracker.increment(env["HTTP_X_API_KEY"])
|
247
|
+
end
|
248
|
+
|
249
|
+
# Store analytics
|
250
|
+
RequestAnalytics.process_ai_insights(env)
|
251
|
+
end
|
252
|
+
|
253
|
+
def extract_user_tier(env)
|
254
|
+
# Extract user tier from headers or database
|
255
|
+
env["HTTP_X_USER_TIER"] || "free"
|
256
|
+
end
|
257
|
+
|
258
|
+
def extract_api_version(env)
|
259
|
+
env["HTTP_X_API_VERSION"] || "v1"
|
260
|
+
end
|
261
|
+
|
262
|
+
def detect_client_type(env)
|
263
|
+
user_agent = env["HTTP_USER_AGENT"] || ""
|
264
|
+
|
265
|
+
return "mobile" if user_agent.match?(/Mobile|Android|iPhone/i)
|
266
|
+
return "browser" if user_agent.match?(/Mozilla|Chrome|Safari/i)
|
267
|
+
return "api_client" if user_agent.match?(/curl|HTTPie|Postman/i)
|
268
|
+
|
269
|
+
"unknown"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# Configuration for different environments
|
274
|
+
case Rails.env
|
275
|
+
when "development"
|
276
|
+
# Development-specific AI configuration
|
277
|
+
Rack::AI.configure do |config|
|
278
|
+
config.explain_decisions = true
|
279
|
+
config.log_level = :debug
|
280
|
+
config.provider = :local # Use local AI for development
|
281
|
+
config.api_url = "http://localhost:8080"
|
282
|
+
end
|
283
|
+
|
284
|
+
when "test"
|
285
|
+
# Test-specific configuration
|
286
|
+
Rack::AI.configure do |config|
|
287
|
+
config.features = [] # Disable AI features in tests
|
288
|
+
config.fail_safe = true
|
289
|
+
end
|
290
|
+
|
291
|
+
when "production"
|
292
|
+
# Production-specific configuration
|
293
|
+
Rack::AI.configure do |config|
|
294
|
+
config.provider = :openai
|
295
|
+
config.api_key = ENV["OPENAI_API_KEY"]
|
296
|
+
config.timeout = 10 # Shorter timeout in production
|
297
|
+
config.retries = 2
|
298
|
+
config.explain_decisions = false
|
299
|
+
config.sanitize_logs = true
|
300
|
+
end
|
301
|
+
end
|