ticuna 0.2.6 → 0.2.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 559816faa31497288f44f3c2174199ad15af23dceb2c7e373b2f9b7446c87725
4
- data.tar.gz: 8758245018266453979599a0428b94bcbaaba288c6455c113f40c7e39abb97dd
3
+ metadata.gz: 55e07fd5840706e2936718a07ad6e6e6be5ae8681b6c8b763bac6c9c073d632f
4
+ data.tar.gz: '0118e2253d49b82acbbe08ed17145997330a9c42f30f276e87b7ff01136710d9'
5
5
  SHA512:
6
- metadata.gz: 76171e5dc940d98159fb8b94119facf7cc9b23f08f30a37cda59ad57483e91915a261e694c50f2135eb17fa20955e05092358a98382e763ed762de1c610ee827
7
- data.tar.gz: ec1bf63e151eec143d2d1a8ded518cef4ca7b9a64654612f54eeaf3d7695b99e9ca83b7485e9d239c587c19930b8259a65f1c9c1a245fb6ade3e4426fc5be175
6
+ metadata.gz: 90467485b1691fdf24b14c442945f82f8b58db85b4ff47ee1f2403adf96b3fdd5efcd54fc94cd3c88068151037ac220058536797c9b407f2acd83b2a7edbab3e
7
+ data.tar.gz: d60b05c8b3e1306835c9996e91b88accfe8ca2fe7d1f47c0358d7ae2903a4c7b2bc2e6949007c6294cda3a312c9c5bbea81f9d9cc40095d830eea04c8c657031
data/CHANGELOG.md CHANGED
@@ -31,4 +31,8 @@
31
31
  - Add `errors?` method
32
32
 
33
33
  ## [0.2.6] - 2025-10-22
34
- - Add `context` method
34
+ - Add `context` method
35
+
36
+ ## [0.2.7] - 2025-10-22
37
+ - Add modular response, to attend any LLM model
38
+ - Add `.response` method in Ticuna::Response to ease access to the real response
data/lib/ticuna/llm.rb CHANGED
@@ -10,12 +10,11 @@ module Ticuna
10
10
  def self.new(provider = nil)
11
11
  provider_key = detect_provider(provider)
12
12
  provider_client = Ticuna::Providers::CLIENTS[provider_key].call
13
- new_instance = allocate
14
- new_instance.send(:initialize_llm, provider_client)
15
- new_instance
13
+ allocate.tap { |instance| instance.send(:initialize_llm, provider_key, provider_client) }
16
14
  end
17
15
 
18
- def initialize_llm(provider_client)
16
+ def initialize_llm(provider_key, provider_client)
17
+ @provider_key = provider_key
19
18
  @provider = provider_client
20
19
  @tools = []
21
20
  @contexts = []
@@ -52,7 +51,8 @@ module Ticuna
52
51
  model_string = detect_llm_model(model)
53
52
 
54
53
  Ticuna::Response.new(
55
- @provider.ask_with_messages(messages, stream: stream, model: model_string, output_format: output_format, &block)
54
+ @provider.ask_with_messages(messages, stream: stream, model: model_string, output_format: output_format, &block),
55
+ provider: @provider_key
56
56
  )
57
57
  end
58
58
 
@@ -7,6 +7,8 @@ module Ticuna
7
7
  class OpenAI < BaseProvider
8
8
  def initialize(api_key:)
9
9
  super(api_key: api_key, base_url: "https://api.openai.com/v1/")
10
+ @response = String.new
11
+ @raw_response = String.new
10
12
  end
11
13
 
12
14
  def ask(message, stream: false, model: "gpt-4.1-nano", output_format: :text, &block)
@@ -67,7 +69,8 @@ module Ticuna
67
69
  end
68
70
  end
69
71
 
70
- {
72
+ @response = full_text
73
+ @raw_response = {
71
74
  "id" => "streamed_completion_#{Time.now.to_i}",
72
75
  "object" => "chat.completion",
73
76
  "model" => body[:model],
@@ -81,9 +84,13 @@ module Ticuna
81
84
  }
82
85
  else
83
86
  resp = @connection.post(path, body.to_json)
84
- JSON.parse(resp.body)
87
+ @raw_response = JSON.parse(resp.body)
88
+ @response = @raw_response.dig("choices", 0, "message", "content")
85
89
  end
90
+
91
+ @raw_response
86
92
  end
93
+ attr_reader :response, :raw_response
87
94
  end
88
95
  end
89
96
  end
@@ -24,5 +24,9 @@ module Ticuna
24
24
  # deepseek: -> { Ticuna::Providers::DeepSeek.new(api_key: ENVS[:deepseek].call) },
25
25
  # mistral: -> { Ticuna::Providers::Mistral.new(api_key: ENVS[:mistral].call) }
26
26
  }.freeze
27
+
28
+ RESPONSE_EXTRACTORS = {
29
+ openai: ->(data) { data.dig(:choices, 0, :message, :content) }
30
+ }.freeze
27
31
  end
28
32
  end
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "json"
4
+ require "ticuna/providers"
4
5
 
5
6
  module Ticuna
6
7
  class Response
7
- attr_reader :data, :errors, :parsed
8
+ attr_reader :data, :errors, :parsed, :raw_response, :response, :provider
8
9
 
9
- def initialize(raw)
10
+ def initialize(raw, provider: nil)
11
+ @provider = provider
12
+ @raw_response = raw
10
13
  @parsed =
11
14
  case raw
12
15
  when String
@@ -22,7 +25,14 @@ module Ticuna
22
25
  end
23
26
 
24
27
  @data = deep_symbolize_keys(@parsed)
25
- @errors = deep_symbolize_keys(@parsed["error"] || [])
28
+ error_payload =
29
+ if @parsed.is_a?(Hash)
30
+ @parsed["error"] || @parsed[:error] || []
31
+ else
32
+ []
33
+ end
34
+ @errors = deep_symbolize_keys(error_payload)
35
+ @response = resolve_response
26
36
  end
27
37
 
28
38
  def [](key)
@@ -70,12 +80,36 @@ module Ticuna
70
80
  def wrap(value)
71
81
  case value
72
82
  when Hash
73
- self.class.new(value)
83
+ self.class.new(value, provider: provider)
74
84
  when Array
75
85
  value.map { |v| wrap(v) }
76
86
  else
77
87
  value
78
88
  end
79
89
  end
90
+
91
+ def resolve_response
92
+ from_provider = extract_from_provider
93
+ return from_provider unless blank?(from_provider)
94
+
95
+ fallback =
96
+ if @data.is_a?(Hash)
97
+ @data[:content] || @data[:response]
98
+ end
99
+ return fallback unless blank?(fallback)
100
+
101
+ @parsed if @parsed.is_a?(String)
102
+ end
103
+
104
+ def blank?(value)
105
+ value.respond_to?(:empty?) ? value.empty? : !value
106
+ end
107
+
108
+ def extract_from_provider
109
+ return unless provider
110
+
111
+ extractor = Ticuna::Providers::RESPONSE_EXTRACTORS[provider]
112
+ extractor&.call(@data)
113
+ end
80
114
  end
81
115
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ticuna
4
- VERSION = "0.2.6"
4
+ VERSION = "0.2.7"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ticuna
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chirana