llm_classifier 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/.devcontainer/Dockerfile +3 -0
- data/.devcontainer/compose.yaml +13 -0
- data/.devcontainer/devcontainer.json +43 -0
- data/.rspec +3 -0
- data/.rubocop.yml +45 -0
- data/CHANGELOG.md +30 -0
- data/LICENSE.txt +21 -0
- data/README.md +309 -0
- data/Rakefile +12 -0
- data/lib/llm_classifier/adapters/anthropic.rb +72 -0
- data/lib/llm_classifier/adapters/base.rb +18 -0
- data/lib/llm_classifier/adapters/openai.rb +70 -0
- data/lib/llm_classifier/adapters/ruby_llm.rb +30 -0
- data/lib/llm_classifier/classifier.rb +206 -0
- data/lib/llm_classifier/configuration.rb +38 -0
- data/lib/llm_classifier/content_fetchers/base.rb +18 -0
- data/lib/llm_classifier/content_fetchers/null.rb +12 -0
- data/lib/llm_classifier/content_fetchers/web.rb +178 -0
- data/lib/llm_classifier/knowledge.rb +44 -0
- data/lib/llm_classifier/rails/concerns/classifiable.rb +88 -0
- data/lib/llm_classifier/rails/generators/classifier_generator.rb +34 -0
- data/lib/llm_classifier/rails/generators/install_generator.rb +54 -0
- data/lib/llm_classifier/rails/generators/templates/classifier.rb.erb +48 -0
- data/lib/llm_classifier/rails/generators/templates/classifier_spec.rb.erb +15 -0
- data/lib/llm_classifier/rails/railtie.rb +18 -0
- data/lib/llm_classifier/result.rb +65 -0
- data/lib/llm_classifier/version.rb +5 -0
- data/lib/llm_classifier.rb +41 -0
- metadata +88 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class <%= class_name %> < LlmClassifier::Classifier
|
|
4
|
+
categories <%= categories_array.map { |c| ":#{c}" }.join(", ") %>
|
|
5
|
+
|
|
6
|
+
# Uncomment to enable multi-label classification
|
|
7
|
+
# multi_label true
|
|
8
|
+
|
|
9
|
+
# Uncomment to override the default model
|
|
10
|
+
# model "gpt-4o-mini"
|
|
11
|
+
|
|
12
|
+
# Uncomment to override the default adapter
|
|
13
|
+
# adapter :openai
|
|
14
|
+
|
|
15
|
+
system_prompt <<~PROMPT
|
|
16
|
+
You are a classifier. Analyze the given input and classify it into the appropriate category.
|
|
17
|
+
|
|
18
|
+
Categories:
|
|
19
|
+
<% categories_array.each do |cat| -%>
|
|
20
|
+
- <%= cat %>: [describe what this category means]
|
|
21
|
+
<% end -%>
|
|
22
|
+
|
|
23
|
+
Respond with ONLY a JSON object:
|
|
24
|
+
{
|
|
25
|
+
"categories": ["category"],
|
|
26
|
+
"confidence": 0.0-1.0,
|
|
27
|
+
"reasoning": "Brief explanation"
|
|
28
|
+
}
|
|
29
|
+
PROMPT
|
|
30
|
+
|
|
31
|
+
# Uncomment to add domain knowledge
|
|
32
|
+
# knowledge do
|
|
33
|
+
# important_terms %w[term1 term2 term3]
|
|
34
|
+
# category_hints({
|
|
35
|
+
# <%= categories_array.first %>: "hint for identifying this category"
|
|
36
|
+
# })
|
|
37
|
+
# end
|
|
38
|
+
|
|
39
|
+
# Uncomment to preprocess input
|
|
40
|
+
# before_classify do |input|
|
|
41
|
+
# input.downcase.strip
|
|
42
|
+
# end
|
|
43
|
+
|
|
44
|
+
# Uncomment to log or process results
|
|
45
|
+
# after_classify do |result|
|
|
46
|
+
# Rails.logger.info("Classification result: #{result.category}")
|
|
47
|
+
# end
|
|
48
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_helper"
|
|
4
|
+
|
|
5
|
+
RSpec.describe <%= class_name %> do
|
|
6
|
+
describe ".classify" do
|
|
7
|
+
it "classifies input into valid categories" do
|
|
8
|
+
# TODO: Add VCR cassette or mock the LLM response
|
|
9
|
+
result = described_class.classify("sample input text")
|
|
10
|
+
|
|
11
|
+
expect(result).to be_success
|
|
12
|
+
expect(result.category).to be_in(<%= categories_array %>)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LlmClassifier
|
|
4
|
+
module Rails
|
|
5
|
+
# Rails integration hook
|
|
6
|
+
class Railtie < ::Rails::Railtie
|
|
7
|
+
initializer "llm_classifier.configure_rails_initialization" do
|
|
8
|
+
# Set Rails logger as default
|
|
9
|
+
LlmClassifier.configuration.logger = ::Rails.logger
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
generators do
|
|
13
|
+
require_relative "generators/install_generator"
|
|
14
|
+
require_relative "generators/classifier_generator"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LlmClassifier
|
|
4
|
+
# Result object returned from classification operations
|
|
5
|
+
class Result
|
|
6
|
+
attr_reader :categories, :confidence, :reasoning, :raw_response, :metadata, :error
|
|
7
|
+
|
|
8
|
+
def initialize(categories: [], confidence: nil, reasoning: nil, raw_response: nil, error: nil, metadata: {})
|
|
9
|
+
@categories = Array(categories)
|
|
10
|
+
@confidence = confidence
|
|
11
|
+
@reasoning = reasoning
|
|
12
|
+
@raw_response = raw_response
|
|
13
|
+
@metadata = metadata
|
|
14
|
+
@error = error
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def success?
|
|
18
|
+
@error.nil?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def failure?
|
|
22
|
+
!success?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def category
|
|
26
|
+
@categories.first
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def multi_label?
|
|
30
|
+
@categories.size > 1
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def to_h
|
|
34
|
+
{
|
|
35
|
+
success: success?,
|
|
36
|
+
categories: @categories,
|
|
37
|
+
category: category,
|
|
38
|
+
confidence: @confidence,
|
|
39
|
+
reasoning: @reasoning,
|
|
40
|
+
metadata: @metadata,
|
|
41
|
+
error: @error
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class << self
|
|
46
|
+
def success(categories:, confidence: nil, reasoning: nil, raw_response: nil, metadata: {})
|
|
47
|
+
new(
|
|
48
|
+
categories: categories,
|
|
49
|
+
confidence: confidence,
|
|
50
|
+
reasoning: reasoning,
|
|
51
|
+
raw_response: raw_response,
|
|
52
|
+
metadata: metadata
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def failure(error:, raw_response: nil, metadata: {})
|
|
57
|
+
new(
|
|
58
|
+
error: error,
|
|
59
|
+
raw_response: raw_response,
|
|
60
|
+
metadata: metadata
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "zeitwerk"
|
|
4
|
+
|
|
5
|
+
loader = Zeitwerk::Loader.for_gem
|
|
6
|
+
loader.inflector.inflect(
|
|
7
|
+
"openai" => "OpenAI",
|
|
8
|
+
"ruby_llm" => "RubyLlm"
|
|
9
|
+
)
|
|
10
|
+
loader.ignore("#{__dir__}/llm_classifier/rails")
|
|
11
|
+
loader.setup
|
|
12
|
+
|
|
13
|
+
# LlmClassifier provides LLM-powered classification with pluggable adapters and Rails integration
|
|
14
|
+
module LlmClassifier
|
|
15
|
+
class Error < StandardError; end
|
|
16
|
+
class ConfigurationError < Error; end
|
|
17
|
+
class AdapterError < Error; end
|
|
18
|
+
class ClassificationError < Error; end
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
def configuration
|
|
22
|
+
@configuration ||= Configuration.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def configure
|
|
26
|
+
yield(configuration)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def reset_configuration!
|
|
30
|
+
@configuration = Configuration.new
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
loader.eager_load
|
|
36
|
+
|
|
37
|
+
# Load Rails integration if Rails is present
|
|
38
|
+
if defined?(Rails::Railtie)
|
|
39
|
+
require_relative "llm_classifier/rails/railtie"
|
|
40
|
+
require_relative "llm_classifier/rails/concerns/classifiable"
|
|
41
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: llm_classifier
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Dmitry Sychev
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: zeitwerk
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.6'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.6'
|
|
26
|
+
description: A flexible Ruby gem for building LLM-based classifiers. Define categories,
|
|
27
|
+
system prompts, and domain knowledge using a clean DSL. Supports multiple LLM backends
|
|
28
|
+
(ruby_llm, OpenAI, Anthropic) and integrates seamlessly with Rails.
|
|
29
|
+
email:
|
|
30
|
+
- dmitry.sychev@axiumfoundry.com
|
|
31
|
+
executables: []
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- ".devcontainer/Dockerfile"
|
|
36
|
+
- ".devcontainer/compose.yaml"
|
|
37
|
+
- ".devcontainer/devcontainer.json"
|
|
38
|
+
- ".rspec"
|
|
39
|
+
- ".rubocop.yml"
|
|
40
|
+
- CHANGELOG.md
|
|
41
|
+
- LICENSE.txt
|
|
42
|
+
- README.md
|
|
43
|
+
- Rakefile
|
|
44
|
+
- lib/llm_classifier.rb
|
|
45
|
+
- lib/llm_classifier/adapters/anthropic.rb
|
|
46
|
+
- lib/llm_classifier/adapters/base.rb
|
|
47
|
+
- lib/llm_classifier/adapters/openai.rb
|
|
48
|
+
- lib/llm_classifier/adapters/ruby_llm.rb
|
|
49
|
+
- lib/llm_classifier/classifier.rb
|
|
50
|
+
- lib/llm_classifier/configuration.rb
|
|
51
|
+
- lib/llm_classifier/content_fetchers/base.rb
|
|
52
|
+
- lib/llm_classifier/content_fetchers/null.rb
|
|
53
|
+
- lib/llm_classifier/content_fetchers/web.rb
|
|
54
|
+
- lib/llm_classifier/knowledge.rb
|
|
55
|
+
- lib/llm_classifier/rails/concerns/classifiable.rb
|
|
56
|
+
- lib/llm_classifier/rails/generators/classifier_generator.rb
|
|
57
|
+
- lib/llm_classifier/rails/generators/install_generator.rb
|
|
58
|
+
- lib/llm_classifier/rails/generators/templates/classifier.rb.erb
|
|
59
|
+
- lib/llm_classifier/rails/generators/templates/classifier_spec.rb.erb
|
|
60
|
+
- lib/llm_classifier/rails/railtie.rb
|
|
61
|
+
- lib/llm_classifier/result.rb
|
|
62
|
+
- lib/llm_classifier/version.rb
|
|
63
|
+
homepage: https://github.com/AxiumFoundry/llm_classifier
|
|
64
|
+
licenses:
|
|
65
|
+
- MIT
|
|
66
|
+
metadata:
|
|
67
|
+
homepage_uri: https://github.com/AxiumFoundry/llm_classifier
|
|
68
|
+
source_code_uri: https://github.com/AxiumFoundry/llm_classifier
|
|
69
|
+
changelog_uri: https://github.com/AxiumFoundry/llm_classifier/blob/main/CHANGELOG.md
|
|
70
|
+
rubygems_mfa_required: 'true'
|
|
71
|
+
rdoc_options: []
|
|
72
|
+
require_paths:
|
|
73
|
+
- lib
|
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
|
+
requirements:
|
|
76
|
+
- - ">="
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: 3.1.0
|
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '0'
|
|
84
|
+
requirements: []
|
|
85
|
+
rubygems_version: 3.6.9
|
|
86
|
+
specification_version: 4
|
|
87
|
+
summary: LLM-powered classification for Ruby with pluggable adapters and Rails integration
|
|
88
|
+
test_files: []
|