scout-ai 0.2.0 → 1.0.1
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 +155 -9
- data/README.md +296 -0
- data/Rakefile +3 -0
- data/VERSION +1 -1
- data/bin/scout-ai +2 -0
- data/doc/Agent.md +279 -0
- data/doc/Chat.md +258 -0
- data/doc/LLM.md +446 -0
- data/doc/Model.md +513 -0
- data/doc/RAG.md +129 -0
- data/lib/scout/llm/agent/chat.rb +74 -0
- data/lib/scout/llm/agent/delegate.rb +39 -0
- data/lib/scout/llm/agent/iterate.rb +44 -0
- data/lib/scout/llm/agent.rb +51 -30
- data/lib/scout/llm/ask.rb +63 -21
- data/lib/scout/llm/backends/anthropic.rb +147 -0
- 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 +62 -35
- data/lib/scout/llm/backends/openai.rb +77 -33
- 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 +320 -0
- data/lib/scout/llm/chat.rb +703 -0
- data/lib/scout/llm/embed.rb +4 -4
- data/lib/scout/llm/mcp.rb +28 -0
- data/lib/scout/llm/parse.rb +71 -13
- data/lib/scout/llm/rag.rb +9 -0
- data/lib/scout/llm/tools/call.rb +66 -0
- data/lib/scout/llm/tools/knowledge_base.rb +158 -0
- data/lib/scout/llm/tools/mcp.rb +59 -0
- data/lib/scout/llm/tools/workflow.rb +69 -0
- data/lib/scout/llm/tools.rb +112 -76
- 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 +4 -1
- data/python/scout_ai/__init__.py +35 -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/next_token.py +315 -0
- data/python/scout_ai/util.py +32 -0
- data/scout-ai.gemspec +143 -0
- data/scout_commands/agent/ask +89 -14
- data/scout_commands/agent/kb +15 -0
- data/scout_commands/documenter +148 -0
- data/scout_commands/llm/ask +71 -12
- data/scout_commands/llm/process +4 -2
- data/scout_commands/llm/server +319 -0
- data/share/server/chat.html +138 -0
- data/share/server/chat.js +468 -0
- data/test/data/cat.jpg +0 -0
- data/test/scout/llm/agent/test_chat.rb +14 -0
- data/test/scout/llm/backends/test_anthropic.rb +134 -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 +134 -10
- data/test/scout/llm/backends/test_responses.rb +239 -0
- data/test/scout/llm/test_agent.rb +0 -70
- data/test/scout/llm/test_ask.rb +4 -1
- data/test/scout/llm/test_chat.rb +256 -0
- data/test/scout/llm/test_mcp.rb +29 -0
- data/test/scout/llm/test_parse.rb +81 -2
- data/test/scout/llm/tools/test_call.rb +0 -0
- data/test/scout/llm/tools/test_knowledge_base.rb +22 -0
- data/test/scout/llm/tools/test_mcp.rb +11 -0
- data/test/scout/llm/tools/test_workflow.rb +39 -0
- 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 +113 -7
- data/README.rdoc +0 -18
- data/questions/coach +0 -2
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
|
3
|
+
|
|
4
|
+
class TestLLMBedrock < Test::Unit::TestCase
|
|
5
|
+
def _test_ask
|
|
6
|
+
prompt =<<-EOF
|
|
7
|
+
say hi
|
|
8
|
+
EOF
|
|
9
|
+
ppp LLM::Bedrock.ask prompt, model: "anthropic.claude-3-sonnet-20240229-v1:0", model_max_tokens: 100, model_anthropic_version: 'bedrock-2023-05-31'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _test_embeddings
|
|
14
|
+
Log.severity = 0
|
|
15
|
+
text =<<-EOF
|
|
16
|
+
Some text
|
|
17
|
+
EOF
|
|
18
|
+
emb = LLM::Bedrock.embed text, log_errors: true
|
|
19
|
+
assert(Float === emb.first)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_tool
|
|
23
|
+
prompt =<<-EOF
|
|
24
|
+
What is the weather in London. Should I take my umbrella? Use the provided tool
|
|
25
|
+
EOF
|
|
26
|
+
|
|
27
|
+
tools = [
|
|
28
|
+
{
|
|
29
|
+
"type": "function",
|
|
30
|
+
"function": {
|
|
31
|
+
"name": "get_weather",
|
|
32
|
+
"description": "Get the current temperature and raining conditions for a specific location",
|
|
33
|
+
"parameters": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"properties": {
|
|
36
|
+
"location": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "The city and state, e.g., San Francisco, CA"
|
|
39
|
+
},
|
|
40
|
+
"unit": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"enum": ["Celsius", "Fahrenheit"],
|
|
43
|
+
"description": "The temperature unit to use. Infer this from the user's location."
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"required": ["location", "unit"]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
sss 0
|
|
53
|
+
response = LLM::Bedrock.ask prompt, tool_choice: 'required', tools: tools, model: "anthropic.claude-3-sonnet-20240229-v1:0", model_max_tokens: 100, model_anthropic_version: 'bedrock-2023-05-31' do |name,arguments|
|
|
54
|
+
"It's 15 degrees and raining."
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
ppp response
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
@@ -13,7 +13,7 @@ user: write a script that sorts files in a directory
|
|
|
13
13
|
ppp LLM::Huggingface.ask prompt, model: 'HuggingFaceTB/SmolLM2-135M-Instruct'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def
|
|
16
|
+
def _test_embeddings
|
|
17
17
|
Log.severity = 0
|
|
18
18
|
text =<<-EOF
|
|
19
19
|
Some text
|
|
@@ -22,7 +22,7 @@ Some text
|
|
|
22
22
|
assert(Float === emb.first)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def
|
|
25
|
+
def _test_embedding_array
|
|
26
26
|
Log.severity = 0
|
|
27
27
|
text =<<-EOF
|
|
28
28
|
Some text
|
|
@@ -31,7 +31,7 @@ Some text
|
|
|
31
31
|
assert(Float === emb.first.first)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
def
|
|
34
|
+
def _test_tool
|
|
35
35
|
prompt =<<-EOF
|
|
36
36
|
What is the weather in London. Should I take an umbrella?
|
|
37
37
|
EOF
|
|
@@ -13,22 +13,42 @@ user: write a script that sorts files in a directory
|
|
|
13
13
|
ppp LLM::OLlama.ask prompt, model: 'mistral', mode: 'chat'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def
|
|
16
|
+
def test_tool_call_output
|
|
17
17
|
Log.severity = 0
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
prompt =<<-EOF
|
|
19
|
+
function_call:
|
|
20
|
+
|
|
21
|
+
{"type":"function","function":{"name":"Baking-bake_muffin_tray","arguments":{}},"id":"Baking_bake_muffin_tray_Default"}
|
|
22
|
+
|
|
23
|
+
function_call_output:
|
|
24
|
+
|
|
25
|
+
{"id":"Baking_bake_muffin_tray_Default","content":"Baking batter (Mixing base (Whisking eggs from share/pantry/eggs) with mixer (share/pantry/flour))"}
|
|
26
|
+
|
|
27
|
+
user:
|
|
28
|
+
|
|
29
|
+
How do you bake muffins, according to the tool I provided you. Don't
|
|
30
|
+
tell me the recipe you already know, use the tool call output. Let me
|
|
31
|
+
know if you didn't get it.
|
|
20
32
|
EOF
|
|
21
|
-
|
|
22
|
-
assert(Float === emb.first)
|
|
33
|
+
ppp LLM::OLlama.ask prompt, model: 'mistral', mode: 'chat'
|
|
23
34
|
end
|
|
24
35
|
|
|
25
|
-
def
|
|
36
|
+
def test_tool_call_output_weather
|
|
26
37
|
Log.severity = 0
|
|
27
|
-
|
|
28
|
-
|
|
38
|
+
prompt =<<-EOF
|
|
39
|
+
function_call:
|
|
40
|
+
|
|
41
|
+
{"name":"get_current_temperature", "arguments":{"location":"London","unit":"Celsius"},"id":"tNTnsQq2s6jGh0npOh43AwDD"}
|
|
42
|
+
|
|
43
|
+
function_call_output:
|
|
44
|
+
|
|
45
|
+
{"id":"tNTnsQq2s6jGh0npOh43AwDD", "content":"It's 15 degrees and raining."}
|
|
46
|
+
|
|
47
|
+
user:
|
|
48
|
+
|
|
49
|
+
should i take an umbrella?
|
|
29
50
|
EOF
|
|
30
|
-
|
|
31
|
-
assert(Float === emb.first.first)
|
|
51
|
+
ppp LLM::OLlama.ask prompt, model: 'mistral'
|
|
32
52
|
end
|
|
33
53
|
|
|
34
54
|
def test_tool
|
|
@@ -68,5 +88,23 @@ What is the weather in London. Should I take an umbrella?
|
|
|
68
88
|
|
|
69
89
|
ppp respose
|
|
70
90
|
end
|
|
91
|
+
|
|
92
|
+
def test_embeddings
|
|
93
|
+
Log.severity = 0
|
|
94
|
+
text =<<-EOF
|
|
95
|
+
Some text
|
|
96
|
+
EOF
|
|
97
|
+
emb = LLM::OLlama.embed text, model: 'mistral'
|
|
98
|
+
assert(Float === emb.first)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def test_embedding_array
|
|
102
|
+
Log.severity = 0
|
|
103
|
+
text =<<-EOF
|
|
104
|
+
Some text
|
|
105
|
+
EOF
|
|
106
|
+
emb = LLM::OLlama.embed [text], model: 'mistral'
|
|
107
|
+
assert(Float === emb.first.first)
|
|
108
|
+
end
|
|
71
109
|
end
|
|
72
110
|
|
|
@@ -11,24 +11,134 @@ user: write a script that sorts files in a directory
|
|
|
11
11
|
ppp LLM::OpenAI.ask prompt
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def
|
|
14
|
+
def __test_embeddings
|
|
15
|
+
Log.severity = 0
|
|
16
|
+
text =<<-EOF
|
|
17
|
+
Some text
|
|
18
|
+
EOF
|
|
19
|
+
emb = LLM::OpenAI.embed text, log_errors: true, model: 'embedding-model'
|
|
20
|
+
|
|
21
|
+
assert(Float === emb.first)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_tool_call_output
|
|
25
|
+
Log.severity = 0
|
|
15
26
|
prompt =<<-EOF
|
|
16
|
-
|
|
27
|
+
function_call:
|
|
28
|
+
|
|
29
|
+
{"type":"function","function":{"name":"Baking-bake_muffin_tray","arguments":"{}"},"id":"Baking_bake_muffin_tray_Default"}
|
|
30
|
+
|
|
31
|
+
function_call_output:
|
|
32
|
+
|
|
33
|
+
{"id":"Baking_bake_muffin_tray_Default","role":"tool","content":"Baking batter (Mixing base (Whisking eggs from share/pantry/eggs) with mixer (share/pantry/flour))"}
|
|
34
|
+
|
|
35
|
+
user:
|
|
36
|
+
|
|
37
|
+
How do you bake muffins, according to the tool I provided you. Don't
|
|
38
|
+
tell me the recipe you already know, use the tool call output. Let me
|
|
39
|
+
know if you didn't get it.
|
|
17
40
|
EOF
|
|
18
|
-
|
|
41
|
+
ppp LLM::OpenAI.ask prompt, model: 'gpt-4.1-nano'
|
|
19
42
|
end
|
|
20
43
|
|
|
21
|
-
def
|
|
44
|
+
def test_tool_call_output_2
|
|
22
45
|
Log.severity = 0
|
|
23
|
-
|
|
24
|
-
|
|
46
|
+
prompt =<<-EOF
|
|
47
|
+
function_call:
|
|
48
|
+
|
|
49
|
+
{"name":"get_current_temperature", "arguments":{"location":"London","unit":"Celsius"},"id":"tNTnsQq2s6jGh0npOh43AwDD"}
|
|
50
|
+
|
|
51
|
+
function_call_output:
|
|
52
|
+
|
|
53
|
+
{"id":"tNTnsQq2s6jGh0npOh43AwDD", "content":"It's 15 degrees and raining."}
|
|
54
|
+
|
|
55
|
+
user:
|
|
56
|
+
|
|
57
|
+
should i take an umbrella?
|
|
25
58
|
EOF
|
|
26
|
-
|
|
27
|
-
|
|
59
|
+
ppp LLM::OpenAI.ask prompt, model: 'gpt-4.1-nano'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def test_tool_call_output_features
|
|
63
|
+
Log.severity = 0
|
|
64
|
+
prompt =<<-EOF
|
|
65
|
+
function_call:
|
|
66
|
+
|
|
67
|
+
{"name":"Baking-bake_muffin_tray","arguments":{},"id":"Baking_bake_muffin_tray_Default"}
|
|
68
|
+
|
|
69
|
+
function_call_output:
|
|
70
|
+
|
|
71
|
+
{"id":"Baking_bake_muffin_tray_Default","content":"Baking batter (Mixing base (Whisking eggs from share/pantry/eggs) with mixer (share/pantry/flour))"}
|
|
72
|
+
|
|
73
|
+
user:
|
|
74
|
+
|
|
75
|
+
How do you bake muffins, according to the tool I provided you. Don't
|
|
76
|
+
tell me the recipe you already know, use the tool call output. Let me
|
|
77
|
+
know if you didn't get it.
|
|
78
|
+
EOF
|
|
79
|
+
ppp LLM::OpenAI.ask prompt, model: 'gpt-4.1-nano'
|
|
28
80
|
end
|
|
29
81
|
|
|
30
|
-
def
|
|
82
|
+
def test_tool_call_output_weather
|
|
83
|
+
Log.severity = 0
|
|
31
84
|
prompt =<<-EOF
|
|
85
|
+
function_call:
|
|
86
|
+
|
|
87
|
+
{"name":"get_current_temperature", "arguments":{"location":"London","unit":"Celsius"},"id":"tNTnsQq2s6jGh0npOh43AwDD"}
|
|
88
|
+
|
|
89
|
+
function_call_output:
|
|
90
|
+
|
|
91
|
+
{"id":"tNTnsQq2s6jGh0npOh43AwDD", "content":"It's 15 degrees and raining."}
|
|
92
|
+
|
|
93
|
+
user:
|
|
94
|
+
|
|
95
|
+
should i take an umbrella?
|
|
96
|
+
EOF
|
|
97
|
+
ppp LLM::OpenAI.ask prompt, model: 'gpt-4.1-nano'
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_tool_gpt5
|
|
102
|
+
prompt =<<-EOF
|
|
103
|
+
user:
|
|
104
|
+
What is the weather in London. Should I take my umbrella?
|
|
105
|
+
EOF
|
|
106
|
+
|
|
107
|
+
tools = [
|
|
108
|
+
{
|
|
109
|
+
"type": "function",
|
|
110
|
+
"function": {
|
|
111
|
+
"name": "get_current_temperature",
|
|
112
|
+
"description": "Get the current temperature and raining conditions for a specific location",
|
|
113
|
+
"parameters": {
|
|
114
|
+
"type": "object",
|
|
115
|
+
"properties": {
|
|
116
|
+
"location": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"description": "The city and state, e.g., San Francisco, CA"
|
|
119
|
+
},
|
|
120
|
+
"unit": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"enum": ["Celsius", "Fahrenheit"],
|
|
123
|
+
"description": "The temperature unit to use. Infer this from the user's location."
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"required": ["location", "unit"]
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
respose = LLM::OpenAI.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-5", log_errors: true do |name,arguments|
|
|
133
|
+
"It's 15 degrees and raining."
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
ppp respose
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def test_tool
|
|
140
|
+
prompt =<<-EOF
|
|
141
|
+
user:
|
|
32
142
|
What is the weather in London. Should I take my umbrella?
|
|
33
143
|
EOF
|
|
34
144
|
|
|
@@ -58,11 +168,25 @@ What is the weather in London. Should I take my umbrella?
|
|
|
58
168
|
]
|
|
59
169
|
|
|
60
170
|
sss 0
|
|
61
|
-
respose = LLM::OpenAI.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-
|
|
171
|
+
respose = LLM::OpenAI.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-4.1-mini", log_errors: true do |name,arguments|
|
|
62
172
|
"It's 15 degrees and raining."
|
|
63
173
|
end
|
|
64
174
|
|
|
65
175
|
ppp respose
|
|
66
176
|
end
|
|
177
|
+
|
|
178
|
+
def test_json_output
|
|
179
|
+
prompt =<<-EOF
|
|
180
|
+
system:
|
|
181
|
+
|
|
182
|
+
Respond in json format with a hash of strings as keys and string arrays as values, at most three in length
|
|
183
|
+
|
|
184
|
+
user:
|
|
185
|
+
|
|
186
|
+
What other movies have the protagonists of the original gost busters played on, just the top.
|
|
187
|
+
EOF
|
|
188
|
+
sss 0
|
|
189
|
+
ppp LLM::OpenAI.ask prompt, format: :json
|
|
190
|
+
end
|
|
67
191
|
end
|
|
68
192
|
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
|
3
|
+
|
|
4
|
+
class TestLLMResponses < Test::Unit::TestCase
|
|
5
|
+
def test_ask
|
|
6
|
+
prompt =<<-EOF
|
|
7
|
+
system: you are a coding helper that only write code and comments without formatting so that it can work directly, avoid the initial and end commas ```.
|
|
8
|
+
user: write a script that sorts files in a directory
|
|
9
|
+
EOF
|
|
10
|
+
sss 0
|
|
11
|
+
ppp LLM::Responses.ask prompt, model: 'gpt-4.1-nano'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def __test_embeddings
|
|
15
|
+
Log.severity = 0
|
|
16
|
+
text =<<-EOF
|
|
17
|
+
Some text
|
|
18
|
+
EOF
|
|
19
|
+
emb = LLM::Responses.embed text, log_errors: true
|
|
20
|
+
assert(Float === emb.first)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_tool_call_output_weather
|
|
24
|
+
Log.severity = 0
|
|
25
|
+
prompt =<<-EOF
|
|
26
|
+
function_call:
|
|
27
|
+
|
|
28
|
+
{"name":"get_current_temperature", "arguments":{"location":"London","unit":"Celsius"},"id":"tNTnsQq2s6jGh0npOh43AwDD"}
|
|
29
|
+
|
|
30
|
+
function_call_output:
|
|
31
|
+
|
|
32
|
+
{"id":"tNTnsQq2s6jGh0npOh43AwDD", "content":"It's 15 degrees and raining."}
|
|
33
|
+
|
|
34
|
+
user:
|
|
35
|
+
|
|
36
|
+
should i take an umbrella?
|
|
37
|
+
EOF
|
|
38
|
+
ppp LLM::Responses.ask prompt, model: 'gpt-4.1-nano'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_tool
|
|
42
|
+
prompt =<<-EOF
|
|
43
|
+
user:
|
|
44
|
+
What is the weather in London. Should I take my umbrella?
|
|
45
|
+
EOF
|
|
46
|
+
|
|
47
|
+
tools = [
|
|
48
|
+
{
|
|
49
|
+
"type": "function",
|
|
50
|
+
"name": "get_current_temperature",
|
|
51
|
+
"description": "Get the current temperature and raining conditions for a specific location",
|
|
52
|
+
"parameters": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"properties": {
|
|
55
|
+
"location": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"description": "The city and state, e.g., San Francisco, CA"
|
|
58
|
+
},
|
|
59
|
+
"unit": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"enum": ["Celsius", "Fahrenheit"],
|
|
62
|
+
"description": "The temperature unit to use. Infer this from the user's location."
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"required": ["location", "unit"]
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
sss 1
|
|
71
|
+
respose = LLM::Responses.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-4.1-nano", log_errors: true do |name,arguments|
|
|
72
|
+
"It's 15 degrees and raining."
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
ppp respose
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_news
|
|
79
|
+
prompt =<<-EOF
|
|
80
|
+
websearch: true
|
|
81
|
+
|
|
82
|
+
user:
|
|
83
|
+
|
|
84
|
+
What was the top new in the US today?
|
|
85
|
+
EOF
|
|
86
|
+
ppp LLM::Responses.ask prompt
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def test_image
|
|
90
|
+
prompt =<<-EOF
|
|
91
|
+
image: #{datafile_test 'cat.jpg'}
|
|
92
|
+
|
|
93
|
+
user:
|
|
94
|
+
|
|
95
|
+
What animal is represented in the image?
|
|
96
|
+
EOF
|
|
97
|
+
sss 0
|
|
98
|
+
ppp LLM::Responses.ask prompt
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def test_json_output
|
|
102
|
+
prompt =<<-EOF
|
|
103
|
+
system:
|
|
104
|
+
|
|
105
|
+
Respond in json format with a hash of strings as keys and string arrays as values, at most three in length
|
|
106
|
+
|
|
107
|
+
user:
|
|
108
|
+
|
|
109
|
+
What other movies have the protagonists of the original gost busters played on, just the top.
|
|
110
|
+
EOF
|
|
111
|
+
sss 0
|
|
112
|
+
ppp LLM::Responses.ask prompt, format: :json
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_json_format
|
|
116
|
+
prompt =<<-EOF
|
|
117
|
+
user:
|
|
118
|
+
|
|
119
|
+
What other movies have the protagonists of the original gost busters played on.
|
|
120
|
+
Name each actor and the top movie they took part of
|
|
121
|
+
EOF
|
|
122
|
+
sss 0
|
|
123
|
+
|
|
124
|
+
format = {
|
|
125
|
+
name: 'actors_and_top_movies',
|
|
126
|
+
type: 'object',
|
|
127
|
+
properties: {},
|
|
128
|
+
additionalProperties: {type: :string}
|
|
129
|
+
}
|
|
130
|
+
ppp LLM::Responses.ask prompt, format: format
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def test_json_format_list
|
|
134
|
+
prompt =<<-EOF
|
|
135
|
+
user:
|
|
136
|
+
|
|
137
|
+
What other movies have the protagonists of the original gost busters played on.
|
|
138
|
+
Name each actor as keys and the top 3 movies they took part of as values
|
|
139
|
+
EOF
|
|
140
|
+
sss 0
|
|
141
|
+
|
|
142
|
+
format = {
|
|
143
|
+
name: 'actors_and_top_movies',
|
|
144
|
+
type: 'object',
|
|
145
|
+
properties: {},
|
|
146
|
+
additionalProperties: {type: :array, items: {type: :string}}
|
|
147
|
+
}
|
|
148
|
+
ppp LLM::Responses.ask prompt, format: format
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def test_json_format_actor_list
|
|
152
|
+
prompt =<<-EOF
|
|
153
|
+
user:
|
|
154
|
+
|
|
155
|
+
What other movies have the protagonists of the original gost busters played on.
|
|
156
|
+
Name each actor as keys and the top 3 movies they took part of as values
|
|
157
|
+
EOF
|
|
158
|
+
sss 0
|
|
159
|
+
|
|
160
|
+
format = {
|
|
161
|
+
name: 'actors_and_top_movies',
|
|
162
|
+
type: 'object',
|
|
163
|
+
properties: {},
|
|
164
|
+
additionalProperties: false,
|
|
165
|
+
items: {
|
|
166
|
+
type: 'object',
|
|
167
|
+
properties: {
|
|
168
|
+
name: {type: :string, description: 'actor name'},
|
|
169
|
+
movies: {type: :array, description: 'list of top 3 movies', items: {type: :string, description: 'movie title plus year in parenthesis'} },
|
|
170
|
+
additionalProperties: false
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
schema = {
|
|
176
|
+
"type": "object",
|
|
177
|
+
"properties": {
|
|
178
|
+
"people": {
|
|
179
|
+
"type": "array",
|
|
180
|
+
"items": {
|
|
181
|
+
"type": "object",
|
|
182
|
+
"properties": {
|
|
183
|
+
"name": { "type": "string" },
|
|
184
|
+
"movies": {
|
|
185
|
+
"type": "array",
|
|
186
|
+
"items": { "type": "string" },
|
|
187
|
+
"minItems": 3,
|
|
188
|
+
"maxItems": 3
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"required": ["name", "movies"],
|
|
192
|
+
additionalProperties: false
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
additionalProperties: false,
|
|
197
|
+
"required": ["people"]
|
|
198
|
+
}
|
|
199
|
+
ppp LLM::Responses.ask prompt, format: schema
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def test_tool_gpt5
|
|
203
|
+
prompt =<<-EOF
|
|
204
|
+
user:
|
|
205
|
+
What is the weather in London. Should I take my umbrella?
|
|
206
|
+
EOF
|
|
207
|
+
|
|
208
|
+
tools = [
|
|
209
|
+
{
|
|
210
|
+
"type": "function",
|
|
211
|
+
"name": "get_current_temperature",
|
|
212
|
+
"description": "Get the current temperature and raining conditions for a specific location",
|
|
213
|
+
"parameters": {
|
|
214
|
+
"type": "object",
|
|
215
|
+
"properties": {
|
|
216
|
+
"location": {
|
|
217
|
+
"type": "string",
|
|
218
|
+
"description": "The city and state, e.g., San Francisco, CA"
|
|
219
|
+
},
|
|
220
|
+
"unit": {
|
|
221
|
+
"type": "string",
|
|
222
|
+
"enum": ["Celsius", "Fahrenheit"],
|
|
223
|
+
"description": "The temperature unit to use. Infer this from the user's location."
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
"required": ["location", "unit"]
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
]
|
|
230
|
+
|
|
231
|
+
sss 0
|
|
232
|
+
respose = LLM::Responses.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-5", log_errors: true do |name,arguments|
|
|
233
|
+
"It's 15 degrees and raining."
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
ppp respose
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
@@ -39,76 +39,6 @@ class TestLLMAgent < Test::Unit::TestCase
|
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
def test_workflow
|
|
43
|
-
m = Module.new do
|
|
44
|
-
extend Workflow
|
|
45
|
-
self.name = "Registration"
|
|
46
|
-
|
|
47
|
-
desc "Register a person"
|
|
48
|
-
input :name, :string, "Last, first name"
|
|
49
|
-
input :age, :integer, "Age"
|
|
50
|
-
input :gender, :select, "Gender", nil, :select_options => %w(male female)
|
|
51
|
-
task :person => :yaml do
|
|
52
|
-
iii inputs.to_hash
|
|
53
|
-
inputs.to_hash
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
sss 0
|
|
58
|
-
#ppp LLM.workflow_ask(m, "Register Eduard Smith, a 25 yo male", model: "Meta-Llama-3.3-70B-Instruct")
|
|
59
|
-
ppp LLM.workflow_ask(m, "Register Eduard Smith, a 25 yo male, using a tool call to the tool provided", backend: 'ollama', model: "llama3")
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def _test_openai
|
|
63
|
-
TmpFile.with_dir do |dir|
|
|
64
|
-
kb = KnowledgeBase.new dir
|
|
65
|
-
kb.format = {"Person" => "Alias"}
|
|
66
|
-
kb.register :brothers, datafile_test(:person).brothers, undirected: true
|
|
67
|
-
kb.register :marriages, datafile_test(:person).marriages, undirected: true, source: "=>Alias", target: "=>Alias"
|
|
68
|
-
kb.register :parents, datafile_test(:person).parents
|
|
69
|
-
|
|
70
|
-
sss 3
|
|
71
|
-
agent = LLM::Agent.new knowledge_base: kb, model: 'gpt-4o'
|
|
72
|
-
|
|
73
|
-
agent.system = ""
|
|
74
|
-
|
|
75
|
-
ppp agent.ask "Who is Miguel's brother-in-law"
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def _test_argonne
|
|
80
|
-
TmpFile.with_dir do |dir|
|
|
81
|
-
kb = KnowledgeBase.new dir
|
|
82
|
-
kb.format = {"Person" => "Alias"}
|
|
83
|
-
kb.register :brothers, datafile_test(:person).brothers, undirected: true
|
|
84
|
-
kb.register :marriages, datafile_test(:person).marriages, undirected: true, source: "=>Alias", target: "=>Alias"
|
|
85
|
-
kb.register :parents, datafile_test(:person).parents
|
|
86
|
-
|
|
87
|
-
agent.system = ""
|
|
88
|
-
|
|
89
|
-
ppp agent.ask "Who is Miguel's brother-in-law"
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def _test_nvidia
|
|
94
|
-
TmpFile.with_dir do |dir|
|
|
95
|
-
kb = KnowledgeBase.new dir
|
|
96
|
-
kb.format = {"Person" => "Alias"}
|
|
97
|
-
kb.register :brothers, datafile_test(:person).brothers, undirected: true
|
|
98
|
-
kb.register :marriages, datafile_test(:person).marriages, undirected: true, source: "=>Alias", target: "=>Alias"
|
|
99
|
-
kb.register :parents, datafile_test(:person).parents
|
|
100
|
-
|
|
101
|
-
sss 0
|
|
102
|
-
|
|
103
|
-
ppp LLM::OpenAI.ask "Say Hi", url: "https://integrate.api.nvidia.com/v1", model: "deepseek-ai/deepseek-r1"
|
|
104
|
-
exit
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
agent.system = ""
|
|
108
|
-
|
|
109
|
-
ppp agent.ask "Who is Miguel's brother-in-law. Make use of the tools using tool_calls"
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
42
|
|
|
113
43
|
end
|
|
114
44
|
|
data/test/scout/llm/test_ask.rb
CHANGED
|
@@ -12,6 +12,7 @@ system: you are a coding helper that only write code and comments without format
|
|
|
12
12
|
user: write a script that sorts files in a directory
|
|
13
13
|
EOF
|
|
14
14
|
ppp LLM.ask prompt
|
|
15
|
+
ppp LLM.ask prompt
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def _test_workflow_ask
|
|
@@ -37,9 +38,11 @@ user: write a script that sorts files in a directory
|
|
|
37
38
|
"1 minute"
|
|
38
39
|
end
|
|
39
40
|
end
|
|
41
|
+
export :recipe_steps, :step_time
|
|
40
42
|
end
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
sss 0
|
|
45
|
+
ppp LLM.workflow_ask(m, "How much time does it take to prepare a 'vanilla' cake recipe, use the tools provided to find out")
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
def test_knowledbase
|