Rails AI Kit
AI-first toolkit for Rails — two core features today, more on the way.
Two main features
Rails AI Kit currently provides two independent feature sets. Use one, both, or add more as the gem evolves.
| Feature | What it does | Use when |
|---|---|---|
| 1. Guardrails | Run LLM generation through safety checks (toxicity, PII, hallucination, prompt injection). Generate → validate → score → allow/block. | You call an LLM and want to block unsafe outputs or toxic user inputs. |
| 2. Vector classification | Classify text using embeddings + pgvector. Train labels with examples; auto-classify on save or in batch. No ML training, no LLM per request. | You need categories (e.g. support tickets, content tags, document routing). |
More features (evals, tool use, etc.) are planned — the gem is actively developed.
Feature 1: Guardrails
Guardrails wrap LLM calls with safety checks. You get a generated response plus scores; you decide allow/block by threshold. Checks run on both the model output and the user prompt (so toxic or injection-style inputs are detected even if the model refuses to comply).
What you get
-
RailsAiKit.guard(prompt:, model:, checks:, threshold:)— One call: generate + run checks. ReturnsGuardResultwithoutput,safe?,scores,action(:allow/:block). - Guards: toxicity, PII, hallucination, prompt injection (each uses an LLM-as-judge or keyword rules).
- Prompt + output: Toxicity and prompt-injection also evaluate the user prompt; final toxicity = max(prompt_toxicity, output_toxicity). Keyword safety net for obvious offensive language.
-
Rails macro:
ai_generate :summary, from: :content, guards: [...]→article.ai_summary(generate then guard). -
Eval:
RailsAiKit.eval(dataset: "eval.json", model:)→ accuracy, hallucination rate, toxicity failures. -
AI Traces: Optional
rails_ai_tracestable +/ai_tracesdashboard to inspect prompts, responses, scores, and latency.
LLM providers
One config, same API: OpenAI, Anthropic (Claude), Google (Gemini), Groq, or custom (any OpenAI-compatible endpoint via llm_url + llm_key).
Quick example (Guardrails)
result = RailsAiKit.guard(
prompt: "What is the capital of France?",
model: "gpt-4o-mini",
checks: [:toxicity, :hallucination],
threshold: 0.8
)
result.output # => "The capital of France is Paris."
result.safe? # => true
result.scores # => { "toxicity" => 0.0, "hallucination" => 0.0, "label" => "factual" }
result.action # => :allowToxic or injection-style prompts are scored (including a keyword safety net); if any score exceeds threshold, action is :block.
Feature 2: Vector classification
Vector classification uses embeddings + pgvector to assign labels to text. You train each label with example phrases; the gem embeds them, stores one vector per label, and classifies new content by nearest-neighbor (cosine distance). No ML training and no LLM call per classification — only an embedding API (OpenAI or Cohere).
What you get
-
Train labels:
RailsAiKit.classifier("Article").train("sports", examples: ["football match", "cricket"])→ one vector per label inrails_ai_kit_labels. -
Auto-classify on save: Add
vector_classify :content, labels: ["sports", "politics", "tech"]to your model. On save, the gem embedscontent, stores it, compares to label vectors, and setslabelandconfidence_score. -
Classify without saving:
RailsAiKit.classifier("Article").classify("India won the cricket match")→{ label: "sports", confidence: 0.91 }. -
Batch classify:
RailsAiKit.classifier("Article").batch_classify(records, text_attribute: :content). -
Similarity search:
Article.similar_to("new iPhone launch", limit: 5). -
Filtering:
Article.where(label: "sports"),Article.where("confidence_score >= ?", 0.8).
Quick example (Vector classification)
# 1. Train labels once
c = RailsAiKit.classifier("Article")
c.train("sports", examples: ["football match", "cricket tournament"])
c.train("technology", examples: ["new iPhone launch", "AI update"])
# 2. Model
class Article < ApplicationRecord
vector_classify :content, labels: ["sports", "politics", "technology"]
end
# 3. Create record → auto-classified
article = Article.create!(content: "Apple released a new iPhone")
article.label # => "technology"
article.confidence_score # => 0.91Requirements
- Rails 6+
- PostgreSQL with pgvector (for vector classification only)
- Embedding API (OpenAI or Cohere) for vector classification
-
LLM API (OpenAI, Anthropic, Google, Groq, or custom) for Guardrails /
ai_generate/ Eval
Installation
# Gemfile
gem "rails_ai_kit"bundle install
rails g rails_ai_kit:install
rails db:migrateThe install generator adds:
-
pgvector and tables:
rails_ai_kit_labels(for vector classification),rails_ai_traces(for Guardrails tracing) -
Initializer:
config/initializers/rails_ai_kit.rb
Configuration
Edit config/initializers/rails_ai_kit.rb:
RailsAiKit.configure do |config|
# ----- Vector classification (embeddings) -----
config.embedding_provider = :openai
config.embedding_dimensions = 1536
config.api_keys = {
openai: ENV["OPENAI_API_KEY"],
cohere: ENV["COHERE_API_KEY"]
}
config.default_classifier_name = "default"
# ----- Guardrails (LLM) -----
config.llm_provider = :openai
config.default_llm_model = "gpt-4o-mini"
config.llm_api_keys = {
openai: ENV["OPENAI_API_KEY"],
anthropic: ENV["ANTHROPIC_API_KEY"],
google: ENV["GOOGLE_AI_API_KEY"],
groq: ENV["GROQ_API_KEY"]
}
# Custom endpoint:
# config.llm_provider = :custom
# config.llm_url = "https://your-llm.example.com/v1"
# config.llm_key = ENV["CUSTOM_LLM_KEY"]
config.trace_llm_calls = true
endUse env vars or Rails credentials; do not commit API keys.
Add vector columns (for vector classification only)
For models you want to classify:
rails g rails_ai_kit:vector_columns Article content
rails db:migrateAdds embedding, label, confidence_score to the table.
Usage in detail
Guardrails
| Method | Description |
|---|---|
RailsAiKit.guard(prompt:, model:, checks: [:toxicity, :hallucination], threshold: 0.8) |
Generate + run checks; returns GuardResult
|
result.output, result.safe?, result.scores, result.action
|
Response text, safe flag, scores hash, :allow / :block
|
RailsAiKit.eval(dataset: "path.json", model:) |
Run eval dataset; returns accuracy, hallucination rate, toxicity failures |
rails g rails_ai_kit:dashboard |
Add /ai_traces dashboard |
ai_generate macro (Guardrails):
class Article < ApplicationRecord
ai_generate :summary,
from: :content,
prompt_template: "Summarize in 2–3 sentences:\n\n%{text}",
guards: [:toxicity, :hallucination],
threshold: 0.85
end
article.ai_summary # => generated summary or nil if blockedVector classification
| Method | Description |
|---|---|
RailsAiKit.classifier("Article").train("label", examples: ["...", "..."]) |
Train a label with example texts |
RailsAiKit.classifier("Article").classify("some text") |
Classify without saving → { label:, confidence:, distance: }
|
RailsAiKit.classifier("Article").batch_classify(records, text_attribute: :content) |
Batch classify, set label and confidence_score on records |
Article.similar_to("query", limit: 5) |
Similarity search (nearest neighbors by embedding) |
Article.where(label: "sports") |
Filter by predicted label |
vector_classify macro:
class Article < ApplicationRecord
vector_classify :content,
labels: ["sports", "politics", "technology"],
classifier_name: "Article"
end
# On save: embed content → store embedding → set label & confidence_scoreEmbeddings (shared)
RailsAiKit.embed("some text")
RailsAiKit.embedding.embed_batch(["a", "b"])Generators
| Generator | Purpose |
|---|---|
rails g rails_ai_kit:install |
pgvector + rails_ai_kit_labels + rails_ai_traces + initializer |
rails g rails_ai_kit:vector_columns ModelName content_column |
Add embedding, label, confidence_score to a table (vector classification) |
rails g rails_ai_kit:dashboard |
Add AI Traces dashboard at /ai_traces (Guardrails) |
Configuration reference
| Option | Description | Default |
|---|---|---|
| Embeddings (vector classification) | ||
embedding_provider |
:openai or :cohere
|
:openai |
embedding_dimensions |
Vector size | 1536 |
api_keys |
Embedding API keys | {} |
default_classifier_name |
Classifier name when not specified | "default" |
| LLM (Guardrails) | ||
llm_provider |
:openai, :anthropic, :google, :groq, :custom
|
:openai |
llm_api_keys |
LLM API keys | {} |
llm_url, llm_key
|
Custom LLM endpoint | nil |
default_llm_model |
Default model for guard / ai_generate | nil |
trace_llm_calls |
Log guard calls to rails_ai_traces
|
true |
How it works
Guardrails
- You call
RailsAiKit.guard(prompt:, model:, checks:, threshold:). - The gem generates a response with the configured LLM.
- It runs the requested checks (toxicity, PII, hallucination, prompt injection) on the output and, for toxicity/prompt_injection, on the user prompt (in parallel where possible). Keyword rules backstop obvious offensive prompts.
- It merges scores and sets
actionto:blockif any score exceedsthreshold. - Optionally it records the run in
rails_ai_traces.
Vector classification
- You train labels with example texts; the gem embeds them and stores one vector per label in
rails_ai_kit_labels. - When you save a record with
vector_classify, the gem embeds the source column, stores the vector, and finds the nearest label (cosine distance). It setslabelandconfidence_score. - Similarity search uses the same embedding column and pgvector nearest-neighbor.
Roadmap
- Guardrails: More guards, configurable keyword lists, retry/fallback behavior.
- Vector classification: Hierarchical labels, confidence threshold, hybrid search, incremental learning.
- More features: Additional AI capabilities as the gem evolves.
Development
bundle install
bundle exec rake installLicense
MIT.
Related
- pgvector – Vector similarity search for Postgres
- Neighbor – Nearest neighbor search for Rails (used for vector classification)
Creator
Rohit Kushwaha — AI Engineer
