Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 0534011

Browse files
committed
specs are passing
1 parent dbb19b9 commit 0534011

File tree

9 files changed

+114
-123
lines changed

9 files changed

+114
-123
lines changed

lib/completions/dialects/cohere_tools.rb

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,27 +38,24 @@ def tool_results(messages)
3838
end
3939

4040
def translated_tools
41-
raw_tools.map do |t|
42-
tool = t.dup
41+
raw_tools.map do |tool|
42+
defs = {}
4343

44-
tool[:parameter_definitions] = t[:parameters]
45-
.to_a
46-
.reduce({}) do |memo, p|
47-
name = p[:name]
48-
memo[name] = {
49-
description: p[:description],
50-
type: cohere_type(p[:type], p[:item_type]),
51-
required: p[:required],
52-
}
44+
tool.parameters.each do |p|
45+
name = p.name
46+
defs[name] = {
47+
description: p.description,
48+
type: cohere_type(p.type, p.item_type),
49+
required: p.required,
50+
}
5351

54-
memo[name][:default] = p[:default] if p[:default]
55-
memo
56-
end
52+
#defs[name][:default] = p.default if p.default
53+
end
5754

5855
{
59-
name: tool[:name] == "search" ? "search_local" : tool[:name],
60-
description: tool[:description],
61-
parameter_definitions: tool[:parameter_definitions],
56+
name: tool.name == "search" ? "search_local" : tool.name,
57+
description: tool.description,
58+
parameter_definitions: defs,
6259
}
6360
end
6461
end
@@ -72,6 +69,7 @@ def instructions
7269
attr_reader :raw_tools
7370

7471
def cohere_type(type, item_type)
72+
type = type.to_s
7573
case type
7674
when "string"
7775
"str"

lib/completions/dialects/nova_tools.rb

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ def translated_tools
1717
@raw_tools.map do |tool|
1818
{
1919
toolSpec: {
20-
name: tool[:name],
21-
description: tool[:description],
20+
name: tool.name,
21+
description: tool.description,
2222
inputSchema: {
23-
json: convert_tool_to_input_schema(tool),
23+
json: tool.parameters_json_schema,
2424
},
2525
},
2626
}
@@ -51,32 +51,6 @@ def from_raw_tool(raw_message)
5151
},
5252
}
5353
end
54-
55-
private
56-
57-
def convert_tool_to_input_schema(tool)
58-
tool = tool.transform_keys(&:to_sym)
59-
properties = {}
60-
tool[:parameters].each do |param|
61-
schema = {}
62-
type = param[:type]
63-
type = "string" if !%w[string number boolean integer array].include?(type)
64-
65-
schema[:type] = type
66-
67-
if enum = param[:enum]
68-
schema[:enum] = enum
69-
end
70-
71-
schema[:items] = { type: param[:item_type] } if type == "array"
72-
73-
schema[:required] = true if param[:required]
74-
75-
properties[param[:name]] = schema
76-
end
77-
78-
{ type: "object", properties: properties }
79-
end
8054
end
8155
end
8256
end

lib/completions/endpoints/base.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def endpoint_for(provider_name)
2828
DiscourseAi::Completions::Endpoints::OpenRouter,
2929
]
3030

31-
endpoints << DiscourseAi::Completions::Endpoints::Ollama if Rails.env.development?
31+
endpoints << DiscourseAi::Completions::Endpoints::Ollama if !Rails.env.production?
3232

3333
if Rails.env.test? || Rails.env.development?
3434
endpoints << DiscourseAi::Completions::Endpoints::Fake

spec/lib/completions/dialects/gemini_spec.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,11 @@
108108
required: %w[location unit],
109109
properties: {
110110
"location" => {
111-
type: "string",
111+
type: :string,
112112
description: "the city name",
113113
},
114114
"unit" => {
115-
type: "string",
115+
type: :string,
116116
description: "the unit of measurement celcius c or fahrenheit f",
117117
enum: %w[c f],
118118
},
@@ -121,7 +121,6 @@
121121
},
122122
],
123123
}
124-
125124
expect(context.dialect_tools).to contain_exactly(gemini_tools)
126125
end
127126
end

spec/lib/completions/dialects/nova_spec.rb

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,29 +84,30 @@
8484
dialect = nova_dialect_klass.new(prompt, llm_model)
8585
translated = dialect.translate
8686

87-
expect(translated.tool_config).to eq(
88-
{
89-
tools: [
90-
{
91-
toolSpec: {
92-
name: "get_weather",
93-
description: "Get the weather in a city",
94-
inputSchema: {
95-
json: {
96-
type: "object",
97-
properties: {
98-
"location" => {
99-
type: "string",
100-
required: true,
101-
},
87+
expected = {
88+
tools: [
89+
{
90+
toolSpec: {
91+
name: "get_weather",
92+
description: "Get the weather in a city",
93+
inputSchema: {
94+
json: {
95+
type: "object",
96+
properties: {
97+
"location" => {
98+
type: :string,
99+
description: "the city name",
102100
},
103101
},
102+
required: ["location"],
104103
},
105104
},
106105
},
107-
],
108-
},
109-
)
106+
},
107+
],
108+
}
109+
110+
expect(translated.tool_config).to eq(expected)
110111
end
111112
end
112113

spec/lib/completions/dialects/ollama_spec.rb

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
RSpec.describe DiscourseAi::Completions::Dialects::Ollama do
66
fab!(:model) { Fabricate(:ollama_model) }
77
let(:context) { DialectContext.new(described_class, model) }
8+
let(:dialect_class) { DiscourseAi::Completions::Dialects::Dialect.dialect_for(model) }
89

910
describe "#translate" do
1011
context "when native tool support is enabled" do
@@ -59,35 +60,49 @@
5960
describe "#tools" do
6061
context "when native tools are enabled" do
6162
it "returns the translated tools from the OllamaTools class" do
62-
tool = instance_double(DiscourseAi::Completions::Dialects::OllamaTools)
63+
model.update!(provider_params: { enable_native_tool: true })
6364

64-
allow(model).to receive(:lookup_custom_param).with("enable_native_tool").and_return(true)
65-
allow(tool).to receive(:translated_tools)
66-
allow(DiscourseAi::Completions::Dialects::OllamaTools).to receive(:new).and_return(tool)
67-
68-
context.dialect_tools
69-
70-
expect(DiscourseAi::Completions::Dialects::OllamaTools).to have_received(:new).with(
71-
context.prompt.tools,
72-
)
73-
expect(tool).to have_received(:translated_tools)
65+
tool = { name: "noop", description: "do nothing" }
66+
messages = [
67+
{ type: :user, content: "echo away" },
68+
{ type: :tool_call, content: "{}", name: "noop" },
69+
{ type: :tool, content: "{}", name: "noop" },
70+
]
71+
prompt = DiscourseAi::Completions::Prompt.new("a bot", tools: [tool], messages: messages)
72+
dialect = dialect_class.new(prompt, model)
73+
74+
expected = [
75+
{ role: "system", content: "a bot" },
76+
{ role: "user", content: "echo away" },
77+
{
78+
role: "assistant",
79+
content: nil,
80+
tool_calls: [{ type: "function", function: { name: "noop" } }],
81+
},
82+
{ role: "tool", content: "{}", name: "noop" },
83+
]
84+
expect(dialect.translate).to eq(expected)
7485
end
7586
end
7687

7788
context "when native tools are disabled" do
7889
it "returns the translated tools from the XmlTools class" do
79-
tool = instance_double(DiscourseAi::Completions::Dialects::XmlTools)
90+
model.update!(provider_params: { enable_native_tool: false })
8091

81-
allow(model).to receive(:lookup_custom_param).with("enable_native_tool").and_return(false)
82-
allow(tool).to receive(:translated_tools)
83-
allow(DiscourseAi::Completions::Dialects::XmlTools).to receive(:new).and_return(tool)
92+
tool = { name: "noop", description: "do nothing" }
93+
messages = [
94+
{ type: :user, content: "echo away" },
95+
{ type: :tool_call, content: "{}", name: "noop" },
96+
{ type: :tool, content: "{}", name: "noop" },
97+
]
98+
prompt = DiscourseAi::Completions::Prompt.new("a bot", tools: [tool], messages: messages)
99+
dialect = dialect_class.new(prompt, model)
84100

85-
context.dialect_tools
101+
expected = %w[system user assistant user]
102+
roles = dialect.translate.map { |x| x[:role] }
86103

87-
expect(DiscourseAi::Completions::Dialects::XmlTools).to have_received(:new).with(
88-
context.prompt.tools,
89-
)
90-
expect(tool).to have_received(:translated_tools)
104+
# notice, no tool role
105+
expect(roles).to eq(expected)
91106
end
92107
end
93108
end

spec/lib/completions/dialects/ollama_tools_spec.rb

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,33 @@
55
RSpec.describe DiscourseAi::Completions::Dialects::OllamaTools do
66
describe "#translated_tools" do
77
it "translates a tool from our generic format to the Ollama format" do
8-
tools = [
9-
{
10-
name: "github_file_content",
11-
description: "Retrieves the content of specified GitHub files",
12-
parameters: [
13-
{
14-
name: "repo_name",
15-
description: "The name of the GitHub repository (e.g., 'discourse/discourse')",
16-
type: "string",
17-
required: true,
18-
},
19-
{
20-
name: "file_paths",
21-
description: "The paths of the files to retrieve within the repository",
22-
type: "array",
23-
item_type: "string",
24-
required: true,
25-
},
26-
{
27-
name: "branch",
28-
description: "The branch or commit SHA to retrieve the files from (default: 'main')",
29-
type: "string",
30-
required: false,
31-
},
32-
],
33-
},
34-
]
8+
tool = {
9+
name: "github_file_content",
10+
description: "Retrieves the content of specified GitHub files",
11+
parameters: [
12+
{
13+
name: "repo_name",
14+
description: "The name of the GitHub repository (e.g., 'discourse/discourse')",
15+
type: "string",
16+
required: true,
17+
},
18+
{
19+
name: "file_paths",
20+
description: "The paths of the files to retrieve within the repository",
21+
type: "array",
22+
item_type: "string",
23+
required: true,
24+
},
25+
{
26+
name: "branch",
27+
description: "The branch or commit SHA to retrieve the files from (default: 'main')",
28+
type: "string",
29+
required: false,
30+
},
31+
],
32+
}
3533

34+
tools = [DiscourseAi::Completions::ToolDefinition.from_hash(tool)]
3635
ollama_tools = described_class.new(tools)
3736

3837
translated_tools = ollama_tools.translated_tools
@@ -49,16 +48,19 @@
4948
properties: {
5049
"repo_name" => {
5150
description: "The name of the GitHub repository (e.g., 'discourse/discourse')",
52-
type: "string",
51+
type: :string,
5352
},
5453
"file_paths" => {
5554
description: "The paths of the files to retrieve within the repository",
56-
type: "array",
55+
type: :array,
56+
items: {
57+
type: :string,
58+
},
5759
},
5860
"branch" => {
5961
description:
6062
"The branch or commit SHA to retrieve the files from (default: 'main')",
61-
type: "string",
63+
type: :string,
6264
},
6365
},
6466
required: %w[repo_name file_paths],

spec/lib/completions/endpoints/nova_spec.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,11 @@ def encode_message(message)
196196
"inputSchema" => {
197197
"json" => {
198198
"type" => "object",
199+
"required" => ["timezone"],
199200
"properties" => {
200201
"timezone" => {
201202
"type" => "string",
202-
"required" => true,
203+
"description" => "The timezone",
203204
},
204205
},
205206
},
@@ -268,9 +269,10 @@ def encode_message(message)
268269
properties: {
269270
timezone: {
270271
type: "string",
271-
required: true,
272+
description: "The timezone",
272273
},
273274
},
275+
required: ["timezone"],
274276
},
275277
},
276278
},

spec/lib/personas/persona_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ def system_prompt
6969

7070
tools = rendered.tools
7171

72-
expect(tools.find { |t| t[:name] == "search" }).to be_present
73-
expect(tools.find { |t| t[:name] == "tags" }).to be_present
72+
expect(tools.find { |t| t.name == "search" }).to be_present
73+
expect(tools.find { |t| t.name == "tags" }).to be_present
7474

7575
# needs to be configured so it is not available
76-
expect(tools.find { |t| t[:name] == "image" }).to be_nil
76+
expect(tools.find { |t| t.name == "image" }).to be_nil
7777
end
7878

7979
it "can parse string that are wrapped in quotes" do

0 commit comments

Comments
 (0)