Better foundation for chat responses

This commit is contained in:
Jorge Manrubia
2025-05-12 21:30:06 +02:00
parent 5425b03af4
commit cd53ef59eb
9 changed files with 131 additions and 71 deletions
+22 -3
View File
@@ -7,8 +7,8 @@ class Command::ChatQuery < Command
def execute
response = chat.ask query
response = replace_names_with_ids(JSON.parse(response.content))
Command::Result::ChatResponse.new(JSON.pretty_generate(response))
generated_commands = replace_names_with_ids(JSON.parse(response.content))
build_chat_response_with generated_commands
end
private
@@ -17,6 +17,8 @@ class Command::ChatQuery < Command
chat.with_instructions(prompt)
end
# TODO:
# - Don't generate initial /search if not requested. "Assign to JZ" should
def prompt
<<~PROMPT
You are a helpful assistant that translates natural language into commands that Fizzy understand.
@@ -76,7 +78,9 @@ class Command::ChatQuery < Command
]
Unless asking for explicit filtering, always prefer /insight over /search. When asking about "cards" with properties that can
be satisfied with /search, then use /search
be satisfied with /search, then use /search.
A response can contain at most one /search command.
Please combine commands to satisfy what the user needs. E.g: search with keywords and filters and then apply
as many commands as needed. Make sure you don't leave actions mentioned in the query needs unattended.'
@@ -111,4 +115,19 @@ class Command::ChatQuery < Command
User.all.find { |user| user.mentionable_handles.include?(string_without_at) }
end
def build_chat_response_with(generated_commands)
Command::Result::ChatResponse.new \
command_lines: response_command_lines_from(generated_commands),
context_url: response_context_url_from(generated_commands)
end
def response_command_lines_from(generated_commands)
generated_commands.filter { it["command"] != "/search" }.collect { it["command"] }
end
def response_context_url_from(generated_commands)
if search_command = generated_commands.find { it["command"] == "/search" }
cards_path(**search_command.without("command"))
end
end
end
+33
View File
@@ -0,0 +1,33 @@
# A composite of commands
class Command::Composite
attr_reader :commands
def initialize(commands)
@commands = commands
end
def title
@commands.collect(&:title).join(", ")
end
def execute
ApplicationRecord.transaction do
commands.each(&:execute)
end
end
def undo
ApplicationRecord.transaction do
undoable_commands.reverse.each(&:undo)
end
end
def needs_confirmation?
commands.any?(&:needs_confirmation?)
end
private
def undoable_commands
commands.filter(&:undoable?)
end
end
+1 -1
View File
@@ -9,7 +9,7 @@ class Command::GetInsight < Command
def execute
response = chat.ask query
Command::Result::ChatResponse.new({ reply: response.content })
Command::Result::InsightResponse.new({ reply: response.content })
end
def undoable?
+12 -1
View File
@@ -1 +1,12 @@
Command::Result::ChatResponse = Struct.new(:content)
class Command::Result::ChatResponse
attr_reader :command_lines, :context_url
def initialize(context_url: nil, command_lines:)
@context_url = context_url
@command_lines = command_lines
end
def has_context_url?
context_url.present?
end
end
@@ -0,0 +1 @@
Command::Result::InsightResponse = Struct.new(:content)