scout-ai 0.2.0 → 1.0.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/.vimproject +91 -10
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/bin/scout-ai +2 -0
- data/lib/scout/llm/agent/chat.rb +24 -0
- data/lib/scout/llm/agent.rb +13 -13
- data/lib/scout/llm/ask.rb +26 -16
- data/lib/scout/llm/backends/bedrock.rb +129 -0
- data/lib/scout/llm/backends/huggingface.rb +6 -21
- data/lib/scout/llm/backends/ollama.rb +69 -36
- data/lib/scout/llm/backends/openai.rb +85 -35
- data/lib/scout/llm/backends/openwebui.rb +1 -1
- data/lib/scout/llm/backends/relay.rb +3 -2
- data/lib/scout/llm/backends/responses.rb +272 -0
- data/lib/scout/llm/chat.rb +547 -0
- data/lib/scout/llm/parse.rb +70 -13
- data/lib/scout/llm/tools.rb +126 -5
- data/lib/scout/llm/utils.rb +17 -10
- data/lib/scout/model/base.rb +19 -0
- data/lib/scout/model/python/base.rb +25 -0
- data/lib/scout/model/python/huggingface/causal/next_token.rb +23 -0
- data/lib/scout/model/python/huggingface/causal.rb +29 -0
- data/lib/scout/model/python/huggingface/classification +0 -0
- data/lib/scout/model/python/huggingface/classification.rb +50 -0
- data/lib/scout/model/python/huggingface.rb +112 -0
- data/lib/scout/model/python/torch/dataloader.rb +57 -0
- data/lib/scout/model/python/torch/helpers.rb +84 -0
- data/lib/scout/model/python/torch/introspection.rb +34 -0
- data/lib/scout/model/python/torch/load_and_save.rb +47 -0
- data/lib/scout/model/python/torch.rb +94 -0
- data/lib/scout/model/util/run.rb +181 -0
- data/lib/scout/model/util/save.rb +81 -0
- data/lib/scout-ai.rb +3 -1
- data/python/scout_ai/__init__.py +35 -0
- data/python/scout_ai/__pycache__/__init__.cpython-310.pyc +0 -0
- data/python/scout_ai/__pycache__/__init__.cpython-311.pyc +0 -0
- data/python/scout_ai/__pycache__/huggingface.cpython-310.pyc +0 -0
- data/python/scout_ai/__pycache__/huggingface.cpython-311.pyc +0 -0
- data/python/scout_ai/__pycache__/util.cpython-310.pyc +0 -0
- data/python/scout_ai/__pycache__/util.cpython-311.pyc +0 -0
- data/python/scout_ai/atcold/__init__.py +0 -0
- data/python/scout_ai/atcold/plot_lib.py +141 -0
- data/python/scout_ai/atcold/spiral.py +27 -0
- data/python/scout_ai/huggingface/data.py +48 -0
- data/python/scout_ai/huggingface/eval.py +60 -0
- data/python/scout_ai/huggingface/model.py +29 -0
- data/python/scout_ai/huggingface/rlhf.py +83 -0
- data/python/scout_ai/huggingface/train/__init__.py +34 -0
- data/python/scout_ai/huggingface/train/__pycache__/__init__.cpython-310.pyc +0 -0
- data/python/scout_ai/huggingface/train/__pycache__/next_token.cpython-310.pyc +0 -0
- data/python/scout_ai/huggingface/train/next_token.py +315 -0
- data/python/scout_ai/language_model.py +70 -0
- data/python/scout_ai/util.py +32 -0
- data/scout-ai.gemspec +130 -0
- data/scout_commands/agent/ask +133 -15
- data/scout_commands/agent/kb +15 -0
- data/scout_commands/llm/ask +71 -12
- data/scout_commands/llm/process +4 -2
- data/test/data/cat.jpg +0 -0
- data/test/scout/llm/agent/test_chat.rb +14 -0
- data/test/scout/llm/backends/test_bedrock.rb +60 -0
- data/test/scout/llm/backends/test_huggingface.rb +3 -3
- data/test/scout/llm/backends/test_ollama.rb +48 -10
- data/test/scout/llm/backends/test_openai.rb +96 -11
- data/test/scout/llm/backends/test_responses.rb +115 -0
- data/test/scout/llm/test_ask.rb +1 -0
- data/test/scout/llm/test_chat.rb +214 -0
- data/test/scout/llm/test_parse.rb +81 -2
- data/test/scout/model/python/huggingface/causal/test_next_token.rb +59 -0
- data/test/scout/model/python/huggingface/test_causal.rb +33 -0
- data/test/scout/model/python/huggingface/test_classification.rb +30 -0
- data/test/scout/model/python/test_base.rb +44 -0
- data/test/scout/model/python/test_huggingface.rb +9 -0
- data/test/scout/model/python/test_torch.rb +71 -0
- data/test/scout/model/python/torch/test_helpers.rb +14 -0
- data/test/scout/model/test_base.rb +117 -0
- data/test/scout/model/util/test_save.rb +31 -0
- metadata +72 -5
- data/questions/coach +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c66f7d74bdf6583e77cb7dd132bfc7d677399cc5ddeb42d59cacdef2c432d72
|
4
|
+
data.tar.gz: 9dcdc99b701696dd724394124a02bac3bde5706d94d9efad81c0ab11641d4e47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a72b0575c3c92eb4dfa413bada73c4448f85434ee99fe446b204b29e789142ac7cdd0fab3f422b994c3eb663c254dbbb097ae2fe0bd27aa7c56815690ee79289
|
7
|
+
data.tar.gz: 15616e4363983823e17ace7c866f49772e954e75eeae5b6677fb32bda322d9608be508594393cd0e032b0bc1666fe2a561b444a0b2af27360577c86f51f6c028
|
data/.vimproject
CHANGED
@@ -1,10 +1,47 @@
|
|
1
|
-
scout-ai
|
1
|
+
scout-ai=$PWD filter="*.rb *.rake Rakefile *.rdoc *.R *.sh *.js *.haml *.sass *.txt *.conf" {
|
2
2
|
Rakefile
|
3
3
|
bin=bin filter="*"{
|
4
4
|
scout-ai
|
5
5
|
}
|
6
|
-
|
7
|
-
|
6
|
+
agents=agents{
|
7
|
+
analyst.rb
|
8
|
+
}
|
9
|
+
chats=chats{
|
10
|
+
system=system{
|
11
|
+
scout-ai
|
12
|
+
}
|
13
|
+
doc=doc{
|
14
|
+
chat
|
15
|
+
model.analysis
|
16
|
+
model
|
17
|
+
}
|
18
|
+
develop=develop{
|
19
|
+
training=training{
|
20
|
+
intro
|
21
|
+
basics
|
22
|
+
data=data{
|
23
|
+
main
|
24
|
+
next_token
|
25
|
+
}
|
26
|
+
data.tmp
|
27
|
+
python
|
28
|
+
}
|
29
|
+
chat
|
30
|
+
model
|
31
|
+
causalLM
|
32
|
+
rf
|
33
|
+
}
|
34
|
+
refactor=refactor{
|
35
|
+
chat
|
36
|
+
}
|
37
|
+
help=help{
|
38
|
+
tools
|
39
|
+
from_pretrained
|
40
|
+
fine-tunning
|
41
|
+
}
|
42
|
+
test=test{
|
43
|
+
rf.rb
|
44
|
+
}
|
8
45
|
}
|
9
46
|
lib=lib {
|
10
47
|
scout-ai.rb
|
@@ -12,24 +49,72 @@ scout-ai=/$PWD filter="*.rb *.rake Rakefile *.rdoc *.R *.sh *.js *.haml *.sass *
|
|
12
49
|
llm=llm{
|
13
50
|
utils.rb
|
14
51
|
parse.rb
|
52
|
+
tools.rb
|
53
|
+
chat.rb
|
54
|
+
|
15
55
|
backends=backends{
|
16
|
-
ollama.rb
|
17
56
|
openai.rb
|
57
|
+
responses.rb
|
58
|
+
ollama.rb
|
18
59
|
openwebui.rb
|
19
60
|
huggingface.rb
|
20
61
|
relay.rb
|
21
62
|
}
|
63
|
+
|
22
64
|
ask.rb
|
23
65
|
|
24
66
|
embed.rb
|
25
67
|
|
26
68
|
rag.rb
|
27
69
|
|
28
|
-
tools.rb
|
29
70
|
agent.rb
|
30
71
|
}
|
72
|
+
model=model{
|
73
|
+
util=util{
|
74
|
+
save.rb
|
75
|
+
run.rb
|
76
|
+
}
|
77
|
+
base.rb
|
78
|
+
|
79
|
+
python=python{
|
80
|
+
base.rb
|
81
|
+
torch.rb
|
82
|
+
torch=torch{
|
83
|
+
helpers.rb
|
84
|
+
dataloader.rb
|
85
|
+
introspection.rb
|
86
|
+
load_and_save.rb
|
87
|
+
}
|
88
|
+
huggingface.rb
|
89
|
+
huggingface=huggingface{
|
90
|
+
classification.rb
|
91
|
+
causal.rb
|
92
|
+
causal=causal{
|
93
|
+
next_token.rb
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
31
98
|
}
|
32
99
|
}
|
100
|
+
python=python filter="*"{
|
101
|
+
scout_ai=scout_ai{
|
102
|
+
__init__.py
|
103
|
+
language_model.py
|
104
|
+
util.py
|
105
|
+
huggingface=huggingface{
|
106
|
+
data.py
|
107
|
+
eval.py
|
108
|
+
model.py
|
109
|
+
train=train{
|
110
|
+
__init__.py
|
111
|
+
next_token.py
|
112
|
+
}
|
113
|
+
rlhf.py
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
33
118
|
test=test {
|
34
119
|
data=data filter="*"{
|
35
120
|
person=person{
|
@@ -51,11 +136,7 @@ scout-ai=/$PWD filter="*.rb *.rake Rakefile *.rdoc *.R *.sh *.js *.haml *.sass *
|
|
51
136
|
}
|
52
137
|
agent=agent{
|
53
138
|
ask
|
139
|
+
kb
|
54
140
|
}
|
55
141
|
}
|
56
|
-
questions=questions filter="*"{
|
57
|
-
coach
|
58
|
-
evaluator
|
59
|
-
templater
|
60
|
-
}
|
61
142
|
}
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0
|
data/bin/scout-ai
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
module LLM
|
2
|
+
class Agent
|
3
|
+
def start_chat
|
4
|
+
@start_chat ||= Chat.setup []
|
5
|
+
end
|
6
|
+
|
7
|
+
def start(chat=nil)
|
8
|
+
if chat
|
9
|
+
(@current_chat || start_chat).annotate chat unless Chat === chat
|
10
|
+
@current_chat = chat
|
11
|
+
else
|
12
|
+
@current_chat = start_chat.branch
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def current_chat
|
17
|
+
@current_chat ||= start
|
18
|
+
end
|
19
|
+
|
20
|
+
def method_missing(name,...)
|
21
|
+
current_chat.send(name, ...)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/scout/llm/agent.rb
CHANGED
@@ -2,13 +2,12 @@ require_relative 'ask'
|
|
2
2
|
|
3
3
|
module LLM
|
4
4
|
class Agent
|
5
|
-
attr_accessor :
|
6
|
-
def initialize(
|
7
|
-
@system = system
|
5
|
+
attr_accessor :workflow, :knowledge_base, :start_chat
|
6
|
+
def initialize(workflow: nil, knowledge_base: nil, start_chat: nil, **kwargs)
|
8
7
|
@workflow = workflow
|
9
8
|
@knowledge_base = knowledge_base
|
10
|
-
@model = model
|
11
9
|
@other_options = kwargs
|
10
|
+
@start_chat = start_chat
|
12
11
|
end
|
13
12
|
|
14
13
|
def format_message(message, prefix = "user")
|
@@ -19,17 +18,17 @@ module LLM
|
|
19
18
|
|
20
19
|
def system_prompt
|
21
20
|
system = @system
|
21
|
+
system = [] if system.nil?
|
22
22
|
system = [system] unless system.nil? || system.is_a?(Array)
|
23
|
+
system = [] if system.nil?
|
23
24
|
|
24
|
-
if @knowledge_base
|
25
|
+
if @knowledge_base and @knowledge_base.all_databases.any?
|
25
26
|
system << <<-EOF
|
26
27
|
You have access to the following databases associating entities:
|
27
28
|
EOF
|
28
29
|
|
29
30
|
knowledge_base.all_databases.each do |database|
|
30
|
-
system <<
|
31
|
-
* #{database}: #{knowledge_base.source(database)} => #{knowledge_base.target(database)}
|
32
|
-
EOF
|
31
|
+
system << knowledge_base.markdown(database)
|
33
32
|
end
|
34
33
|
end
|
35
34
|
|
@@ -45,21 +44,21 @@ You have access to the following databases associating entities:
|
|
45
44
|
end
|
46
45
|
|
47
46
|
# function: takes an array of messages and calls LLM.ask with them
|
48
|
-
def ask(messages, model = nil)
|
47
|
+
def ask(messages, model = nil, options = {})
|
49
48
|
messages = [messages] unless messages.is_a? Array
|
50
|
-
model ||= @model
|
49
|
+
model ||= @model if model
|
51
50
|
|
52
51
|
tools = []
|
53
52
|
tools += LLM.workflow_tools(workflow) if workflow
|
54
|
-
tools += LLM.knowledge_base_tool_definition(knowledge_base) if knowledge_base
|
53
|
+
tools += LLM.knowledge_base_tool_definition(knowledge_base) if knowledge_base and knowledge_base.all_databases.any?
|
55
54
|
|
56
|
-
LLM.ask prompt(messages), @other_options.merge(
|
55
|
+
LLM.ask prompt(messages), @other_options.merge(log_errors: true, tools: tools) do |name,parameters|
|
57
56
|
case name
|
58
57
|
when 'children'
|
59
58
|
parameters = IndiferentHash.setup(parameters)
|
60
59
|
database, entities = parameters.values_at "database", "entities"
|
61
60
|
Log.high "Finding #{entities} children in #{database}"
|
62
|
-
knowledge_base.children(database, entities)
|
61
|
+
knowledge_base.children(database, entities)
|
63
62
|
else
|
64
63
|
if workflow
|
65
64
|
begin
|
@@ -76,3 +75,4 @@ You have access to the following databases associating entities:
|
|
76
75
|
end
|
77
76
|
end
|
78
77
|
end
|
78
|
+
require_relative 'agent/chat'
|
data/lib/scout/llm/ask.rb
CHANGED
@@ -2,32 +2,42 @@ require 'scout'
|
|
2
2
|
require_relative 'backends/openai'
|
3
3
|
require_relative 'backends/ollama'
|
4
4
|
require_relative 'backends/openwebui'
|
5
|
+
require_relative 'backends/bedrock'
|
5
6
|
require_relative 'backends/relay'
|
7
|
+
require_relative 'backends/responses'
|
6
8
|
|
7
9
|
module LLM
|
8
10
|
def self.ask(question, options = {}, &block)
|
9
|
-
|
11
|
+
messages = LLM.chat(question)
|
12
|
+
options = IndiferentHash.add_defaults LLM.options(messages), options
|
10
13
|
|
11
|
-
endpoint
|
14
|
+
endpoint, persist = IndiferentHash.process_options options, :endpoint, :persist, persist: true
|
15
|
+
|
16
|
+
endpoint ||= Scout::Config.get :endpoint, :ask, :llm, env: 'ASK_ENDPOINT,LLM_ENDPOINT'
|
12
17
|
if endpoint && Scout.etc.AI[endpoint].exists?
|
13
18
|
options = IndiferentHash.add_defaults options, Scout.etc.AI[endpoint].yaml
|
14
19
|
end
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
Persist.persist(endpoint, :json, prefix: "LLM ask", other: options.merge(messages: messages), persist: persist) do
|
22
|
+
backend = IndiferentHash.process_options options, :backend
|
23
|
+
backend ||= Scout::Config.get :backend, :ask, :llm, env: 'ASK_BACKEND,LLM_BACKEND', default: :openai
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
case backend
|
26
|
+
when :openai, "openai"
|
27
|
+
LLM::OpenAI.ask(messages, options, &block)
|
28
|
+
when :responses, "responses"
|
29
|
+
LLM::Responses.ask(messages, options, &block)
|
30
|
+
when :ollama, "ollama"
|
31
|
+
LLM::OLlama.ask(messages, options, &block)
|
32
|
+
when :openwebui, "openwebui"
|
33
|
+
LLM::OpenWebUI.ask(messages, options, &block)
|
34
|
+
when :relay, "relay"
|
35
|
+
LLM::Relay.ask(messages, options, &block)
|
36
|
+
when :bedrock, "bedrock"
|
37
|
+
LLM::Bedrock.ask(messages, options, &block)
|
38
|
+
else
|
39
|
+
raise "Unknown backend: #{backend}"
|
40
|
+
end
|
31
41
|
end
|
32
42
|
end
|
33
43
|
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'scout'
|
2
|
+
require 'aws-sdk-bedrockruntime'
|
3
|
+
require_relative '../parse'
|
4
|
+
require_relative '../tools'
|
5
|
+
require_relative '../utils'
|
6
|
+
|
7
|
+
module LLM
|
8
|
+
module Bedrock
|
9
|
+
def self.client(region, access_key, secret_key)
|
10
|
+
|
11
|
+
credentials = Aws::Credentials.new(access_key, secret_key) if access_key and secret_key
|
12
|
+
options = {}
|
13
|
+
options[:region] = region if region
|
14
|
+
options[:credentials] = credentials if credentials
|
15
|
+
Aws::BedrockRuntime::Client.new(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.messages_to_prompt(messages)
|
19
|
+
system = []
|
20
|
+
user = []
|
21
|
+
messages.each do |info|
|
22
|
+
role, content = info.values_at :role, :content
|
23
|
+
if role.to_s == 'system'
|
24
|
+
system << content
|
25
|
+
else
|
26
|
+
user << content
|
27
|
+
end
|
28
|
+
end
|
29
|
+
[system*"\n", user*"\n"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.ask(question, options = {}, &block)
|
33
|
+
client, region, access_key, secret_key, type = IndiferentHash.process_options options, :client, :region, :access_key, :secret_key, :type
|
34
|
+
|
35
|
+
model_options = IndiferentHash.pull_keys options, :model
|
36
|
+
model = IndiferentHash.process_options model_options, :model
|
37
|
+
|
38
|
+
if client.nil?
|
39
|
+
region ||= Scout::Config.get(:region, :bedrock_ask, :ask, :bedrock, env: 'AWS_REGION')
|
40
|
+
access_key ||= LLM.get_url_config(:access_key, nil, :bedrock_ask, :ask, :bedrock, env: 'AWS_ACCESS_KEY_ID')
|
41
|
+
secret_key ||= LLM.get_url_config(:secret_key, nil, :bedrock_ask, :ask, :bedrock, env: 'AWS_SECRET_ACCESS_KEY')
|
42
|
+
client = self.client(region, access_key, secret_key)
|
43
|
+
end
|
44
|
+
|
45
|
+
model ||= Scout::Config.get(:model, :bedrock_ask, :ask, :bedrock, env: 'BEDROCK_MODEL_ID')
|
46
|
+
type ||= Scout::Config.get(:type, model, default: :messages)
|
47
|
+
|
48
|
+
role = IndiferentHash.process_options options, :role
|
49
|
+
messages = LLM.parse(question, role)
|
50
|
+
|
51
|
+
case type.to_sym
|
52
|
+
when :messages
|
53
|
+
body = model_options.merge({
|
54
|
+
system: messages.select{|m| m[:role] == 'system'}.collect{|m| m[:content]}*"\n",
|
55
|
+
messages: messages.select{|m| m[:role] == 'user'}
|
56
|
+
})
|
57
|
+
when :prompt
|
58
|
+
system, user = messages_to_prompt messages
|
59
|
+
body = model_options.merge({
|
60
|
+
prompt: user
|
61
|
+
})
|
62
|
+
else
|
63
|
+
raise "Unkown type #{type}"
|
64
|
+
end
|
65
|
+
|
66
|
+
Log.debug "Calling bedrock with model: #{model} parameters: #{Log.fingerprint body}"
|
67
|
+
|
68
|
+
response = client.invoke_model(
|
69
|
+
model_id: model,
|
70
|
+
content_type: 'application/json',
|
71
|
+
body: body.to_json
|
72
|
+
)
|
73
|
+
|
74
|
+
result = JSON.parse(response.body.string)
|
75
|
+
Log.debug "Response: #{Log.fingerprint result}"
|
76
|
+
message = result
|
77
|
+
tool_calls = message.dig('content').select{|m| m['tool_calls']}
|
78
|
+
|
79
|
+
while tool_calls && tool_calls.any?
|
80
|
+
messages << message
|
81
|
+
|
82
|
+
cpus = Scout::Config.get :cpus, :tool_calling, default: 3
|
83
|
+
tool_calls.each do |tool_call|
|
84
|
+
response_message = LLM.tool_response(tool_call, &block)
|
85
|
+
messages << response_message
|
86
|
+
end
|
87
|
+
|
88
|
+
body[:messages] = messages.compact
|
89
|
+
Log.debug "Calling bedrock with parameters: #{Log.fingerprint body}"
|
90
|
+
response = client.invoke_model(
|
91
|
+
model_id: model,
|
92
|
+
content_type: 'application/json',
|
93
|
+
body: body.to_json
|
94
|
+
)
|
95
|
+
result = JSON.parse(response.body.string)
|
96
|
+
Log.debug "Response: #{Log.fingerprint result}"
|
97
|
+
|
98
|
+
message = result
|
99
|
+
tool_calls = message.dig('content').select{|m| m['tool_calls']}
|
100
|
+
end
|
101
|
+
|
102
|
+
message.dig('content').collect{|m|
|
103
|
+
m['text']
|
104
|
+
} * "\n"
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.embed(text, options = {})
|
108
|
+
client, region, access_key, secret_key, model = IndiferentHash.process_options options, :client, :region, :access_key, :secret_key, :model
|
109
|
+
|
110
|
+
if client.nil?
|
111
|
+
region ||= Scout::Config.get(:region, :bedrock_embed, :embed, :bedrock, env: 'AWS_REGION')
|
112
|
+
access_key ||= LLM.get_url_config(:access_key, nil, :bedrock_embed, :embed, :bedrock, env: 'AWS_ACCESS_KEY_ID')
|
113
|
+
secret_key ||= LLM.get_url_config(:secret_key, nil, :bedrock_embed, :embed, :bedrock, env: 'AWS_SECRET_ACCESS_KEY')
|
114
|
+
client = self.client(region, access_key, secret_key)
|
115
|
+
end
|
116
|
+
|
117
|
+
model ||= Scout::Config.get(:model, :bedrock_embed, :embed, :bedrock, env: 'BEDROCK_EMBED_MODEL_ID', default: 'amazon.titan-embed-text-v1')
|
118
|
+
|
119
|
+
response = client.invoke_model(
|
120
|
+
model_id: model,
|
121
|
+
content_type: 'application/json',
|
122
|
+
body: { inputText: text }.to_json
|
123
|
+
)
|
124
|
+
|
125
|
+
result = JSON.parse(response.body.string)
|
126
|
+
result['embedding']
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -1,17 +1,18 @@
|
|
1
1
|
require_relative '../parse'
|
2
2
|
require_relative '../tools'
|
3
|
+
require_relative '../chat'
|
3
4
|
|
4
5
|
module LLM
|
5
6
|
module Huggingface
|
6
7
|
|
7
8
|
def self.model(model_options)
|
8
|
-
require '
|
9
|
-
require '
|
9
|
+
require 'scout/model/python/huggingface'
|
10
|
+
require 'scout/model/python/huggingface/causal'
|
10
11
|
|
11
12
|
model, task, checkpoint, dir = IndiferentHash.process_options model_options, :model, :task, :checkpoint, :dir
|
12
13
|
model ||= Scout::Config.get(:model, :huggingface, env: 'HUGGINGFACE_MODEL,HF_MODEL')
|
13
14
|
|
14
|
-
|
15
|
+
CausalModel.new model, dir, model_options
|
15
16
|
end
|
16
17
|
|
17
18
|
def self.ask(question, options = {}, &block)
|
@@ -20,7 +21,7 @@ module LLM
|
|
20
21
|
|
21
22
|
model = self.model model_options
|
22
23
|
|
23
|
-
messages = LLM.
|
24
|
+
messages = LLM.messages(question)
|
24
25
|
|
25
26
|
system = []
|
26
27
|
prompt = []
|
@@ -36,23 +37,7 @@ module LLM
|
|
36
37
|
parameters = options.merge(messages: messages)
|
37
38
|
Log.debug "Calling client with parameters: #{Log.fingerprint parameters}"
|
38
39
|
|
39
|
-
|
40
|
-
message = response[-1]
|
41
|
-
while message["role"] == "assistant" && message["tool_calls"]
|
42
|
-
messages << message
|
43
|
-
|
44
|
-
message["tool_calls"].each do |tool_call|
|
45
|
-
response_message = LLM.tool_response(tool_call, &block)
|
46
|
-
messages << response_message
|
47
|
-
end
|
48
|
-
|
49
|
-
parameters[:messages] = messages
|
50
|
-
Log.debug "Calling client with parameters: #{Log.fingerprint parameters}"
|
51
|
-
response = model.eval(parameters)
|
52
|
-
message = response[-1]
|
53
|
-
end
|
54
|
-
|
55
|
-
message["content"]
|
40
|
+
model.eval(messages)
|
56
41
|
end
|
57
42
|
|
58
43
|
def self.embed(text, options = {})
|
@@ -2,6 +2,7 @@ require 'ollama-ai'
|
|
2
2
|
require_relative '../parse'
|
3
3
|
require_relative '../tools'
|
4
4
|
require_relative '../utils'
|
5
|
+
require_relative '../chat'
|
5
6
|
|
6
7
|
module LLM
|
7
8
|
module OLlama
|
@@ -15,9 +16,34 @@ module LLM
|
|
15
16
|
)
|
16
17
|
end
|
17
18
|
|
19
|
+
|
20
|
+
def self.process_response(responses, &block)
|
21
|
+
responses.collect do |response|
|
22
|
+
Log.debug "Respose: #{Log.fingerprint response}"
|
23
|
+
|
24
|
+
message = response['message']
|
25
|
+
tool_calls = response.dig("tool_calls") ||
|
26
|
+
response.dig("message", "tool_calls")
|
27
|
+
|
28
|
+
if tool_calls && tool_calls.any?
|
29
|
+
LLM.call_tools tool_calls, &block
|
30
|
+
else
|
31
|
+
[message]
|
32
|
+
end
|
33
|
+
end.flatten
|
34
|
+
end
|
35
|
+
|
18
36
|
def self.ask(question, options = {}, &block)
|
37
|
+
original_options = options.dup
|
19
38
|
|
20
|
-
|
39
|
+
messages = LLM.chat(question)
|
40
|
+
options = options.merge LLM.options messages
|
41
|
+
tools = LLM.tools messages
|
42
|
+
associations = LLM.associations messages
|
43
|
+
|
44
|
+
client, url, key, model, return_messages, format, stream = IndiferentHash.process_options options,
|
45
|
+
:client, :url, :key, :model, :return_messages, :format, :stream,
|
46
|
+
stream: false
|
21
47
|
|
22
48
|
if client.nil?
|
23
49
|
url ||= Scout::Config.get(:url, :ollama_ask, :ask, :ollama, env: 'OLLAMA_URL', default: "http://localhost:11434")
|
@@ -30,51 +56,58 @@ module LLM
|
|
30
56
|
model ||= LLM.get_url_config(:model, url, :ollama_ask, :ask, :ollama, env: 'OLLAMA_MODEL', default: "mistral")
|
31
57
|
end
|
32
58
|
|
33
|
-
mode = IndiferentHash.process_options options, :mode
|
34
59
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
60
|
+
case format.to_sym
|
61
|
+
when :json, :json_object
|
62
|
+
options[:response_format] = {type: 'json_object'}
|
63
|
+
else
|
64
|
+
options[:response_format] = {type: format}
|
65
|
+
end if format
|
66
|
+
|
67
|
+
parameters = options.merge(model: model)
|
68
|
+
|
69
|
+
if tools.any? || associations.any?
|
70
|
+
parameters[:tools] = []
|
71
|
+
parameters[:tools] += tools.values.collect{|a| a.last } if tools
|
72
|
+
parameters[:tools] += associations.values.collect{|a| a.last } if associations
|
73
|
+
if not block_given?
|
74
|
+
block = Proc.new do |name,parameters|
|
75
|
+
IndiferentHash.setup parameters
|
76
|
+
if tools[name]
|
77
|
+
workflow = tools[name].first
|
78
|
+
jobname = parameters.delete :jobname
|
79
|
+
workflow.job(name, jobname, parameters).run
|
80
|
+
else
|
81
|
+
kb = associations[name].first
|
82
|
+
entities, reverse = IndiferentHash.process_options parameters, :entities, :reverse
|
83
|
+
if reverse
|
84
|
+
kb.parents(name, entities)
|
85
|
+
else
|
86
|
+
kb.children(name, entities)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
45
90
|
end
|
46
91
|
end
|
47
92
|
|
48
|
-
|
49
|
-
when :chat, 'chat'
|
50
|
-
parameters = options.merge(model: model, messages: messages)
|
51
|
-
Log.debug "Calling client with parameters: #{Log.fingerprint parameters}"
|
93
|
+
Log.low "Calling client with parameters #{Log.fingerprint parameters}\n#{LLM.print messages}"
|
52
94
|
|
53
|
-
|
54
|
-
response.collect do |choice|
|
55
|
-
message=choice['message']
|
56
|
-
while message["role"] == "assistant" && message["tool_calls"]
|
57
|
-
messages << message
|
95
|
+
parameters[:messages] = LLM.tools_to_ollama messages
|
58
96
|
|
59
|
-
|
60
|
-
response_message = LLM.tool_response(tool_call, &block)
|
61
|
-
messages << response_message
|
62
|
-
end
|
97
|
+
parameters[:stream] = stream
|
63
98
|
|
64
|
-
|
65
|
-
Log.debug "Calling client with parameters: #{Log.fingerprint parameters}"
|
66
|
-
response = client.chat(parameters)
|
99
|
+
response = self.process_response client.chat(parameters), &block
|
67
100
|
|
68
|
-
|
69
|
-
|
101
|
+
res = if response.last[:role] == 'function_call_output'
|
102
|
+
response + self.ask(messages + response, original_options.except(:tool_choice).merge(return_messages: true, tools: parameters[:tools]), &block)
|
103
|
+
else
|
104
|
+
response
|
105
|
+
end
|
70
106
|
|
71
|
-
|
72
|
-
|
107
|
+
if return_messages
|
108
|
+
res
|
73
109
|
else
|
74
|
-
|
75
|
-
Log.debug "Calling client with parameters: #{Log.fingerprint parameters}"
|
76
|
-
response = client.generate(parameters)
|
77
|
-
response.collect{|e| e['response']} * ""
|
110
|
+
res.last['content']
|
78
111
|
end
|
79
112
|
end
|
80
113
|
|