intelli_agent 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3fca7e6fcb2e2360ccd76c9d09506f73db72dd525dfd771322a19a6982eedd52
4
+ data.tar.gz: 2bcb9b1cc62b6dfb9a6c4ecc634dab04e9c1c27a2941dd2feb6a0f8aad858934
5
+ SHA512:
6
+ metadata.gz: 3de9eaddade5b5d5f16e385ef4cbff9bd7e7eade087b4bbc04c5c8ae2c3d0cc15ef79b518536d023f3153b62a4b748e53f735b7f33a338450db403d824c86f06
7
+ data.tar.gz: aa27675fcfc8c0bcab9701b1f0e8ca6ec09eb03f8c4fd141b9c0b63465c196f9bfcf85ad8c401eeb2c32e82930f310c3ae0fbac445f43f1e5d4dd6aa6c1622e7
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # AI Agent
data/lib/ai/agent.rb ADDED
@@ -0,0 +1,71 @@
1
+ class AI::Agent
2
+ attr_reader :assistant, :thread, :instructions, :vector_store_id
3
+
4
+ def initialize(assistant_id: nil, thread_id: nil, thread_instructions: nil, vector_store_id: nil)
5
+ @openai_client = OpenAI::Client.new
6
+
7
+ assistant_id ||= ENV.fetch('OPENAI_AKAPU_CORE_ASSISTANT_ID')
8
+ @assistant = @openai_client.assistants.retrieve(id: assistant_id)
9
+
10
+ thread_params = {}
11
+
12
+ # Only one vector store can be attached, according to the OpenAI API documentation
13
+ @vector_store_id = vector_store_id
14
+ thread_params = { tool_resources: { file_search: { vector_store_ids: [vector_store_id] } } } if @vector_store_id
15
+
16
+ thread_id ||= @openai_client.threads.create(parameters: thread_params)['id']
17
+ @thread = @openai_client.threads.retrieve(id: thread_id)
18
+
19
+ @instructions = thread_instructions || @assistant['instructions']
20
+ end
21
+
22
+ def add_message(text, role: 'user')
23
+ @openai_client.messages.create(thread_id: @thread['id'], parameters: { role: role, content: text })
24
+ end
25
+
26
+ def messages
27
+ @openai_client.messages.list(thread_id: @thread['id'])
28
+ end
29
+
30
+ def last_message
31
+ messages['data'].first['content'].first['text']['value']
32
+ end
33
+
34
+ def run(instructions: nil, additional_instructions: nil, additional_message: nil, model: nil, tool_choice: nil)
35
+ params = { assistant_id: @assistant['id'] }
36
+
37
+ params[:instructions] = instructions || @instructions
38
+ params[:additional_instructions] = additional_instructions unless additional_instructions.nil?
39
+ params[:tool_choice] = tool_choice unless tool_choice.nil?
40
+
41
+ params[:additional_messages] = [{ role: :user, content: additional_message }] unless additional_message.nil?
42
+
43
+ params[:model] = model || @assistant['model']
44
+
45
+ run_id = @openai_client.runs.create(thread_id: @thread['id'], parameters: params)['id']
46
+
47
+ loop do
48
+ response = @openai_client.runs.retrieve(id: run_id, thread_id: @thread['id'])
49
+
50
+ case response['status']
51
+ when 'queued', 'in_progress', 'cancelling'
52
+ puts 'Status: Waiting AI Processing finish'
53
+ sleep 1
54
+ when 'completed'
55
+ puts last_message
56
+ break
57
+ when 'requires_action'
58
+ # Handle tool calls (see below)
59
+ when 'cancelled', 'failed', 'expired'
60
+ puts response['last_error'].inspect
61
+ break # or `exit`
62
+ else
63
+ puts "Unknown status response: #{status}"
64
+ end
65
+ end
66
+ end
67
+
68
+ def runs
69
+ @openai_client.runs.list(thread_id: @thread['id'])
70
+ end
71
+ end
File without changes
@@ -0,0 +1,77 @@
1
+ require 'test_helper'
2
+ require 'openai'
3
+
4
+ class AI::AgentTest < ActiveSupport::TestCase
5
+ def setup
6
+ @assistant_id = 'your_assistant_id'
7
+ @thread_id = 'your_thread_id'
8
+ @thread_instructions = 'your_thread_instructions'
9
+ @agent = AI::Agent.new(assistant_id: @assistant_id, thread_id: @thread_id, thread_instructions: @thread_instructions)
10
+ end
11
+
12
+ test 'add_message should create a new message in the thread' do
13
+ text = 'Hello, world!'
14
+ role = 'user'
15
+ message_params = { thread_id: @thread_id, parameters: { role: role, content: text } }
16
+
17
+ OpenAI::Client.any_instance.expects(:messages).returns(stub(create: true))
18
+ @agent.add_message(text, role: role)
19
+
20
+ assert_received(OpenAI::Client) { |expect| expect.messages.create(message_params) }
21
+ end
22
+
23
+ test 'messages should return a list of messages in the thread' do
24
+ messages_params = { thread_id: @thread_id }
25
+
26
+ OpenAI::Client.any_instance.expects(:messages).returns(stub(list: true))
27
+ @agent.messages
28
+
29
+ assert_received(OpenAI::Client) { |expect| expect.messages.list(messages_params) }
30
+ end
31
+
32
+ test 'last_message should return the content of the last message in the thread' do
33
+ message_content = 'Hello, world!'
34
+ messages_response = { 'data' => [{ 'content' => [{ 'text' => { 'value' => message_content } }] }] }
35
+
36
+ OpenAI::Client.any_instance.expects(:messages).returns(stub(list: messages_response))
37
+ assert_equal message_content, @agent.last_message
38
+ end
39
+
40
+ test 'run should create a new run in the thread' do
41
+ instructions = 'your_instructions'
42
+ additional_instructions = 'your_additional_instructions'
43
+ model = 'your_model'
44
+ run_params = { assistant_id: @assistant_id, instructions: instructions, additional_instructions: additional_instructions, model: model }
45
+
46
+ OpenAI::Client.any_instance.expects(:runs).returns(stub(create: true))
47
+ @agent.run(instructions: instructions, additional_instructions: additional_instructions, model: model)
48
+
49
+ assert_received(OpenAI::Client) { |expect| expect.runs.create(run_params) }
50
+ end
51
+
52
+ test 'runs should return a list of runs in the thread' do
53
+ runs_params = { thread_id: @thread_id }
54
+
55
+ OpenAI::Client.any_instance.expects(:runs).returns(stub(list: true))
56
+ @agent.runs
57
+
58
+ assert_received(OpenAI::Client) { |expect| expect.runs.list(runs_params) }
59
+ end
60
+ endrequire 'test_helper'
61
+ require 'artificial_intelligence/ai/agent'
62
+
63
+ class AI::AgentTest < ActiveSupport::TestCase
64
+ def setup
65
+ @agent = AI::Agent.new
66
+ end
67
+
68
+ test "agent can perform action" do
69
+ # Add your test logic here
70
+ end
71
+
72
+ test "agent can learn from experience" do
73
+ # Add your test logic here
74
+ end
75
+
76
+ # Add more tests as needed
77
+ end
File without changes
data/lib/ai.rb ADDED
@@ -0,0 +1,56 @@
1
+ # In the future, this became a bus to more than one AI provider
2
+ module AI
3
+ BASIC_MODEL = ENV.fetch('OPENAI_BASIC_MODEL')
4
+ ADVANCED_MODEL = ENV.fetch('OPENAI_ADVANCED_MODEL')
5
+
6
+ def self.embed(input, model: 'text-embedding-3-large')
7
+ response = OpenAI::Client.new.embeddings(parameters: { input:, model: })
8
+ response.dig('data', 0, 'embedding')
9
+ end
10
+
11
+ def self.single_prompt(prompt:, model: AI::BASIC_MODEL, response_format: nil)
12
+ parameters = { model:, messages: [{ role: 'user', content: prompt }] }
13
+
14
+ parameters[:response_format] = { type: 'json_object' } if response_format.eql?(:json)
15
+
16
+ response = OpenAI::Client.new.chat(parameters:)
17
+ response.dig('choices', 0, 'message', 'content').strip
18
+ end
19
+
20
+ def self.vision(prompt:, image_url:, response_format: nil)
21
+ messages = [{ type: :text, text: prompt },
22
+ { type: :image_url, image_url: { url: image_url } }]
23
+
24
+ parameters = { model: AI::ADVANCED_MODEL, messages: [{ role: :user, content: messages }] }
25
+ parameters[:response_format] = { type: 'json_object' } if response_format.eql?(:json)
26
+
27
+ response = OpenAI::Client.new.chat(parameters:)
28
+
29
+ response.dig('choices', 0, 'message', 'content').strip
30
+ end
31
+
32
+ def self.single_chat(system:, user:, model: AI::BASIC_MODEL, response_format: nil)
33
+ parameters = { model:,
34
+ messages: [
35
+ { role: 'system', content: system },
36
+ { role: 'user', content: user }
37
+ ] }
38
+
39
+ parameters[:response_format] = { type: 'json_object' } if response_format.eql?(:json)
40
+
41
+ response = OpenAI::Client.new.chat(parameters:)
42
+ response.dig('choices', 0, 'message', 'content').strip
43
+ end
44
+
45
+ def self.chat(messages, model: AI::BASIC_MODEL, response_format: nil)
46
+ parameters = { model:, messages: }
47
+ parameters[:response_format] = { type: 'json_object' } if response_format.eql?(:json)
48
+
49
+ response = OpenAI::Client.new.chat(parameters:)
50
+ response.dig('choices', 0, 'message', 'content').strip
51
+ end
52
+
53
+ def self.models
54
+ OpenAI::Client.new.models.list
55
+ end
56
+ end
File without changes
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: intelli_agent
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Gedean Dias
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-07-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby-openai
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '7.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '7.1'
27
+ description: AI Agent.
28
+ email: gedean.dias@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - README.md
34
+ - lib/ai.rb
35
+ - lib/ai.rb:Zone.Identifier
36
+ - lib/ai/agent.rb
37
+ - lib/ai/agent.rb:Zone.Identifier
38
+ - lib/ai/agent_test.rb_
39
+ - lib/ai/agent_test.rb_:Zone.Identifier
40
+ homepage: https://github.com/gedean/intelli_agent
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message: Please check readme file for use instructions.
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '3'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubygems_version: 3.5.16
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: AI Agent
63
+ test_files: []