riffer 0.4.2 → 0.5.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 +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +7 -0
- data/README.md +4 -5
- data/lib/riffer/agent.rb +30 -1
- data/lib/riffer/providers/base.rb +0 -26
- data/lib/riffer/providers/open_ai.rb +6 -11
- data/lib/riffer/providers/repository.rb +15 -0
- data/lib/riffer/providers/test.rb +6 -5
- data/lib/riffer/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 12e6843cdf4824294d9c9470c2dad55125bfa490b49389530145bd334041ce15
|
|
4
|
+
data.tar.gz: 636133b4f5b2a046311a33a3b294ce2eb893bcb3a16292bd83198fc24f3dc500
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a26010e36c164851b3a9cbd6d3b7eebd9dcd935d4fdd405793998d2760b871b01a487724a8628eddc6bf366db164f924990ee12a2c93f99602e2c0f99c341d88
|
|
7
|
+
data.tar.gz: 18428555a37e27ee29c35d21c7b1f6f00f988a22e02e6a25141d6a3d6b9d0c49da43a7bf408886d28734e485fd7ac32015643ac7d1c9fe2406bffd6d9a6602d7
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.5.0](https://github.com/bottrall/riffer/compare/riffer/v0.4.2...riffer/v0.5.0) (2026-01-06)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* streaming via agents ([#63](https://github.com/bottrall/riffer/issues/63)) ([b4171c2](https://github.com/bottrall/riffer/commit/b4171c20f64a7ada1264ce90ab5278c19ff8a47a))
|
|
14
|
+
|
|
8
15
|
## [0.4.2](https://github.com/bottrall/riffer/compare/riffer/v0.4.1...riffer/v0.4.2) (2025-12-29)
|
|
9
16
|
|
|
10
17
|
|
data/README.md
CHANGED
|
@@ -68,13 +68,12 @@ puts agent.generate('Hello world')
|
|
|
68
68
|
# => "Hello world"
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
Streaming example
|
|
71
|
+
Streaming example:
|
|
72
72
|
|
|
73
73
|
```ruby
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
puts chunk.content
|
|
74
|
+
agent = EchoAgent.new
|
|
75
|
+
agent.stream('Tell me a story').each do |event|
|
|
76
|
+
print event.content
|
|
78
77
|
end
|
|
79
78
|
```
|
|
80
79
|
|
data/lib/riffer/agent.rb
CHANGED
|
@@ -91,6 +91,31 @@ class Riffer::Agent
|
|
|
91
91
|
extract_final_response
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
+
# Streams a response from the agent
|
|
95
|
+
# @param prompt_or_messages [String, Array<Hash, Riffer::Messages::Base>]
|
|
96
|
+
# @return [Enumerator] an enumerator yielding stream events
|
|
97
|
+
def stream(prompt_or_messages)
|
|
98
|
+
initialize_messages(prompt_or_messages)
|
|
99
|
+
|
|
100
|
+
Enumerator.new do |yielder|
|
|
101
|
+
accumulated_content = ""
|
|
102
|
+
|
|
103
|
+
call_llm_stream.each do |event|
|
|
104
|
+
yielder << event
|
|
105
|
+
|
|
106
|
+
case event
|
|
107
|
+
when Riffer::StreamEvents::TextDelta
|
|
108
|
+
accumulated_content += event.content
|
|
109
|
+
when Riffer::StreamEvents::TextDone
|
|
110
|
+
accumulated_content = event.content
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
response = Riffer::Messages::Assistant.new(accumulated_content)
|
|
115
|
+
@messages << response
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
94
119
|
private
|
|
95
120
|
|
|
96
121
|
def initialize_messages(prompt_or_messages)
|
|
@@ -110,9 +135,13 @@ class Riffer::Agent
|
|
|
110
135
|
provider_instance.generate_text(messages: @messages, model: @model_name)
|
|
111
136
|
end
|
|
112
137
|
|
|
138
|
+
def call_llm_stream
|
|
139
|
+
provider_instance.stream_text(messages: @messages, model: @model_name)
|
|
140
|
+
end
|
|
141
|
+
|
|
113
142
|
def provider_instance
|
|
114
143
|
@provider_instance ||= begin
|
|
115
|
-
provider_class = Riffer::Providers::
|
|
144
|
+
provider_class = Riffer::Providers::Repository.find(@provider_name)
|
|
116
145
|
raise Riffer::ArgumentError, "Provider not found: #{@provider_name}" unless provider_class
|
|
117
146
|
provider_class.new
|
|
118
147
|
end
|
|
@@ -4,32 +4,6 @@ class Riffer::Providers::Base
|
|
|
4
4
|
include Riffer::Helpers::Dependencies
|
|
5
5
|
include Riffer::Messages::Converter
|
|
6
6
|
|
|
7
|
-
class << self
|
|
8
|
-
def identifier(value = nil)
|
|
9
|
-
return @identifier if value.nil?
|
|
10
|
-
|
|
11
|
-
@identifier = value
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Finds a provider class by identifier
|
|
15
|
-
# @param identifier [String, Symbol] the identifier to search for
|
|
16
|
-
# @return [Class, nil] the provider class, or nil if not found
|
|
17
|
-
def find(identifier)
|
|
18
|
-
ensure_providers_loaded
|
|
19
|
-
subclasses.find { |provider_class| provider_class.identifier == identifier }
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
def ensure_providers_loaded
|
|
25
|
-
return if @providers_loaded
|
|
26
|
-
|
|
27
|
-
Zeitwerk::Loader.eager_load_namespace(Riffer::Providers)
|
|
28
|
-
|
|
29
|
-
@providers_loaded = true
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
7
|
# Generates text using the provider.
|
|
34
8
|
#
|
|
35
9
|
# @param prompt [String, nil] the user prompt (required when `messages` is not provided)
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
require "openai"
|
|
4
4
|
|
|
5
5
|
class Riffer::Providers::OpenAI < Riffer::Providers::Base
|
|
6
|
-
identifier "openai"
|
|
7
|
-
|
|
8
6
|
# Initializes the OpenAI provider.
|
|
9
7
|
# @param options [Hash] optional client options. Use `:api_key` to override `Riffer.config.openai.api_key`.
|
|
10
8
|
# @raise [Riffer::ArgumentError] if an API key is not provided either via `:api_key` or `Riffer.config.openai.api_key`.
|
|
@@ -78,19 +76,16 @@ class Riffer::Providers::OpenAI < Riffer::Providers::Base
|
|
|
78
76
|
end
|
|
79
77
|
|
|
80
78
|
def process_stream_events(stream, yielder)
|
|
81
|
-
stream.each do |
|
|
82
|
-
|
|
79
|
+
stream.each do |raw_event|
|
|
80
|
+
event = convert_event(raw_event)
|
|
83
81
|
|
|
84
|
-
|
|
85
|
-
yielder << content if content
|
|
86
|
-
end
|
|
87
|
-
end
|
|
82
|
+
next unless event
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
|
|
84
|
+
yielder << event if event
|
|
85
|
+
end
|
|
91
86
|
end
|
|
92
87
|
|
|
93
|
-
def
|
|
88
|
+
def convert_event(event)
|
|
94
89
|
case event.type
|
|
95
90
|
when :"response.output_text.delta"
|
|
96
91
|
Riffer::StreamEvents::TextDelta.new(event.delta)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class Riffer::Providers::Repository
|
|
2
|
+
REPO = {
|
|
3
|
+
openai: -> { Riffer::Providers::OpenAI },
|
|
4
|
+
test: -> { Riffer::Providers::Test }
|
|
5
|
+
}.freeze
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
# Finds a provider class by identifier
|
|
9
|
+
# @param identifier [String, Symbol] the identifier to search for
|
|
10
|
+
# @return [Class, nil] the provider class, or nil if not found
|
|
11
|
+
def find(identifier)
|
|
12
|
+
REPO.fetch(identifier.to_sym, nil)&.call
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Riffer::Providers::Test < Riffer::Providers::Base
|
|
4
|
-
identifier "test"
|
|
5
|
-
|
|
6
4
|
attr_reader :calls
|
|
7
5
|
|
|
8
6
|
def initialize(**options)
|
|
@@ -35,11 +33,14 @@ class Riffer::Providers::Test < Riffer::Providers::Base
|
|
|
35
33
|
response = @stubbed_response || @responses[@current_index] || {role: "assistant", content: "Test response"}
|
|
36
34
|
@current_index += 1
|
|
37
35
|
Enumerator.new do |yielder|
|
|
38
|
-
|
|
36
|
+
full_content = response[:content]
|
|
37
|
+
content_parts = full_content.split(". ").map { |part| part + (part.end_with?(".") ? "" : ".") }
|
|
38
|
+
|
|
39
39
|
content_parts.each do |part|
|
|
40
|
-
yielder <<
|
|
41
|
-
sleep 0.5
|
|
40
|
+
yielder << Riffer::StreamEvents::TextDelta.new(part + " ")
|
|
42
41
|
end
|
|
42
|
+
|
|
43
|
+
yielder << Riffer::StreamEvents::TextDone.new(full_content)
|
|
43
44
|
end
|
|
44
45
|
end
|
|
45
46
|
end
|
data/lib/riffer/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: riffer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jake Bottrall
|
|
@@ -150,6 +150,7 @@ files:
|
|
|
150
150
|
- lib/riffer/providers.rb
|
|
151
151
|
- lib/riffer/providers/base.rb
|
|
152
152
|
- lib/riffer/providers/open_ai.rb
|
|
153
|
+
- lib/riffer/providers/repository.rb
|
|
153
154
|
- lib/riffer/providers/test.rb
|
|
154
155
|
- lib/riffer/stream_events.rb
|
|
155
156
|
- lib/riffer/stream_events/base.rb
|