active_intelligence 0.1.0 → 0.2.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/README.md +50 -1
- data/app/models/active_intelligence/chat.rb +31 -0
- data/app/models/active_intelligence/chat_message.rb +12 -0
- data/app/models/concerns/active_intelligence/promptable.rb +6 -5
- data/app/services/active_intelligence/application_service.rb +13 -0
- data/app/services/active_intelligence/chat_repl_service.rb +73 -0
- data/config/initializers/inflections.rb +1 -0
- data/db/migrate/20240520181009_create_active_intelligence_chats.rb +8 -0
- data/db/migrate/20240520185221_create_active_intelligence_chat_messages.rb +10 -0
- data/lib/active_intelligence/asr/aws_adapter.rb +2 -1
- data/lib/active_intelligence/concerns/openai.rb +1 -0
- data/lib/active_intelligence/config.rb +2 -1
- data/lib/active_intelligence/llm/adapter.rb +4 -0
- data/lib/active_intelligence/llm/openai_adapter.rb +19 -2
- data/lib/active_intelligence/version.rb +1 -1
- data/lib/tasks/active_intelligence_tasks.rake +9 -4
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ca1684233da615710eb4627d5f5dd36de700412b55ab9d3bfc33f28ba1b19b6
|
4
|
+
data.tar.gz: b7916597e70b62d5c70af58df106fa881d678d96d378eaae44434c993f0c60d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 179e855f89af509ab9fd3860344df57cefde149b36fccdad3bf9b4d7cbc49f91f5486bcaf01c3f551a7e4e0c83d600ceeef6652951cf0ffcb22b8887d369d841
|
7
|
+
data.tar.gz: a933ec32b319a915ed17a9c1bb4266595fba0a538805046ee4ac98337a678bf6a7664e44472d5ed7a156f34db32f9cb0ca87856ab5035cca49fe59aa7dba4673
|
data/README.md
CHANGED
@@ -19,6 +19,11 @@ And then execute:
|
|
19
19
|
$ bundle
|
20
20
|
```
|
21
21
|
|
22
|
+
To install migrations:
|
23
|
+
```bash
|
24
|
+
rails active_intelligence:install:migrations
|
25
|
+
```
|
26
|
+
|
22
27
|
## LLM Usage
|
23
28
|
|
24
29
|
### 1. Configuration
|
@@ -32,7 +37,7 @@ openai: &openai
|
|
32
37
|
|
33
38
|
development:
|
34
39
|
<<: *openai
|
35
|
-
model: gpt-4-
|
40
|
+
model: gpt-4-turbo
|
36
41
|
temperature: 0.0
|
37
42
|
```
|
38
43
|
|
@@ -62,6 +67,50 @@ default_response = user.from_llm
|
|
62
67
|
invite_response = user.from_llm(:invite)
|
63
68
|
```
|
64
69
|
|
70
|
+
## Chat
|
71
|
+
|
72
|
+
|
73
|
+
```mermaid
|
74
|
+
erDiagram
|
75
|
+
Chat {
|
76
|
+
integer id
|
77
|
+
}
|
78
|
+
ChatMessage {
|
79
|
+
integer id
|
80
|
+
integer chat_id
|
81
|
+
string role
|
82
|
+
string content
|
83
|
+
}
|
84
|
+
Chat ||--o{ ChatMessage : has_many
|
85
|
+
```
|
86
|
+
|
87
|
+
### 6. Create a chat prompt
|
88
|
+
|
89
|
+
```
|
90
|
+
# app/prompts/active_intelligence/chat.erb
|
91
|
+
|
92
|
+
* Your name is Poe. You are a fan of Edgar Allan Poe.
|
93
|
+
* You are the AI propritor of the Raven Hotel.
|
94
|
+
* You exhibit the utmost sincerity and hostpitality.
|
95
|
+
```
|
96
|
+
|
97
|
+
### 7. Create a chat, add a message, and get a reply
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
include ActiveIntelligence
|
101
|
+
|
102
|
+
chat = Chat.create!
|
103
|
+
chat.messages.create!(role: 'user', content: "Hi! Who are you?")
|
104
|
+
puts chat.reply.content
|
105
|
+
````
|
106
|
+
|
107
|
+
### 8. Chat using the REPL
|
108
|
+
|
109
|
+
```
|
110
|
+
rake active_intelligence:chat
|
111
|
+
rake active_intelligence:chat[id]
|
112
|
+
```
|
113
|
+
|
65
114
|
## ASR Usage
|
66
115
|
|
67
116
|
### 1. Configuration
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveIntelligence
|
4
|
+
class Chat < ApplicationRecord
|
5
|
+
include Promptable
|
6
|
+
|
7
|
+
has_many :messages,
|
8
|
+
class_name: ActiveIntelligence::ChatMessage.to_s,
|
9
|
+
dependent: :destroy,
|
10
|
+
counter_cache: :messages_count
|
11
|
+
|
12
|
+
def as_json(options = {})
|
13
|
+
if options.empty?
|
14
|
+
options[:only] = %i[id created_at updated_at]
|
15
|
+
options[:methods] = %i[messages_count]
|
16
|
+
options[:include] = [messages: { only: %i[id role content created_at updated_at] }]
|
17
|
+
end
|
18
|
+
|
19
|
+
super(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def reply(options = {})
|
23
|
+
options = options.dup
|
24
|
+
llm = ActiveIntelligence::LLM::Config.new.adapter(options[:adapter])
|
25
|
+
prompt = options.delete(:prompt) || to_prompt(options.delete(:name))
|
26
|
+
|
27
|
+
reply = llm.reply(self, prompt, options)
|
28
|
+
return messages.create!(role: 'assistant', content: reply)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -5,16 +5,17 @@ module ActiveIntelligence
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
def from_llm(template = nil,
|
9
|
-
|
10
|
-
|
8
|
+
def from_llm(template = nil, options = {})
|
9
|
+
adapter = options[:adapter]
|
10
|
+
llm = ActiveIntelligence::LLM::Config.new.adapter(adapter)
|
11
|
+
return llm.generate(to_prompt(template, options))
|
11
12
|
end
|
12
13
|
|
13
|
-
def to_prompt(name = nil)
|
14
|
+
def to_prompt(name = nil, options = {})
|
14
15
|
template = self.class.name.pluralize.underscore
|
15
16
|
template = [template, name].join('/') if name
|
16
17
|
|
17
|
-
assigns = { self: self }
|
18
|
+
assigns = { self: self }.merge(options[:assigns] || {})
|
18
19
|
prompt = ActiveIntelligence::LLM::Prompt.new(template, assigns)
|
19
20
|
return prompt.render
|
20
21
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# SEE: https://www.toptal.com/ruby-on-rails/rails-service-objects-tutorial
|
4
|
+
|
5
|
+
module ActiveIntelligence
|
6
|
+
class ApplicationService
|
7
|
+
def self.call(*args, &block)
|
8
|
+
new(*args, &block).call
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(*_args, &_block); end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveIntelligence
|
4
|
+
class ChatREPLService < ApplicationService
|
5
|
+
# rubocop:disable Rails/Output
|
6
|
+
|
7
|
+
def initialize(chat)
|
8
|
+
super
|
9
|
+
|
10
|
+
@chat = chat
|
11
|
+
@counter = 1
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
header
|
16
|
+
help
|
17
|
+
history
|
18
|
+
loop { cycle || break }
|
19
|
+
end
|
20
|
+
|
21
|
+
def cycle
|
22
|
+
print prefix(:user)
|
23
|
+
input = $stdin.gets.chomp
|
24
|
+
case input
|
25
|
+
when 'h' then help
|
26
|
+
when 'p' then prompt
|
27
|
+
when 'q' then return false
|
28
|
+
else reply(input)
|
29
|
+
end
|
30
|
+
|
31
|
+
return true
|
32
|
+
end
|
33
|
+
|
34
|
+
def header
|
35
|
+
puts "Chat #{@chat.id}\n"
|
36
|
+
end
|
37
|
+
|
38
|
+
def help
|
39
|
+
puts <<~HELP
|
40
|
+
|
41
|
+
h - help
|
42
|
+
p - prompt
|
43
|
+
q - quit
|
44
|
+
HELP
|
45
|
+
end
|
46
|
+
|
47
|
+
def history
|
48
|
+
@chat.messages.order(:id).each do |message|
|
49
|
+
@counter += 1
|
50
|
+
puts [prefix(message.role), message.content].join
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def prefix(name)
|
55
|
+
"\n(#{name}:#{@counter})> "
|
56
|
+
end
|
57
|
+
|
58
|
+
def prompt
|
59
|
+
puts ["\n", @chat.to_prompt].join
|
60
|
+
end
|
61
|
+
|
62
|
+
def reply(input)
|
63
|
+
@chat.messages.create!(role: 'user', content: input)
|
64
|
+
|
65
|
+
@counter += 1
|
66
|
+
print prefix(:assistant)
|
67
|
+
puts @chat.reply.content
|
68
|
+
@counter += 1
|
69
|
+
end
|
70
|
+
|
71
|
+
# rubocop:enable Rails/Output
|
72
|
+
end
|
73
|
+
end
|
@@ -57,11 +57,12 @@ module ActiveIntelligence
|
|
57
57
|
|
58
58
|
def parameters(key, options)
|
59
59
|
now = Time.now.to_i
|
60
|
+
format = options.delete(:format) # TODO: This ain't good
|
60
61
|
|
61
62
|
parameters = {
|
62
63
|
transcription_job_name: "transcribe-#{now}",
|
63
64
|
language_code: settings[:language_code] || 'en-US',
|
64
|
-
media_format:
|
65
|
+
media_format: format || format(key),
|
65
66
|
media: { media_file_uri: s3_url(key) },
|
66
67
|
output_bucket_name: settings[:bucket],
|
67
68
|
output_key: s3_path("transcribe-#{now}.json")
|
@@ -7,13 +7,30 @@ module ActiveIntelligence
|
|
7
7
|
class OpenAIAdapter < Adapter
|
8
8
|
include ActiveIntelligence::Concerns::OpenAI
|
9
9
|
|
10
|
+
def chat(parameters)
|
11
|
+
response = client.chat(parameters:)
|
12
|
+
return response.dig('choices', 0, 'message', 'content')
|
13
|
+
end
|
14
|
+
|
10
15
|
def generate(prompt, _options = {})
|
11
16
|
parameters = default_parameters
|
12
17
|
parameters[:messages] = [{ role: 'user', content: prompt }]
|
13
18
|
|
14
|
-
|
19
|
+
return chat(parameters)
|
20
|
+
end
|
15
21
|
|
16
|
-
|
22
|
+
def reply(chat, prompt, options = {})
|
23
|
+
limit = options[:limit] || settings[:chat_message_limit] || 10
|
24
|
+
|
25
|
+
parameters = default_parameters
|
26
|
+
parameters[:messages] = [{ role: 'system', content: prompt }]
|
27
|
+
|
28
|
+
messages = chat.messages.order(created_at: :desc).limit(limit).reverse
|
29
|
+
messages.each do |message|
|
30
|
+
parameters[:messages] << { role: message.role, content: message.content }
|
31
|
+
end
|
32
|
+
|
33
|
+
return chat(parameters)
|
17
34
|
end
|
18
35
|
end
|
19
36
|
end
|
@@ -1,6 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
namespace :active_intelligence do
|
4
|
+
include ActiveIntelligence
|
5
|
+
|
6
|
+
desc 'Chat with the LLM'
|
7
|
+
task :chat, [:id] => :environment do |_t, args|
|
8
|
+
chat = args[:id].nil? ? Chat.create! : Chat.find(args[:id])
|
9
|
+
ChatREPLService.call(chat)
|
10
|
+
end
|
11
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_intelligence
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rich Humphrey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -97,10 +97,16 @@ files:
|
|
97
97
|
- app/jobs/active_intelligence/application_job.rb
|
98
98
|
- app/mailers/active_intelligence/application_mailer.rb
|
99
99
|
- app/models/active_intelligence/application_record.rb
|
100
|
+
- app/models/active_intelligence/chat.rb
|
101
|
+
- app/models/active_intelligence/chat_message.rb
|
100
102
|
- app/models/concerns/active_intelligence/promptable.rb
|
103
|
+
- app/services/active_intelligence/application_service.rb
|
104
|
+
- app/services/active_intelligence/chat_repl_service.rb
|
101
105
|
- app/views/layouts/active_intelligence/application.html.erb
|
102
106
|
- config/initializers/inflections.rb
|
103
107
|
- config/routes.rb
|
108
|
+
- db/migrate/20240520181009_create_active_intelligence_chats.rb
|
109
|
+
- db/migrate/20240520185221_create_active_intelligence_chat_messages.rb
|
104
110
|
- lib/active_intelligence.rb
|
105
111
|
- lib/active_intelligence/adapter.rb
|
106
112
|
- lib/active_intelligence/asr/adapter.rb
|