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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +91 -10
  3. data/Rakefile +1 -0
  4. data/VERSION +1 -1
  5. data/bin/scout-ai +2 -0
  6. data/lib/scout/llm/agent/chat.rb +24 -0
  7. data/lib/scout/llm/agent.rb +13 -13
  8. data/lib/scout/llm/ask.rb +26 -16
  9. data/lib/scout/llm/backends/bedrock.rb +129 -0
  10. data/lib/scout/llm/backends/huggingface.rb +6 -21
  11. data/lib/scout/llm/backends/ollama.rb +69 -36
  12. data/lib/scout/llm/backends/openai.rb +85 -35
  13. data/lib/scout/llm/backends/openwebui.rb +1 -1
  14. data/lib/scout/llm/backends/relay.rb +3 -2
  15. data/lib/scout/llm/backends/responses.rb +272 -0
  16. data/lib/scout/llm/chat.rb +547 -0
  17. data/lib/scout/llm/parse.rb +70 -13
  18. data/lib/scout/llm/tools.rb +126 -5
  19. data/lib/scout/llm/utils.rb +17 -10
  20. data/lib/scout/model/base.rb +19 -0
  21. data/lib/scout/model/python/base.rb +25 -0
  22. data/lib/scout/model/python/huggingface/causal/next_token.rb +23 -0
  23. data/lib/scout/model/python/huggingface/causal.rb +29 -0
  24. data/lib/scout/model/python/huggingface/classification +0 -0
  25. data/lib/scout/model/python/huggingface/classification.rb +50 -0
  26. data/lib/scout/model/python/huggingface.rb +112 -0
  27. data/lib/scout/model/python/torch/dataloader.rb +57 -0
  28. data/lib/scout/model/python/torch/helpers.rb +84 -0
  29. data/lib/scout/model/python/torch/introspection.rb +34 -0
  30. data/lib/scout/model/python/torch/load_and_save.rb +47 -0
  31. data/lib/scout/model/python/torch.rb +94 -0
  32. data/lib/scout/model/util/run.rb +181 -0
  33. data/lib/scout/model/util/save.rb +81 -0
  34. data/lib/scout-ai.rb +3 -1
  35. data/python/scout_ai/__init__.py +35 -0
  36. data/python/scout_ai/__pycache__/__init__.cpython-310.pyc +0 -0
  37. data/python/scout_ai/__pycache__/__init__.cpython-311.pyc +0 -0
  38. data/python/scout_ai/__pycache__/huggingface.cpython-310.pyc +0 -0
  39. data/python/scout_ai/__pycache__/huggingface.cpython-311.pyc +0 -0
  40. data/python/scout_ai/__pycache__/util.cpython-310.pyc +0 -0
  41. data/python/scout_ai/__pycache__/util.cpython-311.pyc +0 -0
  42. data/python/scout_ai/atcold/__init__.py +0 -0
  43. data/python/scout_ai/atcold/plot_lib.py +141 -0
  44. data/python/scout_ai/atcold/spiral.py +27 -0
  45. data/python/scout_ai/huggingface/data.py +48 -0
  46. data/python/scout_ai/huggingface/eval.py +60 -0
  47. data/python/scout_ai/huggingface/model.py +29 -0
  48. data/python/scout_ai/huggingface/rlhf.py +83 -0
  49. data/python/scout_ai/huggingface/train/__init__.py +34 -0
  50. data/python/scout_ai/huggingface/train/__pycache__/__init__.cpython-310.pyc +0 -0
  51. data/python/scout_ai/huggingface/train/__pycache__/next_token.cpython-310.pyc +0 -0
  52. data/python/scout_ai/huggingface/train/next_token.py +315 -0
  53. data/python/scout_ai/language_model.py +70 -0
  54. data/python/scout_ai/util.py +32 -0
  55. data/scout-ai.gemspec +130 -0
  56. data/scout_commands/agent/ask +133 -15
  57. data/scout_commands/agent/kb +15 -0
  58. data/scout_commands/llm/ask +71 -12
  59. data/scout_commands/llm/process +4 -2
  60. data/test/data/cat.jpg +0 -0
  61. data/test/scout/llm/agent/test_chat.rb +14 -0
  62. data/test/scout/llm/backends/test_bedrock.rb +60 -0
  63. data/test/scout/llm/backends/test_huggingface.rb +3 -3
  64. data/test/scout/llm/backends/test_ollama.rb +48 -10
  65. data/test/scout/llm/backends/test_openai.rb +96 -11
  66. data/test/scout/llm/backends/test_responses.rb +115 -0
  67. data/test/scout/llm/test_ask.rb +1 -0
  68. data/test/scout/llm/test_chat.rb +214 -0
  69. data/test/scout/llm/test_parse.rb +81 -2
  70. data/test/scout/model/python/huggingface/causal/test_next_token.rb +59 -0
  71. data/test/scout/model/python/huggingface/test_causal.rb +33 -0
  72. data/test/scout/model/python/huggingface/test_classification.rb +30 -0
  73. data/test/scout/model/python/test_base.rb +44 -0
  74. data/test/scout/model/python/test_huggingface.rb +9 -0
  75. data/test/scout/model/python/test_torch.rb +71 -0
  76. data/test/scout/model/python/torch/test_helpers.rb +14 -0
  77. data/test/scout/model/test_base.rb +117 -0
  78. data/test/scout/model/util/test_save.rb +31 -0
  79. metadata +72 -5
  80. data/questions/coach +0 -2
@@ -2,7 +2,7 @@ require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
2
2
  require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
3
3
 
4
4
  class TestLLMOpenAI < Test::Unit::TestCase
5
- def test_ask
5
+ def _test_ask
6
6
  prompt =<<-EOF
7
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
8
  user: write a script that sorts files in a directory
@@ -11,24 +11,95 @@ user: write a script that sorts files in a directory
11
11
  ppp LLM::OpenAI.ask prompt
12
12
  end
13
13
 
14
- def _test_argonne
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
- user: write a script that sorts files in a directory
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
- sss 0
41
+ ppp LLM::OpenAI.ask prompt, model: 'gpt-4.1-nano'
19
42
  end
20
43
 
21
- def _test_embeddings
44
+ def _test_tool_call_output_2
22
45
  Log.severity = 0
23
- text =<<-EOF
24
- Some text
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
- emb = LLM::OpenAI.embed text, log_errors: true
27
- assert(Float === emb.first)
59
+ ppp LLM::OpenAI.ask prompt, model: 'gpt-4.1-nano'
28
60
  end
29
61
 
30
- def _test_tool
62
+ def _test_tool_call_output_features
63
+ Log.severity = 0
31
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'
80
+ end
81
+
82
+ def _test_tool_call_output_weather
83
+ Log.severity = 0
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
+ def test_tool
101
+ prompt =<<-EOF
102
+ user:
32
103
  What is the weather in London. Should I take my umbrella?
33
104
  EOF
34
105
 
@@ -58,11 +129,25 @@ What is the weather in London. Should I take my umbrella?
58
129
  ]
59
130
 
60
131
  sss 0
61
- respose = LLM::OpenAI.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-4o" do |name,arguments|
132
+ respose = LLM::OpenAI.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-4.1-mini", log_errors: true do |name,arguments|
62
133
  "It's 15 degrees and raining."
63
134
  end
64
135
 
65
136
  ppp respose
66
137
  end
138
+
139
+ def _test_json_output
140
+ prompt =<<-EOF
141
+ system:
142
+
143
+ Respond in json format with a hash of strings as keys and string arrays as values, at most three in length
144
+
145
+ user:
146
+
147
+ What other movies have the protagonists of the original gost busters played on, just the top.
148
+ EOF
149
+ sss 0
150
+ ppp LLM::OpenAI.ask prompt, format: :json
151
+ end
67
152
  end
68
153
 
@@ -0,0 +1,115 @@
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
+ end
115
+
@@ -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
@@ -0,0 +1,214 @@
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 TestMessages < Test::Unit::TestCase
5
+
6
+ def test_short
7
+
8
+ question =<<-EOF
9
+ Hi
10
+ EOF
11
+
12
+ iii LLM.chat(question)
13
+ end
14
+
15
+ def test_inline
16
+ question =<<-EOF
17
+ system:
18
+
19
+ you are a terse assistant that only write in short sentences
20
+
21
+ assistant:
22
+
23
+ Here is some stuff
24
+
25
+ user: feedback
26
+
27
+ that continues here
28
+ EOF
29
+
30
+ iii LLM.chat(question)
31
+ end
32
+
33
+ def test_messages
34
+ question =<<-EOF
35
+ system:
36
+
37
+ you are a terse assistant that only write in short sentences
38
+
39
+ user:
40
+
41
+ What is the capital of France
42
+
43
+ assistant:
44
+
45
+ Paris
46
+
47
+ user:
48
+
49
+ is this the national anthem
50
+
51
+ [[
52
+ corous: Viva Espagna
53
+ ]]
54
+
55
+ assistant:
56
+
57
+ no
58
+
59
+ user:
60
+
61
+ import: math.system
62
+
63
+ consider this file
64
+
65
+ <file name=foo_bar>
66
+ foo: bar
67
+ </file>
68
+
69
+ how many characters does it hold
70
+
71
+ assistant:
72
+
73
+ 8
74
+ EOF
75
+
76
+ messages = LLM.messages question
77
+ refute messages.collect{|i| i[:role] }.include?("corous")
78
+ assert messages.collect{|i| i[:role] }.include?("import")
79
+ end
80
+
81
+ def test_chat_import
82
+ file1 =<<-EOF
83
+ system: You are an assistant
84
+ EOF
85
+
86
+ file2 =<<-EOF
87
+ import: header
88
+ user: say something
89
+ EOF
90
+
91
+ TmpFile.with_path do |tmpdir|
92
+ tmpdir.header.write file1
93
+ tmpdir.chat.write file2
94
+
95
+ chat = LLM.chat tmpdir.chat
96
+ end
97
+ end
98
+
99
+ def test_clear
100
+ question =<<-EOF
101
+ system:
102
+
103
+ you are a terse assistant that only write in short sentences
104
+
105
+ clear:
106
+
107
+ user:
108
+
109
+ What is the capital of France
110
+ EOF
111
+
112
+ TmpFile.with_file question do |file|
113
+ messages = LLM.chat file
114
+ refute messages.collect{|m| m[:role] }.include?('system')
115
+ end
116
+ end
117
+
118
+ def __test_job
119
+ question =<<-EOF
120
+ system:
121
+
122
+ you are a terse assistant that only write in short sentences
123
+
124
+ job: Baking/bake_muffin_tray/Default_08a1812eca3a18dce2232509dabc9b41
125
+
126
+ How are muffins made
127
+
128
+ EOF
129
+
130
+ TmpFile.with_file question do |file|
131
+ messages = LLM.chat file
132
+ ppp LLM.print messages
133
+ end
134
+ end
135
+
136
+
137
+ def test_task
138
+ question =<<-EOF
139
+ system:
140
+
141
+ you are a terse assistant that only write in short sentences
142
+
143
+ user:
144
+
145
+ task: Baking bake_muffin_tray blueberries=true title="This is a title" list=one,two,"and three"
146
+
147
+ How are muffins made?
148
+
149
+ EOF
150
+
151
+ TmpFile.with_file question do |file|
152
+ messages = LLM.chat file
153
+ ppp LLM.print messages
154
+ end
155
+ end
156
+
157
+ def test_structure
158
+ require 'scout/llm/ask'
159
+ sss 0
160
+ question =<<-EOF
161
+ system:
162
+
163
+ Respond in json format with a hash of strings as keys and string arrays as values, at most three in length
164
+
165
+ endpoint: sambanova
166
+
167
+ What other movies have the protagonists of the original gost busters played on, just the top.
168
+
169
+ EOF
170
+
171
+ TmpFile.with_file question do |file|
172
+ ppp LLM.ask file
173
+ end
174
+ end
175
+
176
+ def test_tools
177
+ require 'scout/llm/ask'
178
+
179
+ question =<<-EOF
180
+ user:
181
+
182
+ Use the provided tool to learn the instructions of baking a tray of muffins. Don't
183
+ give me your own recipe, return the one provided by the tool
184
+
185
+ tool: Baking bake_muffin_tray
186
+ EOF
187
+
188
+ TmpFile.with_file question do |file|
189
+ ppp LLM.ask file
190
+ end
191
+ end
192
+
193
+ def test_knowledge_base
194
+ require 'scout/llm/ask'
195
+ sss 0
196
+ question =<<-EOF
197
+ system:
198
+
199
+ Query the knowledge base of familiar relationships to answer the question
200
+
201
+ user:
202
+
203
+ Who is Miki's brother in law?
204
+
205
+ association: brothers #{datafile_test(:person).brothers} undirected=true
206
+ association: marriages #{datafile_test(:person).marriages} undirected=true source="=>Alias" target="=>Alias"
207
+ EOF
208
+
209
+ TmpFile.with_file question do |file|
210
+ ppp LLM.ask file
211
+ end
212
+ end
213
+ end
214
+
@@ -4,8 +4,9 @@ require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1
4
4
  class TestLLMParse < Test::Unit::TestCase
5
5
  def test_parse
6
6
  text=<<-EOF
7
+ hi
7
8
  system: you are an asistant
8
- user: Given the contents of this file: [[
9
+ user: Given the contents of this file:[[
9
10
  line 1: 1
10
11
  line 2: 2
11
12
  line 3: 3
@@ -13,7 +14,85 @@ line 3: 3
13
14
  Show me the lines in reverse order
14
15
  EOF
15
16
 
16
- iii LLM.parse(text)
17
+ assert_include LLM.parse(text).first[:content], 'hi'
18
+ assert_include LLM.parse(text).last[:content], 'reverse'
19
+ end
20
+
21
+ def test_code
22
+ text=<<-EOF
23
+ hi
24
+ system: you are an asistant
25
+ user: Given the contents of this file:
26
+ ```yaml
27
+ key: value
28
+ key2: value2
29
+ ```
30
+ Show me the lines in reverse order
31
+ EOF
32
+
33
+ assert_include LLM.parse(text).last[:content], 'key2'
34
+ end
35
+
36
+ def test_lines
37
+ text=<<-EOF
38
+ system: you are an asistant
39
+ user: I have a question
40
+ EOF
41
+
42
+ assert_include LLM.parse(text).last[:content], 'question'
43
+ end
44
+
45
+ def test_blocks
46
+ text=<<-EOF
47
+ system:
48
+
49
+ you are an asistant
50
+
51
+ user:
52
+
53
+ I have a question
54
+
55
+ EOF
56
+
57
+ assert_include LLM.parse(text).last[:content], 'question'
58
+ end
59
+
60
+ def test_no_role
61
+ text=<<-EOF
62
+ I have a question
63
+ EOF
64
+
65
+ assert_include LLM.parse(text).last[:content], 'question'
66
+ end
67
+
68
+
69
+ def test_cmd
70
+ text=<<-EOF
71
+ How many files are there:
72
+
73
+ [[cmd list of files
74
+ echo "file1 file2"
75
+ ]]
76
+ EOF
77
+
78
+ assert_equal :user, LLM.parse(text).last[:role]
79
+ assert_include LLM.parse(text).first[:content], 'file1'
80
+ end
81
+
82
+ def test_directory
83
+ TmpFile.with_path do |tmpdir|
84
+ tmpdir.file1.write "foo"
85
+ tmpdir.file2.write "bar"
86
+ text=<<-EOF
87
+ How many files are there:
88
+
89
+ [[directory DIR
90
+ #{tmpdir}
91
+ ]]
92
+ EOF
93
+
94
+ assert_include LLM.parse(text).first[:content], 'file1'
95
+ end
17
96
  end
18
97
  end
19
98
 
@@ -0,0 +1,59 @@
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
+ require 'scout-ai'
5
+ class TestClass < Test::Unit::TestCase
6
+ def test_main
7
+ model = NextTokenModel.new
8
+ train_texts = [
9
+ "say hi, no!",
10
+ "say hi, no no no",
11
+ "say hi, hi ",
12
+ "say hi, hi how are you ",
13
+ "say hi, hi are you good",
14
+ ]
15
+
16
+ model_name = "distilgpt2" # Replace with your local/other HF Llama checkpoint as needed
17
+
18
+ TmpFile.with_path do |tmp_dir|
19
+ iii tmp_dir
20
+
21
+ sss 0
22
+ model = NextTokenModel.new model_name, tmp_dir, training_num_train_epochs: 1000, training_learning_rate: 0.1
23
+
24
+ iii :new
25
+ chat = Chat.setup []
26
+ chat.user "say hi"
27
+ ppp model.eval chat
28
+
29
+ model.save
30
+ model = PythonModel.new tmp_dir
31
+
32
+ iii :load
33
+ chat = Chat.setup []
34
+ chat.user "say hi"
35
+ ppp model.eval chat
36
+
37
+ iii :training
38
+ state, tokenizer = model.init
39
+ tokenizer.pad_token = tokenizer.eos_token
40
+ model.add_list train_texts.shuffle
41
+ model.train
42
+
43
+ iii :trained
44
+ chat = Chat.setup []
45
+ chat.user "say hi"
46
+ ppp model.eval chat
47
+
48
+ model.save
49
+ model = PythonModel.new tmp_dir
50
+
51
+ iii :load_again
52
+ chat = Chat.setup []
53
+ chat.user "say hi"
54
+ ppp model.eval chat
55
+ end
56
+
57
+ end
58
+ end
59
+
@@ -0,0 +1,33 @@
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 TestClass < Test::Unit::TestCase
5
+ def test_eval_chat
6
+ #model = CausalModel.new 'BSC-LT/salamandra-2b-instruct'
7
+ model = CausalModel.new 'mistralai/Mistral-7B-Instruct-v0.3'
8
+
9
+ model.init
10
+
11
+ net, tok = model.state
12
+
13
+ iii model.eval([
14
+ {role: :system, content: "You are a calculator, just reply with the answer"},
15
+ {role: :user, content: " 1 + 2 ="}
16
+ ])
17
+ end
18
+
19
+ def test_eval_train
20
+ #model = CausalModel.new 'BSC-LT/salamandra-2b-instruct'
21
+ model = CausalModel.new 'mistralai/Mistral-7B-Instruct-v0.3'
22
+
23
+ model.init
24
+
25
+ net, tok = model.state
26
+
27
+ iii model.eval([
28
+ {role: :system, content: "You are a calculator, just reply with the answer"},
29
+ {role: :user, content: " 1 + 2 ="}
30
+ ])
31
+ end
32
+ end
33
+
@@ -0,0 +1,30 @@
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 TestSequenceClassification < Test::Unit::TestCase
5
+ def _test_eval_sequence_classification
6
+ model = SequenceClassificationModel.new 'bert-base-uncased', nil,
7
+ class_labels: %w(Bad Good)
8
+
9
+ assert_include ["Bad", "Good"], model.eval("This is dog")
10
+ assert_include ["Bad", "Good"], model.eval_list(["This is dog", "This is cat"]).first
11
+ end
12
+
13
+ def test_train_sequence_classification
14
+ model = SequenceClassificationModel.new 'bert-base-uncased', nil,
15
+ class_labels: %w(Bad Good)
16
+
17
+ model.init
18
+
19
+ 10.times do
20
+ model.add "The dog", 'Bad'
21
+ model.add "The cat", 'Good'
22
+ end
23
+
24
+ model.train
25
+
26
+ assert_equal "Bad", model.eval("This is dog")
27
+ assert_equal "Good", model.eval("This is cat")
28
+ end
29
+ end
30
+