FIX: Tune function calling (#519)
Adds support for "name" on functions which can be used for tool calls For function calls we need to keep track of id/name and previously we only supported either Also attempts to improve sql helper
This commit is contained in:
parent
b515b4f66d
commit
79638c2f50
|
@ -105,10 +105,16 @@ module DiscourseAi
|
||||||
tool_call_message = {
|
tool_call_message = {
|
||||||
type: :tool_call,
|
type: :tool_call,
|
||||||
id: tool_call_id,
|
id: tool_call_id,
|
||||||
content: { name: tool.name, arguments: tool.parameters }.to_json,
|
content: { arguments: tool.parameters }.to_json,
|
||||||
|
name: tool.name,
|
||||||
}
|
}
|
||||||
|
|
||||||
tool_message = { type: :tool, id: tool_call_id, content: invocation_result_json }
|
tool_message = {
|
||||||
|
type: :tool,
|
||||||
|
id: tool_call_id,
|
||||||
|
content: invocation_result_json,
|
||||||
|
name: tool.name,
|
||||||
|
}
|
||||||
|
|
||||||
if tool.standalone?
|
if tool.standalone?
|
||||||
standalone_context =
|
standalone_context =
|
||||||
|
@ -125,8 +131,8 @@ module DiscourseAi
|
||||||
prompt.push(**tool_message)
|
prompt.push(**tool_message)
|
||||||
end
|
end
|
||||||
|
|
||||||
raw_context << [tool_call_message[:content], tool_call_id, "tool_call"]
|
raw_context << [tool_call_message[:content], tool_call_id, "tool_call", tool.name]
|
||||||
raw_context << [invocation_result_json, tool_call_id, "tool"]
|
raw_context << [invocation_result_json, tool_call_id, "tool", tool.name]
|
||||||
end
|
end
|
||||||
|
|
||||||
def invoke_tool(tool, llm, cancel, &update_blk)
|
def invoke_tool(tool, llm, cancel, &update_blk)
|
||||||
|
|
|
@ -143,10 +143,10 @@ module DiscourseAi
|
||||||
def find_tool(parsed_function)
|
def find_tool(parsed_function)
|
||||||
function_id = parsed_function.at("tool_id")&.text
|
function_id = parsed_function.at("tool_id")&.text
|
||||||
function_name = parsed_function.at("tool_name")&.text
|
function_name = parsed_function.at("tool_name")&.text
|
||||||
return false if function_name.nil?
|
return nil if function_name.nil?
|
||||||
|
|
||||||
tool_klass = available_tools.find { |c| c.signature.dig(:name) == function_name }
|
tool_klass = available_tools.find { |c| c.signature.dig(:name) == function_name }
|
||||||
return false if tool_klass.nil?
|
return nil if tool_klass.nil?
|
||||||
|
|
||||||
arguments = {}
|
arguments = {}
|
||||||
tool_klass.signature[:parameters].to_a.each do |param|
|
tool_klass.signature[:parameters].to_a.each do |param|
|
||||||
|
|
|
@ -8,7 +8,16 @@ module DiscourseAi
|
||||||
return @schema if defined?(@schema)
|
return @schema if defined?(@schema)
|
||||||
|
|
||||||
tables = Hash.new
|
tables = Hash.new
|
||||||
priority_tables = %w[posts topics notifications users user_actions user_emails]
|
priority_tables = %w[
|
||||||
|
posts
|
||||||
|
topics
|
||||||
|
notifications
|
||||||
|
users
|
||||||
|
user_actions
|
||||||
|
user_emails
|
||||||
|
categories
|
||||||
|
groups
|
||||||
|
]
|
||||||
|
|
||||||
DB.query(<<~SQL).each { |row| (tables[row.table_name] ||= []) << row.column_name }
|
DB.query(<<~SQL).each { |row| (tables[row.table_name] ||= []) << row.column_name }
|
||||||
select table_name, column_name from information_schema.columns
|
select table_name, column_name from information_schema.columns
|
||||||
|
@ -16,15 +25,16 @@ module DiscourseAi
|
||||||
order by table_name
|
order by table_name
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
schema = +(priority_tables.map { |name| "#{name}(#{tables[name].join(",")})" }.join("\n"))
|
priority =
|
||||||
|
+(priority_tables.map { |name| "#{name}(#{tables[name].join(",")})" }.join("\n"))
|
||||||
|
|
||||||
schema << "\nOther tables (schema redacted, available on request): "
|
other_tables = +""
|
||||||
tables.each do |table_name, _|
|
tables.each do |table_name, _|
|
||||||
next if priority_tables.include?(table_name)
|
next if priority_tables.include?(table_name)
|
||||||
schema << "#{table_name} "
|
other_tables << "#{table_name} "
|
||||||
end
|
end
|
||||||
|
|
||||||
@schema = schema
|
@schema = { priority_tables: priority, other_tables: other_tables }
|
||||||
end
|
end
|
||||||
|
|
||||||
def tools
|
def tools
|
||||||
|
@ -38,12 +48,15 @@ module DiscourseAi
|
||||||
def system_prompt
|
def system_prompt
|
||||||
<<~PROMPT
|
<<~PROMPT
|
||||||
You are a PostgreSQL expert.
|
You are a PostgreSQL expert.
|
||||||
|
- Avoid returning any text to the user prior to a tool call.
|
||||||
- You understand and generate Discourse Markdown but specialize in creating queries.
|
- You understand and generate Discourse Markdown but specialize in creating queries.
|
||||||
- You live in a Discourse Forum Message.
|
- You live in a Discourse Forum Message.
|
||||||
- The schema in your training set MAY be out of date.
|
- Format SQL for maximum readability. Use line breaks, indentation, and spaces around operators. Add comments if needed to explain complex logic.
|
||||||
|
- Never warn or inform end user you are going to look up schema.
|
||||||
|
- Always try to get ALL the schema you need in the least tool calls.
|
||||||
|
- Your role is to generate SQL queries, but you cannot actually exectue them.
|
||||||
|
- When generating SQL always use ```sql Markdown code blocks.
|
||||||
- When generating SQL NEVER end SQL samples with a semicolon (;).
|
- When generating SQL NEVER end SQL samples with a semicolon (;).
|
||||||
- When generating SQL always use ```sql markdown code blocks.
|
|
||||||
- Always format SQL in a highly readable format.
|
|
||||||
|
|
||||||
Eg:
|
Eg:
|
||||||
|
|
||||||
|
@ -52,17 +65,29 @@ module DiscourseAi
|
||||||
```
|
```
|
||||||
|
|
||||||
The user_actions tables stores likes (action_type 1).
|
The user_actions tables stores likes (action_type 1).
|
||||||
the topics table stores private/personal messages it uses archetype private_message for them.
|
The topics table stores private/personal messages it uses archetype private_message for them.
|
||||||
notification_level can be: {muted: 0, regular: 1, tracking: 2, watching: 3, watching_first_post: 4}.
|
notification_level can be: {muted: 0, regular: 1, tracking: 2, watching: 3, watching_first_post: 4}.
|
||||||
bookmarkable_type can be: Post,Topic,ChatMessage and more
|
bookmarkable_type can be: Post,Topic,ChatMessage and more
|
||||||
|
|
||||||
Current time is: {time}
|
Current time is: {time}
|
||||||
|
Participants here are: {participants}
|
||||||
|
|
||||||
|
Here is a partial list of tables in the database (you can retrieve schema from these tables as needed)
|
||||||
|
|
||||||
|
```
|
||||||
|
#{self.class.schema[:other_tables]}
|
||||||
|
```
|
||||||
|
|
||||||
|
You may look up schema for the tables listed above.
|
||||||
|
|
||||||
|
Here is full information on priority tables:
|
||||||
|
|
||||||
|
```
|
||||||
|
#{self.class.schema[:priority_tables]}
|
||||||
|
```
|
||||||
|
|
||||||
|
NEVER look up schema for the tables listed above, as their full schema is already provided.
|
||||||
|
|
||||||
The current schema for the current DB is:
|
|
||||||
{{
|
|
||||||
#{self.class.schema}
|
|
||||||
}}
|
|
||||||
PROMPT
|
PROMPT
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -122,6 +122,7 @@ module DiscourseAi
|
||||||
}
|
}
|
||||||
|
|
||||||
custom_context[:id] = message[1] if custom_context[:type] != :model
|
custom_context[:id] = message[1] if custom_context[:type] != :model
|
||||||
|
custom_context[:name] = message[3] if message[3]
|
||||||
|
|
||||||
result << custom_context
|
result << custom_context
|
||||||
end
|
end
|
||||||
|
|
|
@ -48,6 +48,7 @@ module DiscourseAi
|
||||||
elsif msg[:type] == :tool_call
|
elsif msg[:type] == :tool_call
|
||||||
call_details = JSON.parse(msg[:content], symbolize_names: true)
|
call_details = JSON.parse(msg[:content], symbolize_names: true)
|
||||||
call_details[:arguments] = call_details[:arguments].to_json
|
call_details[:arguments] = call_details[:arguments].to_json
|
||||||
|
call_details[:name] = msg[:name]
|
||||||
|
|
||||||
{
|
{
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
|
@ -55,7 +56,7 @@ module DiscourseAi
|
||||||
tool_calls: [{ type: "function", function: call_details, id: msg[:id] }],
|
tool_calls: [{ type: "function", function: call_details, id: msg[:id] }],
|
||||||
}
|
}
|
||||||
elsif msg[:type] == :tool
|
elsif msg[:type] == :tool
|
||||||
{ role: "tool", tool_call_id: msg[:id], content: msg[:content] }
|
{ role: "tool", tool_call_id: msg[:id], content: msg[:content], name: msg[:name] }
|
||||||
else
|
else
|
||||||
user_message = { role: "user", content: msg[:content] }
|
user_message = { role: "user", content: msg[:content] }
|
||||||
if msg[:id]
|
if msg[:id]
|
||||||
|
|
|
@ -24,9 +24,9 @@ module DiscourseAi
|
||||||
|
|
||||||
claude_prompt =
|
claude_prompt =
|
||||||
trimmed_messages.reduce(+"") do |memo, msg|
|
trimmed_messages.reduce(+"") do |memo, msg|
|
||||||
next(memo) if msg[:type] == :tool_call
|
if msg[:type] == :tool_call
|
||||||
|
memo << "\n\nAssistant: #{tool_call_to_xml(msg)}"
|
||||||
if msg[:type] == :system
|
elsif msg[:type] == :system
|
||||||
memo << "Human: " unless uses_system_message?
|
memo << "Human: " unless uses_system_message?
|
||||||
memo << msg[:content]
|
memo << msg[:content]
|
||||||
if prompt.tools.present?
|
if prompt.tools.present?
|
||||||
|
@ -36,18 +36,8 @@ module DiscourseAi
|
||||||
elsif msg[:type] == :model
|
elsif msg[:type] == :model
|
||||||
memo << "\n\nAssistant: #{msg[:content]}"
|
memo << "\n\nAssistant: #{msg[:content]}"
|
||||||
elsif msg[:type] == :tool
|
elsif msg[:type] == :tool
|
||||||
memo << "\n\nAssistant:\n"
|
memo << "\n\nHuman:\n"
|
||||||
|
memo << tool_result_to_xml(msg)
|
||||||
memo << (<<~TEXT).strip
|
|
||||||
<function_results>
|
|
||||||
<result>
|
|
||||||
<tool_name>#{msg[:id]}</tool_name>
|
|
||||||
<json>
|
|
||||||
#{msg[:content]}
|
|
||||||
</json>
|
|
||||||
</result>
|
|
||||||
</function_results>
|
|
||||||
TEXT
|
|
||||||
else
|
else
|
||||||
memo << "\n\nHuman: "
|
memo << "\n\nHuman: "
|
||||||
memo << "#{msg[:id]}: " if msg[:id]
|
memo << "#{msg[:id]}: " if msg[:id]
|
||||||
|
|
|
@ -51,10 +51,13 @@ module DiscourseAi
|
||||||
If a parameter type is an array, return a JSON array of values. For example:
|
If a parameter type is an array, return a JSON array of values. For example:
|
||||||
[1,"two",3.0]
|
[1,"two",3.0]
|
||||||
|
|
||||||
Always wrap <invoke> calls in <function_calls> tags.
|
If you wish to call multiple function in one reply, wrap multiple <invoke>
|
||||||
You may call multiple function via <invoke> in a single <function_calls> block.
|
block in a single <function_calls> block.
|
||||||
|
|
||||||
Here are the tools available:
|
Always prefer to lead with tool calls, if you need to execute any.
|
||||||
|
Avoid all niceties prior to tool calls, Eg: "Let me look this up for you.." etc.
|
||||||
|
|
||||||
|
Here are the complete list of tools available:
|
||||||
TEXT
|
TEXT
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -73,7 +76,7 @@ module DiscourseAi
|
||||||
(<<~TEXT).strip
|
(<<~TEXT).strip
|
||||||
<function_results>
|
<function_results>
|
||||||
<result>
|
<result>
|
||||||
<tool_name>#{message[:id]}</tool_name>
|
<tool_name>#{message[:name] || message[:id]}</tool_name>
|
||||||
<json>
|
<json>
|
||||||
#{message[:content]}
|
#{message[:content]}
|
||||||
</json>
|
</json>
|
||||||
|
@ -95,7 +98,7 @@ module DiscourseAi
|
||||||
(<<~TEXT).strip
|
(<<~TEXT).strip
|
||||||
<function_calls>
|
<function_calls>
|
||||||
<invoke>
|
<invoke>
|
||||||
<tool_name>#{parsed[:name]}</tool_name>
|
<tool_name>#{message[:name] || parsed[:name]}</tool_name>
|
||||||
#{parameters}</invoke>
|
#{parameters}</invoke>
|
||||||
</function_calls>
|
</function_calls>
|
||||||
TEXT
|
TEXT
|
||||||
|
|
|
@ -38,7 +38,7 @@ module DiscourseAi
|
||||||
role: "model",
|
role: "model",
|
||||||
parts: {
|
parts: {
|
||||||
functionCall: {
|
functionCall: {
|
||||||
name: call_details[:name],
|
name: msg[:name] || call_details[:name],
|
||||||
args: call_details[:arguments],
|
args: call_details[:arguments],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -48,7 +48,7 @@ module DiscourseAi
|
||||||
role: "function",
|
role: "function",
|
||||||
parts: {
|
parts: {
|
||||||
functionResponse: {
|
functionResponse: {
|
||||||
name: msg[:id],
|
name: msg[:name] || msg[:id],
|
||||||
response: {
|
response: {
|
||||||
content: msg[:content],
|
content: msg[:content],
|
||||||
},
|
},
|
||||||
|
|
|
@ -21,9 +21,10 @@ module DiscourseAi
|
||||||
|
|
||||||
mixtral_prompt =
|
mixtral_prompt =
|
||||||
trim_messages(messages).reduce(+"") do |memo, msg|
|
trim_messages(messages).reduce(+"") do |memo, msg|
|
||||||
next(memo) if msg[:type] == :tool_call
|
if msg[:type] == :tool_call
|
||||||
|
memo << "\n"
|
||||||
if msg[:type] == :system
|
memo << tool_call_to_xml(msg)
|
||||||
|
elsif msg[:type] == :system
|
||||||
memo << (<<~TEXT).strip
|
memo << (<<~TEXT).strip
|
||||||
<s> [INST]
|
<s> [INST]
|
||||||
#{msg[:content]}
|
#{msg[:content]}
|
||||||
|
@ -34,17 +35,7 @@ module DiscourseAi
|
||||||
memo << "\n#{msg[:content]}</s>"
|
memo << "\n#{msg[:content]}</s>"
|
||||||
elsif msg[:type] == :tool
|
elsif msg[:type] == :tool
|
||||||
memo << "\n"
|
memo << "\n"
|
||||||
|
memo << tool_result_to_xml(msg)
|
||||||
memo << (<<~TEXT).strip
|
|
||||||
<function_results>
|
|
||||||
<result>
|
|
||||||
<tool_name>#{msg[:id]}</tool_name>
|
|
||||||
<json>
|
|
||||||
#{msg[:content]}
|
|
||||||
</json>
|
|
||||||
</result>
|
|
||||||
</function_results>
|
|
||||||
TEXT
|
|
||||||
else
|
else
|
||||||
memo << "\n[INST]#{msg[:content]}[/INST]"
|
memo << "\n[INST]#{msg[:content]}[/INST]"
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,9 +23,10 @@ module DiscourseAi
|
||||||
|
|
||||||
llama2_prompt =
|
llama2_prompt =
|
||||||
trimmed_messages.reduce(+"") do |memo, msg|
|
trimmed_messages.reduce(+"") do |memo, msg|
|
||||||
next(memo) if msg[:type] == :tool_call
|
if msg[:type] == :tool_call
|
||||||
|
memo << "\n### Assistant:\n"
|
||||||
if msg[:type] == :system
|
memo << tool_call_to_xml(msg)
|
||||||
|
elsif msg[:type] == :system
|
||||||
memo << (<<~TEXT).strip
|
memo << (<<~TEXT).strip
|
||||||
### System:
|
### System:
|
||||||
#{msg[:content]}
|
#{msg[:content]}
|
||||||
|
@ -34,18 +35,8 @@ module DiscourseAi
|
||||||
elsif msg[:type] == :model
|
elsif msg[:type] == :model
|
||||||
memo << "\n### Assistant:\n#{msg[:content]}"
|
memo << "\n### Assistant:\n#{msg[:content]}"
|
||||||
elsif msg[:type] == :tool
|
elsif msg[:type] == :tool
|
||||||
memo << "\n### Assistant:\n"
|
memo << "\n### User:\n"
|
||||||
|
memo << tool_result_to_xml(msg)
|
||||||
memo << (<<~TEXT).strip
|
|
||||||
<function_results>
|
|
||||||
<result>
|
|
||||||
<tool_name>#{msg[:id]}</tool_name>
|
|
||||||
<json>
|
|
||||||
#{msg[:content]}
|
|
||||||
</json>
|
|
||||||
</result>
|
|
||||||
</function_results>
|
|
||||||
TEXT
|
|
||||||
else
|
else
|
||||||
memo << "\n### User:\n#{msg[:content]}"
|
memo << "\n### User:\n#{msg[:content]}"
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,9 +38,10 @@ module DiscourseAi
|
||||||
@tools = tools
|
@tools = tools
|
||||||
end
|
end
|
||||||
|
|
||||||
def push(type:, content:, id: nil)
|
def push(type:, content:, id: nil, name: nil)
|
||||||
return if type == :system
|
return if type == :system
|
||||||
new_message = { type: type, content: content }
|
new_message = { type: type, content: content }
|
||||||
|
new_message[:name] = name.to_s if name
|
||||||
new_message[:id] = id.to_s if id
|
new_message[:id] = id.to_s if id
|
||||||
|
|
||||||
validate_message(new_message)
|
validate_message(new_message)
|
||||||
|
@ -62,7 +63,7 @@ module DiscourseAi
|
||||||
raise ArgumentError, "message type must be one of #{valid_types}"
|
raise ArgumentError, "message type must be one of #{valid_types}"
|
||||||
end
|
end
|
||||||
|
|
||||||
valid_keys = %i[type content id]
|
valid_keys = %i[type content id name]
|
||||||
if (invalid_keys = message.keys - valid_keys).any?
|
if (invalid_keys = message.keys - valid_keys).any?
|
||||||
raise ArgumentError, "message contains invalid keys: #{invalid_keys}"
|
raise ArgumentError, "message contains invalid keys: #{invalid_keys}"
|
||||||
end
|
end
|
||||||
|
|
|
@ -62,7 +62,12 @@ RSpec.describe DiscourseAi::Completions::Dialects::ChatGpt do
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ role: "tool", content: "I'm a tool result".to_json, tool_call_id: "tool_id" },
|
{
|
||||||
|
role: "tool",
|
||||||
|
content: "I'm a tool result".to_json,
|
||||||
|
tool_call_id: "tool_id",
|
||||||
|
name: "get_weather",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -37,10 +37,20 @@ RSpec.describe DiscourseAi::Completions::Dialects::Claude do
|
||||||
|
|
||||||
Human: user1: This is a new message by a user
|
Human: user1: This is a new message by a user
|
||||||
|
|
||||||
Assistant:
|
Assistant: <function_calls>
|
||||||
|
<invoke>
|
||||||
|
<tool_name>get_weather</tool_name>
|
||||||
|
<parameters>
|
||||||
|
<location>Sydney</location>
|
||||||
|
<unit>c</unit>
|
||||||
|
</parameters>
|
||||||
|
</invoke>
|
||||||
|
</function_calls>
|
||||||
|
|
||||||
|
Human:
|
||||||
<function_results>
|
<function_results>
|
||||||
<result>
|
<result>
|
||||||
<tool_name>tool_id</tool_name>
|
<tool_name>get_weather</tool_name>
|
||||||
<json>
|
<json>
|
||||||
"I'm a tool result"
|
"I'm a tool result"
|
||||||
</json>
|
</json>
|
||||||
|
|
|
@ -51,9 +51,10 @@ class DialectContext
|
||||||
{
|
{
|
||||||
type: :tool_call,
|
type: :tool_call,
|
||||||
id: "tool_id",
|
id: "tool_id",
|
||||||
content: { name: "get_weather", arguments: { location: "Sydney", unit: "c" } }.to_json,
|
name: "get_weather",
|
||||||
|
content: { arguments: { location: "Sydney", unit: "c" } }.to_json,
|
||||||
},
|
},
|
||||||
{ type: :tool, id: "tool_id", content: "I'm a tool result".to_json },
|
{ type: :tool, id: "tool_id", name: "get_weather", content: "I'm a tool result".to_json },
|
||||||
]
|
]
|
||||||
|
|
||||||
a_prompt = prompt
|
a_prompt = prompt
|
||||||
|
|
|
@ -72,7 +72,7 @@ RSpec.describe DiscourseAi::Completions::Dialects::Gemini do
|
||||||
role: "function",
|
role: "function",
|
||||||
parts: {
|
parts: {
|
||||||
functionResponse: {
|
functionResponse: {
|
||||||
name: "tool_id",
|
name: "get_weather",
|
||||||
response: {
|
response: {
|
||||||
content: "I'm a tool result".to_json,
|
content: "I'm a tool result".to_json,
|
||||||
},
|
},
|
||||||
|
|
|
@ -34,9 +34,18 @@ RSpec.describe DiscourseAi::Completions::Dialects::Mixtral do
|
||||||
[INST]This is a message by a user[/INST]
|
[INST]This is a message by a user[/INST]
|
||||||
I'm a previous bot reply, that's why there's no user</s>
|
I'm a previous bot reply, that's why there's no user</s>
|
||||||
[INST]This is a new message by a user[/INST]
|
[INST]This is a new message by a user[/INST]
|
||||||
|
<function_calls>
|
||||||
|
<invoke>
|
||||||
|
<tool_name>get_weather</tool_name>
|
||||||
|
<parameters>
|
||||||
|
<location>Sydney</location>
|
||||||
|
<unit>c</unit>
|
||||||
|
</parameters>
|
||||||
|
</invoke>
|
||||||
|
</function_calls>
|
||||||
<function_results>
|
<function_results>
|
||||||
<result>
|
<result>
|
||||||
<tool_name>tool_id</tool_name>
|
<tool_name>get_weather</tool_name>
|
||||||
<json>
|
<json>
|
||||||
"I'm a tool result"
|
"I'm a tool result"
|
||||||
</json>
|
</json>
|
||||||
|
|
|
@ -38,9 +38,19 @@ RSpec.describe DiscourseAi::Completions::Dialects::OrcaStyle do
|
||||||
### User:
|
### User:
|
||||||
This is a new message by a user
|
This is a new message by a user
|
||||||
### Assistant:
|
### Assistant:
|
||||||
|
<function_calls>
|
||||||
|
<invoke>
|
||||||
|
<tool_name>get_weather</tool_name>
|
||||||
|
<parameters>
|
||||||
|
<location>Sydney</location>
|
||||||
|
<unit>c</unit>
|
||||||
|
</parameters>
|
||||||
|
</invoke>
|
||||||
|
</function_calls>
|
||||||
|
### User:
|
||||||
<function_results>
|
<function_results>
|
||||||
<result>
|
<result>
|
||||||
<tool_name>tool_id</tool_name>
|
<tool_name>get_weather</tool_name>
|
||||||
<json>
|
<json>
|
||||||
"I'm a tool result"
|
"I'm a tool result"
|
||||||
</json>
|
</json>
|
||||||
|
|
|
@ -89,11 +89,19 @@ RSpec.describe DiscourseAi::AiBot::Personas::Persona do
|
||||||
<prompts>["pic3"]</prompts>
|
<prompts>["pic3"]</prompts>
|
||||||
</parameters>
|
</parameters>
|
||||||
</invoke>
|
</invoke>
|
||||||
|
<invoke>
|
||||||
|
<tool_name>unknown</tool_name>
|
||||||
|
<tool_id>abc</tool_id>
|
||||||
|
<parameters>
|
||||||
|
<prompts>["pic3"]</prompts>
|
||||||
|
</parameters>
|
||||||
|
</invoke>
|
||||||
</function_calls>
|
</function_calls>
|
||||||
XML
|
XML
|
||||||
dall_e1, dall_e2 = DiscourseAi::AiBot::Personas::DallE3.new.find_tools(xml)
|
dall_e1, dall_e2 = tools = DiscourseAi::AiBot::Personas::DallE3.new.find_tools(xml)
|
||||||
expect(dall_e1.parameters[:prompts]).to eq(["cat oil painting", "big car"])
|
expect(dall_e1.parameters[:prompts]).to eq(["cat oil painting", "big car"])
|
||||||
expect(dall_e2.parameters[:prompts]).to eq(["pic3"])
|
expect(dall_e2.parameters[:prompts]).to eq(["pic3"])
|
||||||
|
expect(tools.length).to eq(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "custom personas" do
|
describe "custom personas" do
|
||||||
|
|
Loading…
Reference in New Issue