Skip to content

Commit

Permalink
qrencode accepts arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
slimslenderslacks committed Jan 25, 2025
1 parent 761005b commit 0d13e18
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 25 deletions.
17 changes: 12 additions & 5 deletions prompts/examples/qrencode.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
---
name: qrencode
description: Generate QR codes
tools:
- name: qrencode
arguments:
- name: content
description: the content to encode in the QR code
required: true
parameter-values:
content: https://github.com/docker/labs-ai-tools-for-devs
---

# Prompt user
# prompt

Generate a QR code for the content
'https://github.com/docker/labs-ai-tools-for-devs'.
Save the generated image to `qrcode.png`.
Generate a QR code for the content '{{content}}'.
Save the generated image to `/thread/resources/qrcode.png`.
If the command fails, read the man page and try again.
If successful, output the path to the generated image in markdown syntax.

Expand All @@ -16,6 +23,6 @@ If successful, output the path to the generated image in markdown syntax.
After running the above prompt, there should be a file named `qrcode.png` in the current project's host directory.

```bash
open ~/vonwig/altaservice/qrcode.png
open ~/docker/labs-ai-tools-for-devs/qrcode.png
```

2 changes: 1 addition & 1 deletion src/graph.clj
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
(let [[chunk-handler sample] (providers (llm-provider (or (:model metadata) model)))
[c h] (chunk-handler)
request (merge
(dissoc metadata :agent :host-dir :workdir :prompt-format :description :name :parameter-values) ; TODO should we just select relevant keys instead of removing bad ones
(dissoc metadata :agent :host-dir :workdir :prompt-format :description :name :parameter-values :arguments) ; TODO should we just select relevant keys instead of removing bad ones
{:messages messages
:level level}
(when (seq functions) {:tools functions})
Expand Down
1 change: 1 addition & 0 deletions src/jsonrpc/db.clj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
(add {:register ["github:docker/labs-ai-tools-for-devs?path=prompts/examples/explain_dockerfile.md"
"github:docker/labs-ai-tools-for-devs?path=prompts/examples/hello_world.md"]}))

#_{:clj-kondo/ignore [:redefined-var]}
(defn merge [{:keys [registry-content] :as opts}]
(logger/info "adding dynamic prompts" registry-content)
(try
Expand Down
21 changes: 8 additions & 13 deletions src/jsonrpc/server.clj
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@
;; merges client-info capabilities and client protocol-version
(swap! db* merge params)
{:protocol-version "2024-11-05"
:capabilities {:prompts {}
:tools {}}
:capabilities {:prompts {:listChanged true}
:tools {:listChanged true}}
:server-info {:name "docker-mcp-server"
:version "0.0.1"}})

Expand All @@ -96,29 +96,24 @@
(defn entry->prompt-listing [k v _messages]
(merge
{:name (str k)}
(select-keys (:metadata v) [:description])))
(select-keys (:metadata v) [:description :arguments])))

(defmethod lsp.server/receive-request "prompts/list" [_ {:keys [db*]} params]
;; TODO might contain a cursor
(logger/info "prompts/list" params)
(let [prompts
{:prompts (->> (:mcp.prompts/registry @db*)
(mapcat (fn [[k v]] (map (partial entry->prompt-listing k v) (:messages v))))
(mapcat
(fn [[k v]] (map (partial entry->prompt-listing k v) (:messages v))))
(into []))}]
(logger/info prompts)
prompts))

(defmethod lsp.server/receive-request "prompts/get" [_ {:keys [db*]} {:keys [name]}]
;; TODO resolve arguments
(defmethod lsp.server/receive-request "prompts/get" [_ {:keys [db*]} {:keys [name arguments]}]
(logger/info "prompts/get " name)
(let [{:keys [messages metadata] :as entry} (-> @db* :mcp.prompts/registry (get name))]
(let [{:keys [prompt-function metadata]} (-> @db* :mcp.prompts/registry (get name))]
{:description (or (:description metadata) name)
:messages (->> messages
(map (fn [m] (-> m
(update :content (fn [content]
{:type "text"
:text content})))))
(into []))}))
:messages (prompt-function (or arguments {}))}))

(defmethod lsp.server/receive-request "resources/list" [_ _ _]
{:resources []})
Expand Down
36 changes: 30 additions & 6 deletions src/prompts.clj
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,20 @@

(def prompt-file-pattern #".*_(.*)_.*.md")

(defn ->message [{:keys [content] :as m}] (assoc m :content {:text content :type "text"}))

(defn get-prompts
"run extractors and then render prompt templates
returns map of messages, functions, metadata and optionally error"
"run extractors and then render prompt templates (possibly)
parameters
mandatory
either prompts or prompt-content
prompts should be a markdown file
prompts used to be a directory but that's deprecated
optional
user, platform, host-dir - create default facts for template rendering]
parameters - external params bound at rendering time
returns a :schema/prompts-file"
[{:keys [parameters prompts user platform host-dir prompt-content] :as opts}]
(let [{:keys [metadata] :as prompt-data}
(cond
Expand Down Expand Up @@ -184,16 +195,29 @@
parameters
(-> metadata :parameter-values))
renderer (if (= "django" (:prompt-format metadata))
(partial selmer-render (facts m user platform host-dir))
(partial moustache-render prompts (facts m user platform host-dir)))]
(fn [arguments message]
(selmer-render (merge (facts m user platform host-dir) arguments) message))
(fn [arguments message]
(moustache-render prompts (merge (facts m user platform host-dir) arguments) message)))]
((schema/validate :schema/prompts-file)
(-> prompt-data
(update :messages #(map renderer %))
((fn [m] (assoc m :prompt-function (fn [arguments]
(->> (:messages m)
(map (comp ->message (partial renderer arguments)))
(into []))))))
(update :messages #(map (partial renderer {}) %))
(update :metadata dissoc :functions :tools :extractors)
(assoc :functions (->> (or (:tools metadata) (:functions metadata)) (mapcat function-definition)))))))

(comment
(get-prompts {:prompts (fs/file "./prompts/examples/curl.md")})
(get-prompts {:prompts (fs/file "./prompts/examples/generate-dockerfile.md")})
(get-prompts {:prompts (fs/file "./README.md")}))
(get-prompts {:prompts (fs/file "./README.md")})
(=
((:prompt-function (get-prompts {:prompts (fs/file "./prompts/examples/qrencode.md")})) {:content "mycontent"})
[{:role "user",
:content
{:text
"\nGenerate a QR code for the content 'mycontent'.\nSave the generated image to `/thread/resources/qrcode.png`.\nIf the command fails, read the man page and try again.\nIf successful, output the path to the generated image in markdown syntax.",
:type "text"}}]))

0 comments on commit 0d13e18

Please sign in to comment.