smart_prompt 0.1.7 → 0.1.8

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: 3bf70c6e843930ff7e1a03c9dd8bfc97b3d097786f84613aab65863e1e43a624
4
- data.tar.gz: e9ee9d99378453d90e2ac25b88248f3226f241074c7f80e8bf35104279f05202
3
+ metadata.gz: ab0d62158bbd98af9d2f57d9708426cceb95c2d3b2797abc0094de3caf96adf8
4
+ data.tar.gz: d2a50c4ede575eb70caeda1893b60412b04afdec665690b8fd2d4d0f3bdd410e
5
5
  SHA512:
6
- metadata.gz: 02fbfcdb0ae2292994404219eaa2f1218d54de132ceab061ca4466603186cdc9db5826b7e6e1fcfaa8a37f2527f42c3f863154dfd4cfe94b5b7df58969183285
7
- data.tar.gz: b0034a25a0fa4bc6c197beee4635528c3b4887f36a4c8981ebb9894b7c5db61a245a0ff823f6ce171d629ddc65a61a960a172d4235d319d7220050225b7a8a48
6
+ metadata.gz: 6d61c7f8db100a715b16a8bd08ef27bf49f3e38127d68cb37a5fc55c3d5ee781e505d8c4acbc6ac98206bd2aeb22bcdd4dc6d749ed65293fecb5abbc361ffac9
7
+ data.tar.gz: 7f8ff17971d9979a95400bb1e4497737fab2c503d69a1c415a0003ff514400b55ade390d0f007a146e43569978b98e29f5e308091d74e25cd8b405689b73b136
@@ -1,7 +1,10 @@
1
1
  require 'yaml'
2
+ require 'retriable'
3
+ require "numo/narray"
2
4
 
3
5
  module SmartPrompt
4
6
  class Conversation
7
+ include APIHandler
5
8
  attr_reader :messages, :last_response, :config_file
6
9
 
7
10
  def initialize(engine)
@@ -26,12 +29,17 @@ module SmartPrompt
26
29
  end
27
30
 
28
31
  def prompt(template_name, params = {})
29
- template_name = template_name.to_s
30
- SmartPrompt.logger.info "Use template #{template_name}"
31
- raise "Template #{template_name} not found" unless @templates.key?(template_name)
32
- content = @templates[template_name].render(params)
33
- @messages << { role: 'user', content: content }
34
- self
32
+ if template_name.class == Symbol
33
+ template_name = template_name.to_s
34
+ SmartPrompt.logger.info "Use template #{template_name}"
35
+ raise "Template #{template_name} not found" unless @templates.key?(template_name)
36
+ content = @templates[template_name].render(params)
37
+ @messages << { role: 'user', content: content }
38
+ self
39
+ else
40
+ @messages << { role: 'user', content: template_name }
41
+ self
42
+ end
35
43
  end
36
44
 
37
45
  def sys_msg(message)
@@ -47,5 +55,43 @@ module SmartPrompt
47
55
  @messages << { role: 'system', content: @sys_msg }
48
56
  @last_response
49
57
  end
58
+
59
+ def safe_send_msg
60
+ Retriable.retriable(RETRY_OPTIONS) do
61
+ raise ConfigurationError, "No LLM selected" if @current_llm.nil?
62
+ @last_response = @current_llm.send_request(@messages, @model_name)
63
+ @messages=[]
64
+ @messages << { role: 'system', content: @sys_msg }
65
+ @last_response
66
+ end
67
+ rescue => e
68
+ return "Failed to call LLM after #{MAX_RETRIES} attempts: #{e.message}"
69
+ end
70
+
71
+ def normalize(x, length)
72
+ if x.length > length
73
+ x = Numo::NArray.cast(x[0..length-1])
74
+ norm = Math.sqrt((x * x).sum)
75
+ return (x / norm).to_a
76
+ else
77
+ return x.concat([0] * (x.length - length))
78
+ end
79
+ end
80
+
81
+ def embeddings(length)
82
+ Retriable.retriable(RETRY_OPTIONS) do
83
+ raise ConfigurationError, "No LLM selected" if @current_llm.nil?
84
+ text = ""
85
+ @messages.each do |msg|
86
+ if msg[:role]=="user"
87
+ text = msg[:content]
88
+ end
89
+ end
90
+ @last_response = @current_llm.embeddings(text, @model_name)
91
+ @messages=[]
92
+ @messages << { role: 'system', content: @sys_msg }
93
+ normalize(@last_response, length)
94
+ end
95
+ end
50
96
  end
51
97
  end
@@ -51,6 +51,15 @@ module SmartPrompt
51
51
  require(file)
52
52
  end
53
53
  end
54
+
55
+ def check_worker(worker_name)
56
+ if SmartPrompt::Worker.workers[worker_name]
57
+ return true
58
+ else
59
+ SmartPrompt.logger.warn "Invalid worker: #{worker_name}"
60
+ return false
61
+ end
62
+ end
54
63
 
55
64
  def call_worker(worker_name, params = {})
56
65
  SmartPrompt.logger.info "Calling worker: #{worker_name} with params: #{params}"
@@ -6,7 +6,7 @@ module SmartPrompt
6
6
  super
7
7
  begin
8
8
  @client = Ollama.new(credentials: { address: @config['url'] })
9
- rescue Ollama::Error => e
9
+ rescue Ollama::Errors => e
10
10
  SmartPrompt.logger.error "Failed to initialize Ollama client: #{e.message}"
11
11
  raise LLMAPIError, "Invalid Ollama configuration: #{e.message}"
12
12
  rescue SocketError => e
@@ -36,18 +36,9 @@ module SmartPrompt
36
36
  stream: false
37
37
  }
38
38
  )
39
- rescue Ollama::Error => e
39
+ rescue Ollama::Errors => e
40
40
  SmartPrompt.logger.error "Ollama API error: #{e.message}"
41
- raise LLMAPIError, "Ollama API error: #{e.message}"
42
- rescue Ollama::ConnectionError => e
43
- SmartPrompt.logger.error "Connection error: Unable to reach Ollama API"
44
- raise LLMAPIError, "Connection error: Unable to reach Ollama API"
45
- rescue Ollama::TimeoutError => e
46
- SmartPrompt.logger.error "Request to Ollama API timed out"
47
- raise LLMAPIError, "Request to Ollama API timed out"
48
- rescue Ollama::InvalidRequestError => e
49
- SmartPrompt.logger.error "Invalid request to Ollama API: #{e.message}"
50
- raise LLMAPIError, "Invalid request to Ollama API: #{e.message}"
41
+ raise LLMAPIError, "Ollama API error: #{e.message}"
51
42
  rescue JSON::ParserError => e
52
43
  SmartPrompt.logger.error "Failed to parse Ollama API response"
53
44
  raise LLMAPIError, "Failed to parse Ollama API response"
@@ -58,7 +49,31 @@ module SmartPrompt
58
49
  SmartPrompt.logger.info "Successful send a message"
59
50
  end
60
51
  SmartPrompt.logger.info "OllamaAdapter: Received response from Ollama"
61
- return response[0]["response"]
52
+ return response.dig(0,"response")
53
+ end
54
+
55
+ def embeddings(text, model)
56
+ SmartPrompt.logger.info "OllamaAdapter: get embeddings from Ollama"
57
+ if model
58
+ model_name = model
59
+ else
60
+ model_name = @config['model']
61
+ end
62
+ SmartPrompt.logger.info "OllamaAdapter: Using model #{model_name}"
63
+ begin
64
+ response = @client.embeddings(
65
+ {
66
+ model: model_name,
67
+ prompt: text.to_s
68
+ }
69
+ )
70
+ rescue => e
71
+ SmartPrompt.logger.error "Unexpected error during Ollama request: #{e.message}"
72
+ raise Error, "Unexpected error during Ollama request: #{e.message}"
73
+ ensure
74
+ SmartPrompt.logger.info "Successful send a message"
75
+ end
76
+ return response.dig(0,"embedding")
62
77
  end
63
78
  end
64
79
  end
@@ -17,7 +17,7 @@ module SmartPrompt
17
17
  rescue OpenAI::ConfigurationError => e
18
18
  SmartPrompt.logger.error "Failed to initialize OpenAI client: #{e.message}"
19
19
  raise LLMAPIError, "Invalid OpenAI configuration: #{e.message}"
20
- rescue OpenAI::AuthenticationError => e
20
+ rescue OpenAI::Error => e
21
21
  SmartPrompt.logger.error "Failed to initialize OpenAI client: #{e.message}"
22
22
  raise LLMAPIError, "OpenAI authentication failed: #{e.message}"
23
23
  rescue SocketError => e
@@ -47,24 +47,12 @@ module SmartPrompt
47
47
  temperature: @config['temperature'] || 0.7
48
48
  }
49
49
  )
50
- rescue OpenAI::APIError => e
50
+ rescue OpenAI::Error => e
51
51
  SmartPrompt.logger.error "OpenAI API error: #{e.message}"
52
52
  raise LLMAPIError, "OpenAI API error: #{e.message}"
53
- rescue OpenAI::APIConnectionError => e
54
- SmartPrompt.logger.error "Connection error: Unable to reach OpenAI API"
55
- raise LLMAPIError, "Connection error: Unable to reach OpenAI API"
56
- rescue OpenAI::APITimeoutError => e
57
- SmartPrompt.logger.error "Request to OpenAI API timed out"
58
- raise LLMAPIError, "Request to OpenAI API timed out"
59
- rescue OpenAI::InvalidRequestError => e
60
- SmartPrompt.logger.error "Invalid request to OpenAI API: #{e.message}"
61
- raise LLMAPIError, "Invalid request to OpenAI API: #{e.message}"
62
- rescue OpenAI::AuthenticationError => e
63
- SmartPrompt.logger.error "Authentication error with OpenAI API: #{e.message}"
64
- raise LLMAPIError, "Authentication error with OpenAI API: #{e.message}"
65
- rescue OpenAI::RateLimitError => e
66
- SmartPrompt.logger.error "Rate limit exceeded for OpenAI API"
67
- raise LLMAPIError, "Rate limit exceeded for OpenAI API"
53
+ rescue OpenAI::MiddlewareErrors => e
54
+ SmartPrompt.logger.error "OpenAI HTTP Error: #{e.message}"
55
+ raise LLMAPIError, "OpenAI HTTP Error"
68
56
  rescue JSON::ParserError => e
69
57
  SmartPrompt.logger.error "Failed to parse OpenAI API response"
70
58
  raise LLMAPIError, "Failed to parse OpenAI API response"
@@ -77,5 +65,29 @@ module SmartPrompt
77
65
  SmartPrompt.logger.info "OpenAIAdapter: Received response from OpenAI"
78
66
  response.dig("choices", 0, "message", "content")
79
67
  end
68
+
69
+ def embeddings(text, model)
70
+ SmartPrompt.logger.info "OpenAIAdapter: get embeddings from Ollama"
71
+ if model
72
+ model_name = model
73
+ else
74
+ model_name = @config['model']
75
+ end
76
+ SmartPrompt.logger.info "OpenAIAdapter: Using model #{model_name}"
77
+ begin
78
+ response = @client.embeddings(
79
+ parameters: {
80
+ model: model_name,
81
+ input: text.to_s
82
+ }
83
+ )
84
+ rescue => e
85
+ SmartPrompt.logger.error "Unexpected error during Ollama request: #{e.message}"
86
+ raise Error, "Unexpected error during Ollama request: #{e.message}"
87
+ ensure
88
+ SmartPrompt.logger.info "Successful send a message"
89
+ end
90
+ return response.dig("data", 0, "embedding")
91
+ end
80
92
  end
81
93
  end
@@ -1,3 +1,3 @@
1
1
  module SmartPrompt
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.8"
3
3
  end
data/lib/smart_prompt.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require File.expand_path('../smart_prompt/version', __FILE__)
2
2
  require File.expand_path('../smart_prompt/engine', __FILE__)
3
+ require File.expand_path('../smart_prompt/api_handler', __FILE__)
3
4
  require File.expand_path('../smart_prompt/conversation', __FILE__)
4
5
  require File.expand_path('../smart_prompt/llm_adapter', __FILE__)
5
6
  require File.expand_path('../smart_prompt/openai_adapter', __FILE__)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_prompt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - zhuang biaowei
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-17 00:00:00.000000000 Z
11
+ date: 2024-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yaml
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 1.0.4
83
+ - !ruby/object:Gem::Dependency
84
+ name: retriable
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 3.1.2
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 3.1.2
83
97
  description: SmartPrompt provides a flexible DSL for managing prompts, interacting
84
98
  with multiple LLMs, and creating composable task workers.
85
99
  email:
@@ -125,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
139
  - !ruby/object:Gem::Version
126
140
  version: '0'
127
141
  requirements: []
128
- rubygems_version: 3.5.22
142
+ rubygems_version: 3.5.23
129
143
  signing_key:
130
144
  specification_version: 4
131
145
  summary: A smart prompt management and LLM interaction gem