prompt_builder 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/CHANGELOG.md +24 -0
- data/MIT-LICENSE +20 -0
- data/README.md +763 -0
- data/VERSION +1 -0
- data/lib/prompt_builder/content/base.rb +44 -0
- data/lib/prompt_builder/content/input_file.rb +63 -0
- data/lib/prompt_builder/content/input_image.rb +64 -0
- data/lib/prompt_builder/content/input_text.rb +42 -0
- data/lib/prompt_builder/content/input_video.rb +43 -0
- data/lib/prompt_builder/content/output_text.rb +59 -0
- data/lib/prompt_builder/content/reasoning_text.rb +42 -0
- data/lib/prompt_builder/content/refusal_content.rb +42 -0
- data/lib/prompt_builder/content/summary_text.rb +42 -0
- data/lib/prompt_builder/content/text.rb +42 -0
- data/lib/prompt_builder/content.rb +28 -0
- data/lib/prompt_builder/errors.rb +18 -0
- data/lib/prompt_builder/items/base.rb +41 -0
- data/lib/prompt_builder/items/compaction.rb +60 -0
- data/lib/prompt_builder/items/function_call.rb +97 -0
- data/lib/prompt_builder/items/function_call_output.rb +110 -0
- data/lib/prompt_builder/items/item_reference.rb +42 -0
- data/lib/prompt_builder/items/message.rb +113 -0
- data/lib/prompt_builder/items/reasoning.rb +75 -0
- data/lib/prompt_builder/items.rb +13 -0
- data/lib/prompt_builder/response.rb +257 -0
- data/lib/prompt_builder/serializers/base.rb +37 -0
- data/lib/prompt_builder/serializers/chat_completion/request.rb +389 -0
- data/lib/prompt_builder/serializers/chat_completion/response.rb +139 -0
- data/lib/prompt_builder/serializers/chat_completion.rb +30 -0
- data/lib/prompt_builder/serializers/converse/request.rb +623 -0
- data/lib/prompt_builder/serializers/converse/response.rb +140 -0
- data/lib/prompt_builder/serializers/converse.rb +30 -0
- data/lib/prompt_builder/serializers/gemini/request.rb +562 -0
- data/lib/prompt_builder/serializers/gemini/response.rb +233 -0
- data/lib/prompt_builder/serializers/gemini.rb +30 -0
- data/lib/prompt_builder/serializers/messages/request.rb +634 -0
- data/lib/prompt_builder/serializers/messages/response.rb +157 -0
- data/lib/prompt_builder/serializers/messages.rb +30 -0
- data/lib/prompt_builder/serializers/open_responses/request.rb +229 -0
- data/lib/prompt_builder/serializers/open_responses/response.rb +18 -0
- data/lib/prompt_builder/serializers/open_responses.rb +30 -0
- data/lib/prompt_builder/serializers.rb +35 -0
- data/lib/prompt_builder/session.rb +383 -0
- data/lib/prompt_builder/tool_registry.rb +75 -0
- data/lib/prompt_builder/tools/definition.rb +66 -0
- data/lib/prompt_builder/tools.rb +7 -0
- data/lib/prompt_builder/usage.rb +100 -0
- data/lib/prompt_builder.rb +86 -0
- data/prompt_builder.gemspec +41 -0
- metadata +107 -0
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
# Base class for content objects. Provides polymorphic deserialization
|
|
6
|
+
# via the +type+ field in the hash representation.
|
|
7
|
+
class Base
|
|
8
|
+
# Content type registry for polymorphic dispatch.
|
|
9
|
+
TYPES = {
|
|
10
|
+
"input_file" => "InputFile",
|
|
11
|
+
"input_image" => "InputImage",
|
|
12
|
+
"input_text" => "InputText",
|
|
13
|
+
"input_video" => "InputVideo",
|
|
14
|
+
"output_text" => "OutputText",
|
|
15
|
+
"reasoning_text" => "ReasoningText",
|
|
16
|
+
"refusal" => "RefusalContent",
|
|
17
|
+
"summary_text" => "SummaryText",
|
|
18
|
+
"text" => "Text"
|
|
19
|
+
}.freeze
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
# Deserialize a content object from a Hash by dispatching on the +type+ field.
|
|
23
|
+
#
|
|
24
|
+
# @param hash [Hash] a Hash with string keys including a +"type"+ field
|
|
25
|
+
# @return [Content::Base] the deserialized content object
|
|
26
|
+
# @raise [InvalidItemError] if the type is unknown
|
|
27
|
+
def from_h(hash)
|
|
28
|
+
type = hash["type"]
|
|
29
|
+
class_name = TYPES[type]
|
|
30
|
+
raise InvalidItemError, "Unknown content type: #{type.inspect}" unless class_name
|
|
31
|
+
|
|
32
|
+
Content.const_get(class_name).from_h(hash)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Serialize the content object to a Hash with string keys.
|
|
37
|
+
#
|
|
38
|
+
# @return [Hash] the hash representation
|
|
39
|
+
def to_h
|
|
40
|
+
raise NotImplementedError
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
# Represents file input content in a message.
|
|
6
|
+
class InputFile < Base
|
|
7
|
+
# @return [String, nil] the file URL (may be a data URL)
|
|
8
|
+
attr_reader :url
|
|
9
|
+
|
|
10
|
+
# @return [String, nil] the filename
|
|
11
|
+
attr_reader :filename
|
|
12
|
+
|
|
13
|
+
# @return [Hash, nil] provider-specific extra data
|
|
14
|
+
attr_reader :extra
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
# Deserialize an InputFile from a Hash.
|
|
18
|
+
#
|
|
19
|
+
# @param hash [Hash] a Hash with string keys
|
|
20
|
+
# @return [InputFile]
|
|
21
|
+
def from_h(hash)
|
|
22
|
+
new(
|
|
23
|
+
url: hash["url"],
|
|
24
|
+
filename: hash["filename"],
|
|
25
|
+
**hash.except("type", "url", "filename").transform_keys(&:to_sym)
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Create a new InputFile content object.
|
|
31
|
+
#
|
|
32
|
+
# @param url [String, nil] the file URL or data URL
|
|
33
|
+
# @param filename [String, nil] the filename
|
|
34
|
+
# @param extra [Hash] provider-specific extra keyword arguments
|
|
35
|
+
def initialize(url: nil, filename: nil, **extra)
|
|
36
|
+
@filename = filename&.to_s
|
|
37
|
+
@extra = normalize_extra_kwargs(extra)
|
|
38
|
+
@url = url&.to_s
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Serialize to a Hash with string keys. Nil values are omitted.
|
|
42
|
+
#
|
|
43
|
+
# @return [Hash]
|
|
44
|
+
def to_h
|
|
45
|
+
h = {"type" => "input_file"}
|
|
46
|
+
h["url"] = @url if @url
|
|
47
|
+
h["filename"] = @filename if @filename
|
|
48
|
+
h = PromptBuilder.jsonify(@extra).merge(h) unless @extra.empty?
|
|
49
|
+
h
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def normalize_extra_kwargs(extra)
|
|
55
|
+
nested = extra.delete(:extra)
|
|
56
|
+
nested = extra.delete("extra") if nested.nil?
|
|
57
|
+
nested_hash = nested.is_a?(Hash) ? nested : {}
|
|
58
|
+
|
|
59
|
+
PromptBuilder.jsonify(nested_hash.merge(extra)).transform_keys(&:to_s)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
# Represents image input content in a message.
|
|
6
|
+
class InputImage < Base
|
|
7
|
+
# @return [String, nil] the image URL (may be a fully qualified URL or a
|
|
8
|
+
# base64-encoded data URL such as +"data:image/png;base64,..."+ )
|
|
9
|
+
attr_reader :url
|
|
10
|
+
|
|
11
|
+
# @return [String, nil] the detail level for the image
|
|
12
|
+
attr_reader :detail
|
|
13
|
+
|
|
14
|
+
# @return [Hash, nil] provider-specific extra data
|
|
15
|
+
attr_reader :extra
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
# Deserialize an InputImage from a Hash.
|
|
19
|
+
#
|
|
20
|
+
# @param hash [Hash] a Hash with string keys
|
|
21
|
+
# @return [InputImage]
|
|
22
|
+
def from_h(hash)
|
|
23
|
+
new(
|
|
24
|
+
url: hash["url"],
|
|
25
|
+
detail: hash["detail"],
|
|
26
|
+
**hash.except("type", "url", "detail").transform_keys(&:to_sym)
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Create a new InputImage content object.
|
|
32
|
+
#
|
|
33
|
+
# @param url [String, nil] the image URL or data URL
|
|
34
|
+
# @param detail [String, nil] the image detail level
|
|
35
|
+
# @param extra [Hash] provider-specific extra keyword arguments
|
|
36
|
+
def initialize(url: nil, detail: nil, **extra)
|
|
37
|
+
@detail = detail&.to_s
|
|
38
|
+
@extra = normalize_extra_kwargs(extra)
|
|
39
|
+
@url = url&.to_s
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Serialize to a Hash with string keys. Nil values are omitted.
|
|
43
|
+
#
|
|
44
|
+
# @return [Hash]
|
|
45
|
+
def to_h
|
|
46
|
+
h = {"type" => "input_image"}
|
|
47
|
+
h["url"] = @url if @url
|
|
48
|
+
h["detail"] = @detail if @detail
|
|
49
|
+
h = PromptBuilder.jsonify(@extra).merge(h) unless @extra.empty?
|
|
50
|
+
h
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def normalize_extra_kwargs(extra)
|
|
56
|
+
nested = extra.delete(:extra)
|
|
57
|
+
nested = extra.delete("extra") if nested.nil?
|
|
58
|
+
nested_hash = nested.is_a?(Hash) ? nested : {}
|
|
59
|
+
|
|
60
|
+
PromptBuilder.jsonify(nested_hash.merge(extra)).transform_keys(&:to_s)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
# Represents text input content in a message.
|
|
6
|
+
class InputText < Base
|
|
7
|
+
# @return [String] the text content
|
|
8
|
+
attr_reader :text
|
|
9
|
+
|
|
10
|
+
# @return [Hash, nil] provider-specific extra data
|
|
11
|
+
attr_reader :extra
|
|
12
|
+
|
|
13
|
+
# Create a new InputText content object.
|
|
14
|
+
#
|
|
15
|
+
# @param text [String] the text content
|
|
16
|
+
# @param extra [Hash] provider-specific extra keyword arguments
|
|
17
|
+
def initialize(text:, **extra)
|
|
18
|
+
@text = text&.to_s
|
|
19
|
+
@extra = extra.transform_keys(&:to_s)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
# Deserialize an InputText from a Hash.
|
|
24
|
+
#
|
|
25
|
+
# @param hash [Hash] a Hash with string keys
|
|
26
|
+
# @return [InputText]
|
|
27
|
+
def from_h(hash)
|
|
28
|
+
new(text: hash["text"], **hash.except("type", "text").transform_keys(&:to_sym))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Serialize to a Hash with string keys.
|
|
33
|
+
#
|
|
34
|
+
# @return [Hash]
|
|
35
|
+
def to_h
|
|
36
|
+
h = {"type" => "input_text", "text" => @text}
|
|
37
|
+
h = PromptBuilder.jsonify(@extra).merge(h) unless @extra.empty?
|
|
38
|
+
h
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
# Represents video input content in a message.
|
|
6
|
+
class InputVideo < Base
|
|
7
|
+
# @return [String, nil] the video URL
|
|
8
|
+
attr_reader :url
|
|
9
|
+
|
|
10
|
+
# @return [Hash, nil] provider-specific extra data
|
|
11
|
+
attr_reader :extra
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
# Deserialize an InputVideo from a Hash.
|
|
15
|
+
#
|
|
16
|
+
# @param hash [Hash] a Hash with string keys
|
|
17
|
+
# @return [InputVideo]
|
|
18
|
+
def from_h(hash)
|
|
19
|
+
new(url: hash["url"], **hash.except("type", "url").transform_keys(&:to_sym))
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Create a new InputVideo content object.
|
|
24
|
+
#
|
|
25
|
+
# @param url [String, nil] the video URL
|
|
26
|
+
# @param extra [Hash] provider-specific extra keyword arguments
|
|
27
|
+
def initialize(url: nil, **extra)
|
|
28
|
+
@url = url&.to_s
|
|
29
|
+
@extra = extra.transform_keys(&:to_s)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Serialize to a Hash with string keys. Nil values are omitted.
|
|
33
|
+
#
|
|
34
|
+
# @return [Hash]
|
|
35
|
+
def to_h
|
|
36
|
+
h = {"type" => "input_video"}
|
|
37
|
+
h["url"] = @url if @url
|
|
38
|
+
h = PromptBuilder.jsonify(@extra).merge(h) unless @extra.empty?
|
|
39
|
+
h
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
# Represents text output content in an assistant message.
|
|
6
|
+
class OutputText < Base
|
|
7
|
+
# @return [String] the text content
|
|
8
|
+
attr_reader :text
|
|
9
|
+
|
|
10
|
+
# @return [Array<Hash>] annotations on the text
|
|
11
|
+
attr_reader :annotations
|
|
12
|
+
|
|
13
|
+
# @return [Array<Hash>] token log probabilities for the text
|
|
14
|
+
attr_reader :logprobs
|
|
15
|
+
|
|
16
|
+
# @return [Hash, nil] provider-specific extra data
|
|
17
|
+
attr_reader :extra
|
|
18
|
+
|
|
19
|
+
# Create a new OutputText content object.
|
|
20
|
+
#
|
|
21
|
+
# @param text [String] the text content
|
|
22
|
+
# @param annotations [Array<Hash>] annotations on the text
|
|
23
|
+
# @param logprobs [Array<Hash>] token log probabilities on the text
|
|
24
|
+
# @param extra [Hash] provider-specific extra keyword arguments
|
|
25
|
+
def initialize(text:, annotations: [], logprobs: [], **extra)
|
|
26
|
+
@text = text&.to_s
|
|
27
|
+
@annotations = PromptBuilder.jsonify(annotations)
|
|
28
|
+
@logprobs = PromptBuilder.jsonify(logprobs)
|
|
29
|
+
@extra = extra.transform_keys(&:to_s)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
# Deserialize an OutputText from a Hash.
|
|
34
|
+
#
|
|
35
|
+
# @param hash [Hash] a Hash with string keys
|
|
36
|
+
# @return [OutputText]
|
|
37
|
+
def from_h(hash)
|
|
38
|
+
new(
|
|
39
|
+
text: hash["text"],
|
|
40
|
+
annotations: hash["annotations"] || [],
|
|
41
|
+
logprobs: hash["logprobs"] || [],
|
|
42
|
+
**hash.except("type", "text", "annotations", "logprobs").transform_keys(&:to_sym)
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Serialize to a Hash with string keys. Empty annotations are omitted.
|
|
48
|
+
#
|
|
49
|
+
# @return [Hash]
|
|
50
|
+
def to_h
|
|
51
|
+
h = {"type" => "output_text", "text" => @text}
|
|
52
|
+
h["annotations"] = @annotations unless @annotations.empty?
|
|
53
|
+
h["logprobs"] = @logprobs unless @logprobs.empty?
|
|
54
|
+
h = PromptBuilder.jsonify(@extra).merge(h) unless @extra.empty?
|
|
55
|
+
h
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
# Represents reasoning text content from the model.
|
|
6
|
+
class ReasoningText < Base
|
|
7
|
+
# @return [String] the reasoning text content
|
|
8
|
+
attr_reader :text
|
|
9
|
+
|
|
10
|
+
# @return [Hash, nil] provider-specific extra data
|
|
11
|
+
attr_reader :extra
|
|
12
|
+
|
|
13
|
+
# Create a new ReasoningText content object.
|
|
14
|
+
#
|
|
15
|
+
# @param text [String] the reasoning text content
|
|
16
|
+
# @param extra [Hash] provider-specific extra keyword arguments
|
|
17
|
+
def initialize(text:, **extra)
|
|
18
|
+
@text = text&.to_s
|
|
19
|
+
@extra = extra.transform_keys(&:to_s)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
# Deserialize a ReasoningText from a Hash.
|
|
24
|
+
#
|
|
25
|
+
# @param hash [Hash] a Hash with string keys
|
|
26
|
+
# @return [ReasoningText]
|
|
27
|
+
def from_h(hash)
|
|
28
|
+
new(text: hash["text"], **hash.except("type", "text").transform_keys(&:to_sym))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Serialize to a Hash with string keys.
|
|
33
|
+
#
|
|
34
|
+
# @return [Hash]
|
|
35
|
+
def to_h
|
|
36
|
+
h = {"type" => "reasoning_text", "text" => @text}
|
|
37
|
+
h = PromptBuilder.jsonify(@extra).merge(h) unless @extra.empty?
|
|
38
|
+
h
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
# Represents a refusal content block returned by the model.
|
|
6
|
+
class RefusalContent < Base
|
|
7
|
+
# @return [String] the refusal message
|
|
8
|
+
attr_reader :refusal
|
|
9
|
+
|
|
10
|
+
# @return [Hash, nil] provider-specific extra data
|
|
11
|
+
attr_reader :extra
|
|
12
|
+
|
|
13
|
+
# Create a new RefusalContent object.
|
|
14
|
+
#
|
|
15
|
+
# @param refusal [String] the refusal message
|
|
16
|
+
# @param extra [Hash] provider-specific extra keyword arguments
|
|
17
|
+
def initialize(refusal:, **extra)
|
|
18
|
+
@refusal = refusal&.to_s
|
|
19
|
+
@extra = extra.transform_keys(&:to_s)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
# Deserialize a RefusalContent from a Hash.
|
|
24
|
+
#
|
|
25
|
+
# @param hash [Hash] a Hash with string keys
|
|
26
|
+
# @return [RefusalContent]
|
|
27
|
+
def from_h(hash)
|
|
28
|
+
new(refusal: hash["refusal"], **hash.except("type", "refusal").transform_keys(&:to_sym))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Serialize to a Hash with string keys.
|
|
33
|
+
#
|
|
34
|
+
# @return [Hash]
|
|
35
|
+
def to_h
|
|
36
|
+
h = {"type" => "refusal", "refusal" => @refusal}
|
|
37
|
+
h = PromptBuilder.jsonify(@extra).merge(h) unless @extra.empty?
|
|
38
|
+
h
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
# Represents a summary text content from the model's reasoning.
|
|
6
|
+
class SummaryText < Base
|
|
7
|
+
# @return [String] the summary text content
|
|
8
|
+
attr_reader :text
|
|
9
|
+
|
|
10
|
+
# @return [Hash, nil] provider-specific extra data
|
|
11
|
+
attr_reader :extra
|
|
12
|
+
|
|
13
|
+
# Create a new SummaryText content object.
|
|
14
|
+
#
|
|
15
|
+
# @param text [String] the summary text content
|
|
16
|
+
# @param extra [Hash] provider-specific extra keyword arguments
|
|
17
|
+
def initialize(text:, **extra)
|
|
18
|
+
@text = text&.to_s
|
|
19
|
+
@extra = extra.transform_keys(&:to_s)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
# Deserialize a SummaryText from a Hash.
|
|
24
|
+
#
|
|
25
|
+
# @param hash [Hash] a Hash with string keys
|
|
26
|
+
# @return [SummaryText]
|
|
27
|
+
def from_h(hash)
|
|
28
|
+
new(text: hash["text"], **hash.except("type", "text").transform_keys(&:to_sym))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Serialize to a Hash with string keys.
|
|
33
|
+
#
|
|
34
|
+
# @return [Hash]
|
|
35
|
+
def to_h
|
|
36
|
+
h = {"type" => "summary_text", "text" => @text}
|
|
37
|
+
h = PromptBuilder.jsonify(@extra).merge(h) unless @extra.empty?
|
|
38
|
+
h
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
# Represents generic text content in a message or reasoning item.
|
|
6
|
+
class Text < Base
|
|
7
|
+
# @return [String] the text content
|
|
8
|
+
attr_reader :text
|
|
9
|
+
|
|
10
|
+
# @return [Hash, nil] provider-specific extra data
|
|
11
|
+
attr_reader :extra
|
|
12
|
+
|
|
13
|
+
# Create a new Text content object.
|
|
14
|
+
#
|
|
15
|
+
# @param text [String] the text content
|
|
16
|
+
# @param extra [Hash] provider-specific extra keyword arguments
|
|
17
|
+
def initialize(text:, **extra)
|
|
18
|
+
@text = text&.to_s
|
|
19
|
+
@extra = extra.transform_keys(&:to_s)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
# Deserialize a Text from a Hash.
|
|
24
|
+
#
|
|
25
|
+
# @param hash [Hash] a Hash with string keys
|
|
26
|
+
# @return [Text]
|
|
27
|
+
def from_h(hash)
|
|
28
|
+
new(text: hash["text"], **hash.except("type", "text").transform_keys(&:to_sym))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Serialize to a Hash with string keys.
|
|
33
|
+
#
|
|
34
|
+
# @return [Hash]
|
|
35
|
+
def to_h
|
|
36
|
+
h = {"type" => "text", "text" => @text}
|
|
37
|
+
h = PromptBuilder.jsonify(@extra).merge(h) unless @extra.empty?
|
|
38
|
+
h
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Content
|
|
5
|
+
autoload :Base, File.expand_path("content/base", __dir__)
|
|
6
|
+
autoload :InputFile, File.expand_path("content/input_file", __dir__)
|
|
7
|
+
autoload :InputImage, File.expand_path("content/input_image", __dir__)
|
|
8
|
+
autoload :InputText, File.expand_path("content/input_text", __dir__)
|
|
9
|
+
autoload :InputVideo, File.expand_path("content/input_video", __dir__)
|
|
10
|
+
autoload :OutputText, File.expand_path("content/output_text", __dir__)
|
|
11
|
+
autoload :ReasoningText, File.expand_path("content/reasoning_text", __dir__)
|
|
12
|
+
autoload :RefusalContent, File.expand_path("content/refusal_content", __dir__)
|
|
13
|
+
autoload :SummaryText, File.expand_path("content/summary_text", __dir__)
|
|
14
|
+
autoload :Text, File.expand_path("content/text", __dir__)
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
# Construct a base64-encoded data URL from raw binary data and a content type.
|
|
18
|
+
# Delegates to {PromptBuilder.data_url}.
|
|
19
|
+
#
|
|
20
|
+
# @param data [String] the raw binary data
|
|
21
|
+
# @param content_type [String] the MIME content type (e.g. "image/png", "application/pdf")
|
|
22
|
+
# @return [String] a data URL in the form "data:<content_type>;base64,<encoded_data>"
|
|
23
|
+
def data_url(data, content_type)
|
|
24
|
+
PromptBuilder.data_url(data, content_type)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
# Base error class for all PromptBuilder errors.
|
|
5
|
+
class Error < StandardError; end
|
|
6
|
+
|
|
7
|
+
# Raised when a format conversion is not supported.
|
|
8
|
+
class UnsupportedFormatError < Error; end
|
|
9
|
+
|
|
10
|
+
# Raised when an invalid item type is encountered.
|
|
11
|
+
class InvalidItemError < Error; end
|
|
12
|
+
|
|
13
|
+
# Raised when a tool is not found in the registry.
|
|
14
|
+
class ToolNotFoundError < Error; end
|
|
15
|
+
|
|
16
|
+
# Raised when an operation is invalid for the current session state.
|
|
17
|
+
class InvalidStateError < Error; end
|
|
18
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Items
|
|
5
|
+
# Base class for conversation items. Provides polymorphic deserialization
|
|
6
|
+
# via the +type+ field in the hash representation.
|
|
7
|
+
class Base
|
|
8
|
+
# Item type registry for polymorphic dispatch.
|
|
9
|
+
TYPES = {
|
|
10
|
+
"compaction" => "Compaction",
|
|
11
|
+
"function_call" => "FunctionCall",
|
|
12
|
+
"function_call_output" => "FunctionCallOutput",
|
|
13
|
+
"item_reference" => "ItemReference",
|
|
14
|
+
"message" => "Message",
|
|
15
|
+
"reasoning" => "Reasoning"
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
# Deserialize an item from a Hash by dispatching on the +type+ field.
|
|
20
|
+
#
|
|
21
|
+
# @param hash [Hash] a Hash with string keys including a +"type"+ field
|
|
22
|
+
# @return [Items::Base] the deserialized item
|
|
23
|
+
# @raise [InvalidItemError] if the type is unknown
|
|
24
|
+
def from_h(hash)
|
|
25
|
+
type = hash["type"]
|
|
26
|
+
class_name = TYPES[type]
|
|
27
|
+
raise InvalidItemError, "Unknown item type: #{type.inspect}" unless class_name
|
|
28
|
+
|
|
29
|
+
Items.const_get(class_name).from_h(hash)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Serialize the item to a Hash with string keys.
|
|
34
|
+
#
|
|
35
|
+
# @return [Hash] the hash representation
|
|
36
|
+
def to_h
|
|
37
|
+
raise NotImplementedError
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptBuilder
|
|
4
|
+
module Items
|
|
5
|
+
# Represents a compaction item that summarizes earlier conversation history.
|
|
6
|
+
class Compaction < Base
|
|
7
|
+
# @return [String, nil] the compaction item identifier
|
|
8
|
+
attr_reader :id
|
|
9
|
+
|
|
10
|
+
# @return [String, nil] encrypted compacted content
|
|
11
|
+
attr_reader :encrypted_content
|
|
12
|
+
|
|
13
|
+
# @return [String, nil] who created the compaction (e.g. "user" or "assistant")
|
|
14
|
+
attr_reader :created_by
|
|
15
|
+
|
|
16
|
+
# @return [Hash, nil] provider-specific extra data
|
|
17
|
+
attr_reader :extra
|
|
18
|
+
|
|
19
|
+
# Create a new Compaction item.
|
|
20
|
+
#
|
|
21
|
+
# @param id [String, nil] the compaction item identifier
|
|
22
|
+
# @param encrypted_content [String, nil] encrypted compacted content
|
|
23
|
+
# @param created_by [String, nil] who created the compaction
|
|
24
|
+
# @param extra [Hash] provider-specific extra keyword arguments
|
|
25
|
+
def initialize(id: nil, encrypted_content: nil, created_by: nil, **extra)
|
|
26
|
+
@id = id&.to_s
|
|
27
|
+
@encrypted_content = encrypted_content&.to_s
|
|
28
|
+
@created_by = created_by&.to_s
|
|
29
|
+
@extra = extra.transform_keys(&:to_s)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
# Deserialize a Compaction item from a Hash.
|
|
34
|
+
#
|
|
35
|
+
# @param hash [Hash] a Hash with string keys
|
|
36
|
+
# @return [Compaction]
|
|
37
|
+
def from_h(hash)
|
|
38
|
+
new(
|
|
39
|
+
id: hash["id"],
|
|
40
|
+
encrypted_content: hash["encrypted_content"],
|
|
41
|
+
created_by: hash["created_by"],
|
|
42
|
+
**hash.except("type", "id", "encrypted_content", "created_by").transform_keys(&:to_sym)
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Serialize to a Hash with string keys. Nil values are omitted.
|
|
48
|
+
#
|
|
49
|
+
# @return [Hash]
|
|
50
|
+
def to_h
|
|
51
|
+
h = {"type" => "compaction"}
|
|
52
|
+
h["id"] = @id if @id
|
|
53
|
+
h["encrypted_content"] = @encrypted_content if @encrypted_content
|
|
54
|
+
h["created_by"] = @created_by if @created_by
|
|
55
|
+
h = PromptBuilder.jsonify(@extra).merge(h) unless @extra.empty?
|
|
56
|
+
h
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|