ruby_conversations 1.1.0 → 1.1.2

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: dd956939c0daaea90e866266a6ab8a5bba2b3ec9bb295c81a6f2e902b163d968
4
- data.tar.gz: a03a9a78205f79a6d4850cb7cd58ca0fc7413b0754e62563b541b8adc1b32917
3
+ metadata.gz: ebe08b35dd3c009e6bd81c5fb6bbb8e9d109d51b76d4469a8af13deeadaebfc5
4
+ data.tar.gz: db51099d58654198bcbb1d0c873896f729170937798b0f8cee7928cc44dc5e3c
5
5
  SHA512:
6
- metadata.gz: abab8e151b670375b5486c7915eb921f1c24943b6f20d65f56229428d7254afe8ef18d98fe957df82de16e6219d9b4196489044fcee6e04887b201c8b2528833
7
- data.tar.gz: 3f4e262b42234bb4ed48a18d11a165edc932f75999c64f13afe8aa2b93ccd04b2e4370c3ad4b90470882e299947133831ff712a71d6418a3f36773127b21d7f2
6
+ metadata.gz: 78866ece10dffbce9e4daaa3b6fff1dd8b019663b5c0f665f4043b984b8de17a4c004ae23e62a490eae3626540be14f0811a3b9fef7b00c18f7593789dced64a
7
+ data.tar.gz: 84cd8cfe96fad9343323ecd5080586647ab2bb762290954b2aa8887c875f628d96c12d6b61a4473489ea584c2b2cb5749b35cb5632f129e71e5b903a5c890666
data/README.md CHANGED
@@ -7,9 +7,7 @@ A Rails engine for managing AI conversations and storing them in prompt studio.
7
7
  - **Built-in Prompt Management**: Version-controlled prompts with placeholder validation
8
8
  - **Conversation History**: Track and manage conversation threads
9
9
  - **Input/Output Storage**: Structured storage for message inputs and responses
10
- - **Real-time Updates**: Built-in broadcasting support for real-time applications
11
10
  - **JWT Authentication**: Secure remote mode with JWT authentication
12
- - **Easy Integration**: Simple setup with Rails generators
13
11
 
14
12
  ## Installation
15
13
 
@@ -36,7 +34,7 @@ gem install ruby_conversations
36
34
  Configure the engine in `config/initializers/ai_conversation_engine.rb`:
37
35
 
38
36
  ```ruby
39
- AiConversationEngine.configure do |config|
37
+ RubyConversations.configure do |config|
40
38
  # API settings
41
39
  config.api_url = ENV['AI_CONVERSATION_API_URL']
42
40
  config.jwt_secret = ENV['AI_CONVERSATION_JWT_SECRET']
@@ -51,34 +49,13 @@ end
51
49
 
52
50
  ```ruby
53
51
  # Create a new conversation
54
- conversation = AiConversation.create!
52
+ conversation = RubyConversations::Conversation.new
55
53
 
56
54
  # Ask a question using a predefined prompt
57
- conversation.ask("explain_code", inputs: { code: "def hello; end" })
58
- ```
59
-
60
- ### With Associated Objects
61
-
62
- ```ruby
63
- # Create a conversation linked to another object
64
- class Project < ApplicationRecord
65
- has_many :conversations, as: :conversationable,
66
- class_name: 'AiConversationEngine::AiConversation'
67
- end
68
-
69
- project = Project.find(1)
70
- conversation = project.conversations.create!
71
- conversation.ask("analyze_project", inputs: { name: project.name })
72
- ```
73
-
74
-
75
- ### Real-time Updates
76
-
77
- ```ruby
78
- # In your view
79
- <%= turbo_stream_from "chat_#{@conversation.id}" %>
55
+ conversation.with_prompt("explain_code", inputs: { code: "def hello; end" })
56
+ result = conversation.call_llm
80
57
 
81
- # Updates are automatically broadcast when messages are added
58
+ puts result[:content]
82
59
  ```
83
60
 
84
61
  ## Development
@@ -6,15 +6,17 @@ module RubyConversations
6
6
  module ConversationChat
7
7
  extend ActiveSupport::Concern
8
8
 
9
- def execute(system_message: nil)
9
+ def call_llm(system_message: nil, &block)
10
10
  validate_conversation_state
11
- chat_messages = generate_chat_response(system_message)
11
+ chat_messages = generate_chat_response(system_message, &block)
12
12
 
13
13
  validate_tool_calls(chat_messages)
14
14
 
15
15
  store_and_update_conversation(chat_messages)
16
16
  end
17
17
 
18
+ alias execute call_llm
19
+
18
20
  def validate_tool_calls(chat_messages)
19
21
  return unless tools_configured?
20
22
  return if tool_calls?(chat_messages)
@@ -50,9 +52,9 @@ module RubyConversations
50
52
  raise ArgumentError, 'Conversation must have at least one message to execute' unless message
51
53
  end
52
54
 
53
- def generate_chat_response(system_message)
55
+ def generate_chat_response(system_message, &)
54
56
  setup_llm_chat(system_message: system_message)
55
- chat.ask(messages.last.request)
57
+ chat.ask(messages.last.request, &)
56
58
  chat.messages
57
59
  end
58
60
 
@@ -62,7 +64,8 @@ module RubyConversations
62
64
 
63
65
  {
64
66
  response: chat_messages,
65
- conversation: self
67
+ conversation: self,
68
+ content: chat_messages.last.content
66
69
  }
67
70
  end
68
71
 
@@ -17,15 +17,20 @@ module RubyConversations
17
17
  end
18
18
  end
19
19
 
20
- def ask_multiple(prompt_inputs, description: nil)
20
+ def with_prompts(prompt_inputs, description: nil)
21
21
  MessageBuilder.new(self).build_from_multiple_prompts(prompt_inputs, description: description)
22
22
  self
23
23
  end
24
24
 
25
- def ask(name, description: nil, inputs: {})
25
+ def with_prompt(name, description: nil, inputs: {})
26
26
  MessageBuilder.new(self).build_from_single_prompt(name, description: description, inputs: inputs)
27
27
  self
28
28
  end
29
+
30
+ def with_user_message(message, description: nil)
31
+ MessageBuilder.new(self).build_from_user_message(message, description: description)
32
+ self
33
+ end
29
34
  end
30
35
  end
31
36
  end
@@ -3,22 +3,14 @@
3
3
  module RubyConversations
4
4
  module Concerns
5
5
  # Handles the management of LLM credentials for AI conversations.
6
- # This concern provides methods for configuring LLM credentials from either
6
+ # Provides methods for configuring LLM credentials from either
7
7
  # environment variables or an AWS credential provider.
8
8
  module LlmCredentials
9
9
  extend ActiveSupport::Concern
10
10
 
11
- class_methods do
12
- def configure_llm_credentials
13
- RubyLLM.configure do |config|
14
- credentials = provider_credentials
15
- config.bedrock_region = ENV.fetch('AWS_REGION', 'us-west-2')
16
- config.bedrock_api_key = credentials[:api_key]
17
- config.bedrock_secret_key = credentials[:secret_key]
18
- config.bedrock_session_token = credentials[:session_token]
19
- end
20
- end
21
-
11
+ # Helper methods for retrieving AWS credentials from different sources
12
+ # These methods are meant to be used as class methods in the LlmCredentials module
13
+ module CredentialHelpers
22
14
  private
23
15
 
24
16
  def env_credentials
@@ -30,16 +22,30 @@ module RubyConversations
30
22
  end
31
23
 
32
24
  def provider_credentials
33
- credential_provider = AwsCredentialProvider.instance
34
- credential_provider.refresh_if_expired!
25
+ provider = AwsCredentialProvider.instance
26
+ provider.refresh_if_expired!
35
27
  {
36
- api_key: credential_provider.access_key_id,
37
- secret_key: credential_provider.secret_access_key,
38
- session_token: credential_provider.session_token
28
+ api_key: provider.access_key_id,
29
+ secret_key: provider.secret_access_key,
30
+ session_token: provider.session_token
39
31
  }
40
32
  end
41
33
  end
42
34
 
35
+ class_methods do
36
+ include CredentialHelpers
37
+
38
+ def configure_llm_credentials
39
+ RubyLLM.configure do |config|
40
+ creds = provider_credentials
41
+ config.bedrock_region = ENV.fetch('AWS_REGION', 'us-west-2')
42
+ config.bedrock_api_key = creds[:api_key]
43
+ config.bedrock_secret_key = creds[:secret_key]
44
+ config.bedrock_session_token = creds[:session_token]
45
+ end
46
+ end
47
+ end
48
+
43
49
  def configure_llm_credentials
44
50
  self.class.configure_llm_credentials
45
51
  end
@@ -13,36 +13,22 @@ module RubyConversations
13
13
  include RubyConversations::Concerns::MessageProcessing
14
14
 
15
15
  # Define attributes needed for API interaction & local state
16
- attr_accessor :chat, :id, :conversationable_type, :conversationable_id, :conversationable,
17
- :messages, :tool, :tools, :created_at, :updated_at, :persist
16
+ attr_accessor :id, :conversationable_type, :conversationable_id, :conversationable,
17
+ :messages, :tool, :tools, :created_at, :updated_at
18
18
 
19
19
  # Validations
20
20
  validates :messages, presence: { message: 'At least one message is required' }, on: :update
21
21
  validate :validate_messages
22
22
 
23
23
  # Initialization
24
- def initialize(attributes = nil)
25
- attributes ||= {}
26
- # Ensure messages is always an array before super assigns other attributes
24
+ def initialize(attributes = {})
25
+ @chat = attributes.delete(:chat)
27
26
  @messages = []
28
- # Extract nested attributes before super tries to assign them
29
- messages_attrs = attributes.delete(:messages) || attributes.delete('messages') ||
30
- attributes.delete(:messages_attributes) || attributes.delete('messages_attributes') || []
31
- # Extract persist flag, default to false
32
- @persist = attributes.delete(:persist) || attributes.delete('persist') || false
33
-
34
- super # Initialize with remaining attributes using ActiveModel::Model
35
- initialize_messages(messages_attrs)
36
-
37
- build_chat
27
+ super
38
28
  end
39
29
 
40
- def build_chat
41
- @chat = if @persist && RubyConversations.configuration.persistence_model
42
- resolve_persistence_model.create!(model_id: llm, provider: provider)
43
- else
44
- RubyLLM.chat(model: llm, provider: provider).with_temperature(0.0)
45
- end
30
+ def chat
31
+ @chat ||= RubyLLM.chat(model: llm, provider: provider).with_temperature(0.0)
46
32
  end
47
33
 
48
34
  def model_identifier
@@ -53,36 +39,12 @@ module RubyConversations
53
39
  @provider ||= RubyConversations.configuration.default_llm_provider
54
40
  end
55
41
 
56
- def initialize_messages(message_attributes)
57
- (message_attributes || []).each do |msg_data|
58
- processed_prompts = process_message_prompts(msg_data)
59
-
60
- message_instance = RubyConversations::Message.new(msg_data.except('id', 'conversation_id', 'created_at',
61
- 'updated_at'))
62
- message_instance.message_prompts = processed_prompts
63
- @messages << message_instance # Add to the messages array
64
- end
65
- end
66
-
67
42
  def conversation_attributes_for_storage
68
43
  { ai_conversation: base_attributes.merge(relationship_attributes).merge(messages_attributes).compact }
69
44
  end
70
45
 
71
46
  private
72
47
 
73
- def resolve_persistence_model
74
- model_config = RubyConversations.configuration.persistence_model
75
- unless model_config.is_a?(String)
76
- raise ConfigurationError, "Invalid persistence_model configured: Must be a String, got #{model_config.class}"
77
- end
78
-
79
- model_config.safe_constantize || raise(ConfigurationError,
80
- "Invalid persistence_model configured: '#{model_config}' could not be resolved.")
81
- rescue NameError => e
82
- # Catch potential NameError from constantize if the class name is invalid
83
- raise ConfigurationError, "Invalid persistence_model configured: #{e.message}"
84
- end
85
-
86
48
  def base_attributes
87
49
  {
88
50
  id: id
@@ -15,7 +15,13 @@ module RubyConversations
15
15
  message = build_message(interpolated_message, description)
16
16
  build_prompt_association(message, prompt, inputs)
17
17
 
18
- message # Return the built message
18
+ message
19
+ end
20
+
21
+ def build_from_user_message(raw_message, description: nil)
22
+ message = build_message(raw_message, description)
23
+ build_message_prompt(message, Prompt.new(name: 'user_message', role: 'user', message: raw_message))
24
+ message
19
25
  end
20
26
 
21
27
  def build_from_multiple_prompts(prompt_inputs, description: nil)
@@ -3,7 +3,7 @@
3
3
  module RubyConversations
4
4
  # Configuration options for RubyConversations
5
5
  class Configuration
6
- attr_accessor :api_url, :jwt_secret, :default_llm_model, :default_llm_provider, :persistence_model
6
+ attr_accessor :api_url, :jwt_secret, :default_llm_model, :default_llm_provider
7
7
 
8
8
  def initialize
9
9
  @default_llm_model = 'claude-3-7-sonnet'
@@ -3,7 +3,7 @@
3
3
  module RubyConversations
4
4
  MAJOR = 1
5
5
  MINOR = 1
6
- PATCH = 0
6
+ PATCH = 2
7
7
 
8
8
  VERSION = "#{RubyConversations::MAJOR}.#{RubyConversations::MINOR}.#{RubyConversations::PATCH}".freeze
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_conversations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Shippy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-25 00:00:00.000000000 Z
11
+ date: 2025-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport