LLM task(s) for generating dashboard descriptions | (ns metabase-enterprise.llm.tasks.describe-dashboard (:require [clojure.set :refer [rename-keys]] [clojure.walk :as walk] [metabase-enterprise.llm.client :as llm-client] [metabase.util :as u] [metabase.util.json :as json] [toucan2.core :as t2])) |
Create a data-oriented summary of a dashboard as input to an LLM for summarization. | (defn- dashboard->prompt-data
[dashboard-id]
(let [{dashboard-name :name :keys [parameters dashcards]}
(t2/hydrate (t2/select-one :model/Dashboard dashboard-id) [:dashcards
:card
:series
:dashcard/action
:dashcard/linkcard-info]
:tabs
:param_fields
:param_values)
param-id->param (zipmap
(map :id parameters)
(map (fn [param]
(-> (select-keys param [:name :type])
(rename-keys {:name :parameter-name :type :filter-type})
(update :filter-type name)))
parameters))]
{:dashboard-name dashboard-name
:charts (for [{:keys [card parameter_mappings]} dashcards
:let [{card-name :name
:keys [display
description
visualization_settings
result_metadata]} card
field-name->display-name (zipmap
(map :name result_metadata)
(mapv (some-fn :display_name :name) result_metadata))
visualization_settings (->> visualization_settings
u/remove-nils
(walk/prewalk (fn [v] (field-name->display-name v v))))]]
(cond->
{:chart-name card-name
:chart-description description
:chart-type display
:data-column-names (vals field-name->display-name)
:chart-parameters (mapv
(comp :parameter-name param-id->param :parameter_id)
parameter_mappings)}
(seq visualization_settings)
(assoc :chart-settings visualization_settings)))
:global-parameters (vals param-id->param)})) |
Create a human-friendly summary of a dashboard. Returns a map of the form: {:description "Some inferred description"} | (defn describe-dashboard
[dashboard-id]
(let [dashboard-summary (dashboard->prompt-data dashboard-id)
summary-with-prompts (merge dashboard-summary
{:description "%%FILL_THIS_DESCRIPTION_IN%%"
:keywords "%%FILL_THESE_KEYWORDS_IN%%"
:questions "%%FILL_THESE_QUESTIONS_IN%%"})
json-str (json/encode summary-with-prompts)
client (-> (llm-client/create-chat-completion)
(llm-client/wrap-parse-json
(fn [{:keys [description keywords questions]}]
{:description (format "Keywords: %s\n\nDescription: %s\n\nQuestions:\n%s"
keywords
description
questions)})))]
(client
{:messages
[{:role "system"
:content "You are a helpful assistant that summarizes dashboards I am generating for my customers by
filling in the missing \"description\", \"keywords\", and \"questions\" keys in a json fragment."}
{:role "assistant"
:content "The \"description\" key is a user friendly description of the dashboard containing up to
two sentences. This description may not be more than 256 characters."}
{:role "assistant"
:content "The \"keywords\" key is 3-5 single-quoted, comma-separated key words
describing the dashboard (e.g. 'keyword1', 'key word'). Keywords might be used to categorize, concisely
describe, or label the entire dashboard."}
{:role "assistant"
:content "The \"questions\" key contains a markdown-formatted hyphenated list of up to 5 questions this
dashboard might help a user answer. Each question should be on its own line."}
{:role "assistant"
:content "The parts you replace are \"%%FILL_THIS_DESCRIPTION_IN%%\", \"%%FILL_THESE_KEYWORDS_IN%%\",
and \"%%FILL_THESE_QUESTIONS_IN%%\"."}
{:role "assistant"
:content "Return only a json object with the \"description\", \"keywords\", and \"questions\" fields and nothing else."}
{:role "user"
:content json-str}]}))) |