Primitive insight queries
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
import { HttpStatus } from "helpers/http_helpers"
|
||||
import { delay } from "helpers/timing_helpers"
|
||||
import { marked } from "marked"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = [ "input", "form", "confirmation" ]
|
||||
@@ -43,7 +44,11 @@ export default class extends Controller {
|
||||
const response = event.detail.fetchResponse
|
||||
if (response && response.response.headers.get("Content-Type")?.includes("application/json")) {
|
||||
response.response.json().then((commands) => {
|
||||
this.element.querySelector("#chat-responses").textContent = JSON.stringify(commands, null, 2)
|
||||
if (commands.reply) {
|
||||
this.element.querySelector("#chat-insight").innerHTML = marked.parse(commands.reply)
|
||||
} else {
|
||||
this.element.querySelector("#chat-responses").textContent = JSON.stringify(commands, null, 2)
|
||||
}
|
||||
this.#executeCommands(commands)
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -7,7 +7,6 @@ class Command::ChatQuery < Command
|
||||
|
||||
def execute
|
||||
response = chat.ask query
|
||||
Rails.logger.info "***\n#{response.content}\n***"
|
||||
response = replace_names_with_ids(JSON.parse(response.content))
|
||||
Command::Result::ChatResponse.new(JSON.pretty_generate(response))
|
||||
end
|
||||
@@ -28,6 +27,7 @@ class Command::ChatQuery < Command
|
||||
- Close cards: /close [optional reason]
|
||||
- Tag cards: /tag [tag-name]
|
||||
- Search cards: /search. See how this works below:
|
||||
- Get insight about cards: /insight [query]
|
||||
|
||||
asks for a certain set of cards, you can use the /search command to filter. The /search command (and only this
|
||||
command) supports the following parameters:
|
||||
@@ -55,7 +55,7 @@ class Command::ChatQuery < Command
|
||||
Notice that there are overlapping commands (filter by assignee or assign cards). Favor filtering/queries for
|
||||
commands like "cards assigned to someone".
|
||||
|
||||
Notice that only /search commands carry additional JSON params. For /tag, /close and /assign just append the
|
||||
Notice that only /search commands carry additional JSON params. For /tag, /close, /insight and /assign just append the
|
||||
param to the string command. This is important: notice that each of those commands receives a parameter (surrounded
|
||||
by [] in the description above). Make sure if you invoke a given command you pass the params. Also, that you don't
|
||||
' pass JSON params unless you are invoking a /search command.
|
||||
@@ -69,6 +69,14 @@ class Command::ChatQuery < Command
|
||||
]
|
||||
}
|
||||
|
||||
When the user makes questions or requests that are not related to performing actions on cards, or to filtering cards,
|
||||
you should try to answer those by using the /insight command. Before invoking /insight, you need to generate a /search
|
||||
command that filters out the relevant cards to answer the question. Determine some good keywords to pass to /search, so
|
||||
that we can filter out the relevant cards to answer the question.
|
||||
|
||||
When passing terms to /search or the query to /insight, remove generic/common words such as "problem"" and "issue"" and keep
|
||||
the more meaningful nouns only.
|
||||
|
||||
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.'
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
class Command::GetInsight < Command
|
||||
include Command::Cards
|
||||
|
||||
store_accessor :data, :query
|
||||
|
||||
def title
|
||||
"Insight query '#{query}'"
|
||||
end
|
||||
|
||||
def execute
|
||||
response = chat.ask query
|
||||
Command::Result::ChatResponse.new({ reply: response.content })
|
||||
end
|
||||
|
||||
def undoable?
|
||||
false
|
||||
end
|
||||
|
||||
def needs_confirmation?
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
def chat
|
||||
chat = RubyLLM.chat
|
||||
chat.with_instructions(prompt + cards_context)
|
||||
end
|
||||
|
||||
def prompt
|
||||
<<~PROMPT
|
||||
You are a helpful assistant that is able to provide answers and insights about cards.
|
||||
|
||||
A card has a title, a description and a list of comments. When presenting some insight, at the end,
|
||||
list the sources as:
|
||||
|
||||
Try to be concise and accurate.
|
||||
|
||||
See: card id 1, card id 2, and comment id 123.
|
||||
|
||||
Use markdown for the response format.
|
||||
PROMPT
|
||||
end
|
||||
|
||||
def cards_context
|
||||
"".tap do |context|
|
||||
cards.order("created_at desc").limit(25).collect do |card|
|
||||
context << card_context_for(card)
|
||||
|
||||
card.comments.each do |comment|
|
||||
context << comment_context_for(comment)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def card_context_for(card)
|
||||
<<~CONTEXT
|
||||
Card created by: #{card.creator.name}}
|
||||
Id: #{card.id}
|
||||
Title: #{card.title}
|
||||
Description: #{card.description.to_plain_text}
|
||||
Assigned to: #{card.assignees.map(&:name).join(", ")}}
|
||||
Created at: #{card.created_at}}
|
||||
CONTEXT
|
||||
end
|
||||
|
||||
def comment_context_for(comment)
|
||||
<<~CONTEXT
|
||||
Card: #{comment.card.id}
|
||||
Id: #{comment.id}
|
||||
Content: #{comment.body.to_plain_text}}
|
||||
Comment created by: #{comment.creator.name}}
|
||||
CONTEXT
|
||||
end
|
||||
end
|
||||
@@ -25,6 +25,8 @@ class Command::Parser
|
||||
Command::GoToUser.new(user_id: assignee_from(command_name)&.id)
|
||||
when "/assign", "/assignto"
|
||||
Command::Assign.new(assignee_ids: assignees_from(command_arguments).collect(&:id), card_ids: cards.ids)
|
||||
when "/insight"
|
||||
Command::GetInsight.new(query: command_arguments.join(" "), card_ids: cards.ids)
|
||||
when "/clear"
|
||||
Command::ClearFilters.new(params: filter.as_params)
|
||||
when "/close"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ul class="terminal__menu flex-column txt-align-start margin-none margin-block-end unpad" aria-label="Recent commands" data-turbo-permanent="true"><%= render partial: "commands/command", collection: @commands %></ul>
|
||||
|
||||
|
||||
<pre id="chat-responses">
|
||||
</pre>
|
||||
<pre id="chat-responses"></pre>
|
||||
<p id="chat-insight"></p>
|
||||
<%= render "commands/help" %>
|
||||
<% end %>
|
||||
|
||||
@@ -10,3 +10,4 @@ pin "house", to: "house.min.js"
|
||||
pin_all_from "app/javascript/controllers", under: "controllers"
|
||||
pin_all_from "app/javascript/helpers", under: "helpers"
|
||||
pin_all_from "app/javascript/initializers", under: "initializers"
|
||||
pin "marked" # @15.0.11
|
||||
|
||||
Vendored
+2583
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user