diff --git a/.github/workflows/prompts.yml b/.github/workflows/prompts.yml index f866498fb..0546046df 100644 --- a/.github/workflows/prompts.yml +++ b/.github/workflows/prompts.yml @@ -4,8 +4,11 @@ on: pull_request: paths: - 'qdrant-landing/content/**/*.md' - - 'qdrant-landing/layouts/shortcodes/prompt.markdown.md' - - 'qdrant-landing/themes/qdrant-2024/layouts/shortcodes/prompt.html' + # Every shortcode, not just the prompt ones: the Markdown variants are + # what keep prompt bodies out of the agent-facing output, and naming them + # individually is how prompt-index.markdown.md went unguarded. + - 'qdrant-landing/layouts/shortcodes/**' + - 'qdrant-landing/themes/qdrant-2024/layouts/shortcodes/**' - 'automation/prompts/**' - '.github/workflows/prompts.yml' # A skill link breaks when a skill is renamed or unpublished in qdrant/skills, diff --git a/AGENTS.md b/AGENTS.md index 5eacc582d..2e8d99b35 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -98,9 +98,9 @@ automation/prompts/check-skill-links.sh # skill links resolve, needs network automation/snippets/generate-md.py # if you touched snippets, then commit the result ``` -Run `git add -A` or `git add :/` from anywhere other than the repository root. -Plain `git add .` inside `qdrant-landing/` silently misses changes to -`automation/` and `.github/`. +When you are not at the repository root, stage with `git add -A` or +`git add :/`. Plain `git add .` inside `qdrant-landing/` silently misses +changes to `automation/` and `.github/`. ## Two traps in the templates diff --git a/automation/prompts/README.md b/automation/prompts/README.md index efaadf455..93c8e95b9 100644 --- a/automation/prompts/README.md +++ b/automation/prompts/README.md @@ -75,6 +75,19 @@ does. That split is why titles stay short, and why the type signal is consistent across every prompt rather than depending on each author phrasing it the same way. +## Formatting a prompt body + +**Do not hard-wrap prose.** Write each paragraph as one long line and let the +page wrap it. The element renders the body with `white-space: pre-wrap`, so any +line breaks you type are preserved, and a body wrapped at 80 columns keeps those +breaks in a content column that is narrower than that. `start-building` is the +exception: its numbered steps and indented commands are structure, so its line +breaks are content. + +**A body can contain anything, including fenced blocks.** The shortcode passes +it to Chroma as a value rather than re-parsing it as markdown, so a prompt that +includes a YAML or JSON snippet renders correctly. + ## Two rules that break silently **Prompt bodies must never reach a built `index.md`.** Those files are consumed diff --git a/automation/prompts/check-prompts.sh b/automation/prompts/check-prompts.sh index 355586149..9d4539981 100755 --- a/automation/prompts/check-prompts.sh +++ b/automation/prompts/check-prompts.sh @@ -9,8 +9,11 @@ # body, so the only way a body reaches index.md is an author pasting it as # a fenced block instead of using the shortcode. That is a source-level # mistake, so it is caught in the source. -# 2. The Markdown variant of the shortcode still drops the body. Rule 1 is -# only equivalent to "no body in index.md" while this holds. +# 2. No Markdown variant renders the body. Rule 1 is only equivalent to "no +# body in index.md" while this holds, and it has to cover every template +# that can reach a prompt's content, not just the element's. The index +# ranges the same pages, so a body added there lands in the built +# index.md exactly the same way. # 3. Every prompt's declared `page:` really includes it. The prompt files live # in one folder and cannot know who includes them, so the declaration is # what the index trusts. This also catches a prompt that is written but @@ -28,7 +31,12 @@ repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" public_dir="${1:-}" prompts_dir="$repo_root/qdrant-landing/content/documentation/headless/prompts" content_dir="$repo_root/qdrant-landing/content" -md_shortcode="$repo_root/qdrant-landing/layouts/shortcodes/prompt.markdown.md" +# Every Markdown-output template that can reach a prompt page. Add to this list +# rather than writing a new check if another one appears. +md_shortcodes=( + "$repo_root/qdrant-landing/layouts/shortcodes/prompt.markdown.md" + "$repo_root/qdrant-landing/layouts/shortcodes/prompt-index.markdown.md" +) failures=0 @@ -42,12 +50,15 @@ if [[ ! -d "$prompts_dir" ]]; then exit 0 fi -# --- rule 2: the Markdown variant must not render the prompt body --- -if [[ ! -f "$md_shortcode" ]]; then - fail "missing $md_shortcode: without it, prompt bodies reach the agent-facing Markdown" -elif grep -qE '\.(RawContent|Content|Inner)\b' "$md_shortcode"; then - fail "$md_shortcode renders the prompt body; it must emit only the skill pointer" -fi +# --- rule 2: no Markdown variant may render the prompt body --- +for md_shortcode in "${md_shortcodes[@]}"; do + rel="${md_shortcode#"$repo_root"/}" + if [[ ! -f "$md_shortcode" ]]; then + fail "missing $rel: without it, prompt bodies reach the agent-facing Markdown" + elif grep -qE '\.(RawContent|Content|Inner)\b' "$md_shortcode"; then + fail "$rel renders the prompt body; it must emit only titles, pages, and skill pointers" + fi +done shopt -s nullglob checked=0 diff --git a/qdrant-landing/content/documentation/agentic-tools/_index.md b/qdrant-landing/content/documentation/agentic-tools/_index.md index ee9d25cbe..539a9ca0d 100644 --- a/qdrant-landing/content/documentation/agentic-tools/_index.md +++ b/qdrant-landing/content/documentation/agentic-tools/_index.md @@ -13,16 +13,17 @@ Use them to give your agent task-specific guidance, troubleshoot existing deploy ## Start Building -If you're new to Qdrant, paste this into your coding assistant. +If you're new to Qdrant, the Start building on Qdrant prompt takes your coding assistant from an empty project to a working search query. It stands up a local instance, installs the client with local embeddings, adds the [Qdrant Advisor](/documentation/agentic-tools/skills/#the-qdrant-advisor) skill, and then builds against your own use case. {{< prompt "start-building" >}} -Nothing in those four steps needs an account. +None of that needs an account. Qdrant runs in Docker and [FastEmbed](/documentation/fastembed/fastembed-quickstart/) generates embeddings on your machine, so you can go from nothing to a working search query without signing up for anything. -Step 4 does the work that matters. -A wrong collection configuration rarely fails loudly in vector search: a mismatched distance metric or a missing payload index returns plausible results and quietly costs you relevance, so it's worth making your agent commit to those choices out loud before it writes code. +The part that matters most is the collection configuration. +A wrong one rarely fails loudly in vector search: a mismatched distance metric or a missing payload index returns plausible results and quietly costs you relevance. +The prompt is written to make your assistant ask what you are building, then commit to those choices out loud before it writes any code. ## Agent Skills diff --git a/qdrant-landing/content/documentation/agentic-tools/prompts.md b/qdrant-landing/content/documentation/agentic-tools/prompts.md index 05b272a42..858b9d6bb 100644 --- a/qdrant-landing/content/documentation/agentic-tools/prompts.md +++ b/qdrant-landing/content/documentation/agentic-tools/prompts.md @@ -12,6 +12,6 @@ Qdrant documentation includes short, ready-to-use prompts on the pages where the Each prompt is collapsed by default, requires no additional input, and tells your assistant which [agent skill](/documentation/agentic-tools/skills/) to load. The prompt defines the task; the skill provides the Qdrant-specific guidance needed to complete it. -This page lists all available prompts. Follow a link to open the prompt alongside the documentation that provides its context. +This page lists all available prompts. Follow a link to jump to the prompt on the page that provides its context. {{< prompt-index >}} diff --git a/qdrant-landing/content/documentation/headless/prompts/design-a-collection.md b/qdrant-landing/content/documentation/headless/prompts/design-a-collection.md index 2ae1470f4..0391021e9 100644 --- a/qdrant-landing/content/documentation/headless/prompts/design-a-collection.md +++ b/qdrant-landing/content/documentation/headless/prompts/design-a-collection.md @@ -1,15 +1,8 @@ --- title: "Design a collection" -skill: qdrant-multitenancy +# No skill: on purpose. The catalog has no collection-design skill, and +# qdrant-multitenancy would label the whole prompt as a tenancy prompt in +# the index. The body still links it where it is actually relevant. page: /documentation/manage-data/collections/ --- -Help me design a Qdrant collection for my data. Ask me what I am searching -over, roughly how many vectors I expect, which embedding model I am using, and -what I will filter on, before you write any code. Decide first whether this -should be one collection or many, reading -https://skills.qdrant.tech/qdrant-multitenancy/SKILL.md, since that choice -drives the index layout. Then derive the vector size from the model rather than -hardcoding it, name the distance metric the model was trained for and say why -you picked it, and add a payload index for every field I will filter on. Finish -by telling me which of these I cannot change later without recreating the -collection. +Help me design a Qdrant collection for my data. Ask me what I am searching over, roughly how many vectors I expect, which embedding model I am using, and what I will filter on, before you write any code. Decide first whether this should be one collection or many, reading https://skills.qdrant.tech/qdrant-multitenancy/SKILL.md, since that choice drives the index layout. Then derive the vector size from the model rather than hardcoding it, name the distance metric the model was trained for and say why you picked it, and add a payload index for every field I will filter on. Finish by telling me which of these I cannot change later without recreating the collection. diff --git a/qdrant-landing/content/documentation/headless/prompts/diagnose-memory-usage.md b/qdrant-landing/content/documentation/headless/prompts/diagnose-memory-usage.md index 76f1aa006..7a1c35b8e 100644 --- a/qdrant-landing/content/documentation/headless/prompts/diagnose-memory-usage.md +++ b/qdrant-landing/content/documentation/headless/prompts/diagnose-memory-usage.md @@ -3,11 +3,4 @@ title: "Diagnose high memory usage" skill: qdrant-performance-optimization/memory-usage-optimization page: /documentation/ops-optimization/optimize/ --- -My Qdrant memory usage is higher than I expected, or a node was killed for -running out of memory. Read -https://skills.qdrant.tech/qdrant-performance-optimization/memory-usage-optimization/SKILL.md -first, then ask me for my collection configuration before proposing anything. -Tell me which component is actually consuming the memory, whether that is the -vectors, the HNSW index, or the payload indexes, and give me the fixes in order -of impact. Say which ones need a reindex, and what recall I would lose if I -quantize. +My Qdrant memory usage is higher than I expected, or a node was killed for running out of memory. Read https://skills.qdrant.tech/qdrant-performance-optimization/memory-usage-optimization/SKILL.md first, then ask me for my collection configuration before proposing anything. Tell me which component is actually consuming the memory, whether that is the vectors, the HNSW index, or the payload indexes, and give me the fixes in order of impact. Say which ones need a reindex, and what recall I would lose if I quantize. diff --git a/qdrant-landing/content/documentation/headless/prompts/review-before-launch.md b/qdrant-landing/content/documentation/headless/prompts/review-before-launch.md index 4d9cb7808..1641b420c 100644 --- a/qdrant-landing/content/documentation/headless/prompts/review-before-launch.md +++ b/qdrant-landing/content/documentation/headless/prompts/review-before-launch.md @@ -3,10 +3,4 @@ title: "Review my deployment" skill: qdrant-sizing page: /documentation/production-checklist/ --- -Review my Qdrant deployment before I put production traffic on it. Read -https://skills.qdrant.tech/qdrant-sizing/SKILL.md, then ask me for my -collection configuration, my expected vector count and query rate, and the -hardware I have provisioned. Tell me which of my settings will not survive real -load, ordered by how much it would hurt, and separate what I can change later -from what needs the collection recreated. Where my numbers do not support a -conclusion, say what to measure rather than guessing. +Review my Qdrant deployment before I put production traffic on it. Read https://skills.qdrant.tech/qdrant-sizing/SKILL.md, then ask me for my collection configuration, my expected vector count and query rate, and the hardware I have provisioned. Tell me which of my settings will not survive real load, ordered by how much it would hurt, and separate what I can change later from what needs the collection recreated. Where my numbers do not support a conclusion, say what to measure rather than guessing. diff --git a/qdrant-landing/content/documentation/headless/prompts/set-up-monitoring.md b/qdrant-landing/content/documentation/headless/prompts/set-up-monitoring.md index e6fab07fa..cd7bdbb9e 100644 --- a/qdrant-landing/content/documentation/headless/prompts/set-up-monitoring.md +++ b/qdrant-landing/content/documentation/headless/prompts/set-up-monitoring.md @@ -3,9 +3,4 @@ title: "Set up monitoring" skill: qdrant-monitoring/setup page: /documentation/ops-monitoring/monitoring/ --- -Help me set up monitoring for my Qdrant deployment. Read -https://skills.qdrant.tech/qdrant-monitoring/setup/SKILL.md first, then ask me -whether I am self-hosted, on Qdrant Cloud, or on Hybrid Cloud, since the scrape -setup differs. Give me the Prometheus scrape config, the health probes worth -wiring up, and the three or four alerts that would actually have caught a real -incident. Tell me which metrics to ignore. +Help me set up monitoring for my Qdrant deployment. Read https://skills.qdrant.tech/qdrant-monitoring/setup/SKILL.md first, then ask me whether I am self-hosted, on Qdrant Cloud, or on Hybrid Cloud, since the scrape setup differs. Give me the Prometheus scrape config, the health probes worth wiring up, and the three or four alerts that would actually have caught a real incident. Tell me which metrics to ignore. diff --git a/qdrant-landing/content/documentation/manage-data/collections.md b/qdrant-landing/content/documentation/manage-data/collections.md index d1666d80e..9bfd9664c 100644 --- a/qdrant-landing/content/documentation/manage-data/collections.md +++ b/qdrant-landing/content/documentation/manage-data/collections.md @@ -29,7 +29,7 @@ Qdrant supports these most popular types of metrics: In addition to metrics and vector size, each collection uses its own set of parameters that controls collection optimization, index construction, and vacuum. These settings can be changed at any time by a corresponding request. -If you would rather have an agent design this with you, the following prompt asks it for your data and query shape first, then commits to a vector configuration and the payload indexes to create. +To hand this to an agent instead, the Design a collection prompt makes it ask about your data and query shape first, then commit to a vector configuration and the payload indexes to create. {{< prompt "design-a-collection" >}} diff --git a/qdrant-landing/content/documentation/ops-monitoring/monitoring.md b/qdrant-landing/content/documentation/ops-monitoring/monitoring.md index 1784c4aa0..9289d5cf8 100644 --- a/qdrant-landing/content/documentation/ops-monitoring/monitoring.md +++ b/qdrant-landing/content/documentation/ops-monitoring/monitoring.md @@ -21,7 +21,7 @@ The integration with Qdrant is easy to [configure](https://prometheus.io/docs/prometheus/latest/getting_started/#configure-prometheus-to-monitor-the-sample-targets) with Prometheus and Grafana. -If you would rather have an agent handle this, use the following prompt to select the appropriate configuration for your deployment type and recommend relevant alerts. +If you would rather have an agent handle this, the Set up monitoring prompt asks it to select the right configuration for your deployment type and recommend the alerts worth wiring up. {{< prompt "set-up-monitoring" >}} diff --git a/qdrant-landing/content/documentation/ops-optimization/optimize.md b/qdrant-landing/content/documentation/ops-optimization/optimize.md index fd6c16a85..e6e797425 100644 --- a/qdrant-landing/content/documentation/ops-optimization/optimize.md +++ b/qdrant-landing/content/documentation/ops-optimization/optimize.md @@ -25,7 +25,7 @@ This guide will walk you three main optimization strategies: This page covers the memory parameter introduced in Qdrant v1.19. If you're using an older version, see the Legacy Settings section for how to map the new parameter to the old ones. -If you would rather have an agent work through this with you, the following prompt asks it to find which component is actually using the memory before it suggests any changes. +An agent can work through this with you. The Diagnose high memory usage prompt makes it find which component is actually using the memory before it suggests any changes. {{< prompt "diagnose-memory-usage" >}} diff --git a/qdrant-landing/content/documentation/production-checklist.md b/qdrant-landing/content/documentation/production-checklist.md index 4c128be34..3a8676982 100644 --- a/qdrant-landing/content/documentation/production-checklist.md +++ b/qdrant-landing/content/documentation/production-checklist.md @@ -10,7 +10,7 @@ weight: 147 A practical checklist to ensure Qdrant is optimized, stable, and ready to handle real-world load. -If you would rather have an agent run through this with you, use the following prompt to get a prioritized list of what would break first under real load. +An agent can run the checklist with you. The Review my deployment prompt asks it for a prioritized list of what would break first under real load. {{< prompt "review-before-launch" >}} diff --git a/qdrant-landing/layouts/shortcodes/prompt-index.markdown.md b/qdrant-landing/layouts/shortcodes/prompt-index.markdown.md index d683c069b..4ad6b6e74 100644 --- a/qdrant-landing/layouts/shortcodes/prompt-index.markdown.md +++ b/qdrant-landing/layouts/shortcodes/prompt-index.markdown.md @@ -7,6 +7,10 @@ Keep in step with prompt-index.html, which emits table markup instead of pipes because shortcode output is not re-parsed as markdown. + + Page links are absolute and index.md-suffixed to match every other link in + this output, which single.markdown.md rewrites that way. A bare site path + would be the one column an agent reading this table could not resolve. */ -}} {{- $section := site.GetPage "documentation/headless/prompts" -}} {{- if not $section -}} @@ -15,5 +19,5 @@ | Prompt | Page | Agent skill | |---|---|---| {{ range $section.RegularPages.ByTitle -}} -| {{ .Title }} | {{ with .Params.page }}{{ . }}{{ else }}None{{ end }} | {{ with .Params.skill }}https://skills.qdrant.tech/{{ . }}/SKILL.md{{ else }}None{{ end }} | +| {{ .Title }} | {{ with .Params.page }}{{ with site.GetPage . }}{{ .Permalink }}index.md{{ else }}{{ . }}{{ end }}{{ else }}None{{ end }} | {{ with .Params.skill }}https://skills.qdrant.tech/{{ . }}/SKILL.md{{ else }}None{{ end }} | {{ end -}} diff --git a/qdrant-landing/themes/qdrant-2024/assets/css/components/_prompt.scss b/qdrant-landing/themes/qdrant-2024/assets/css/components/_prompt.scss index 236925e8a..8d1a2f1cf 100644 --- a/qdrant-landing/themes/qdrant-2024/assets/css/components/_prompt.scss +++ b/qdrant-landing/themes/qdrant-2024/assets/css/components/_prompt.scss @@ -1,10 +1,22 @@ @use '../helpers/functions' as *; +// Both themes are declared here so a palette change is a one-block edit. The +// light values were previously written as literals at the use site, which is +// how a palette silently stops being the palette. $prompt-surface: $neutral-20; $prompt-border: $neutral-40; $prompt-text: $neutral-98; $prompt-text-muted: $neutral-70; $prompt-accent: $primary-60; +// The body block sits deeper than the card. Without this it renders the same +// $neutral-20 as the card and the prompt reads as loose monospace in a box. +$prompt-block-surface: $neutral-10; + +$prompt-surface-light: $neutral-98; +$prompt-border-light: $neutral-94; +$prompt-text-light: $neutral-10; +$prompt-text-muted-light: $neutral-50; +$prompt-accent-light: $primary-40; .prompt { background: $prompt-surface; @@ -79,9 +91,24 @@ $prompt-accent: $primary-60; padding: 0 pxToRem(16) pxToRem(16); } - // The fenced block Chroma emits inside the body. + // The block Chroma emits inside the body. .highlight { margin: 0; + background: $prompt-block-surface; + } + + // A prompt is prose, not code. Its line breaks come from how the author + // wrapped the source file, so a fixed-width
 clips every line at any
+  // window narrower than the wrap width instead of reflowing. Sideways
+  // scrolling is a fair bargain for code and a bad one for a paragraph.
+  // pre-wrap keeps the deliberate line structure in prompts that have one.
+  .highlight > pre {
+    white-space: pre-wrap;
+    overflow-wrap: break-word;
+    // copy-code.js absolutely positions its button at the top right of
+    // .highlight. Wrapped text now reaches the full width, so the first line
+    // would run underneath it.
+    padding-right: pxToRem(56);
   }
 
   &__skill {
@@ -99,9 +126,9 @@ $prompt-accent: $primary-60;
   }
 
   [data-theme='light'] & {
-    background: $neutral-98;
-    border-color: $neutral-94;
-    border-left-color: $primary-40;
+    background: $prompt-surface-light;
+    border-color: $prompt-border-light;
+    border-left-color: $prompt-accent-light;
   }
 }
 
@@ -109,25 +136,25 @@ $prompt-accent: $primary-60;
 // lands in the descendant position, where it can never match, because the
 // theme attribute sits on .
 [data-theme='light'] .prompt__summary {
-  color: $neutral-10;
+  color: $prompt-text-light;
 }
 
 [data-theme='light'] .prompt__summary::before {
-  border-right-color: $primary-40;
-  border-bottom-color: $primary-40;
+  border-right-color: $prompt-accent-light;
+  border-bottom-color: $prompt-accent-light;
 }
 
 [data-theme='light'] .prompt__summary:hover {
-  color: $primary-40;
+  color: $prompt-accent-light;
 }
 
 [data-theme='light'] .prompt__skill,
 [data-theme='light'] .prompt__kind {
-  color: $neutral-50;
+  color: $prompt-text-muted-light;
 }
 
 [data-theme='light'] .prompt__kind {
-  border-right-color: $neutral-94;
+  border-right-color: $prompt-border-light;
 }
 
 @media (prefers-reduced-motion: reduce) {
diff --git a/qdrant-landing/themes/qdrant-2024/layouts/shortcodes/prompt.html b/qdrant-landing/themes/qdrant-2024/layouts/shortcodes/prompt.html
index 51ca27bc9..5b162db80 100644
--- a/qdrant-landing/themes/qdrant-2024/layouts/shortcodes/prompt.html
+++ b/qdrant-landing/themes/qdrant-2024/layouts/shortcodes/prompt.html
@@ -3,10 +3,15 @@
 
   Usage: {{< prompt "set-up-monitoring" >}}
 
-  The prompt file's body is plain text. This template wraps it in a fenced
-  block and runs it through markdownify so Chroma produces a real
-  `.highlight > pre`, which copy-code.js finds and adds a copy button to. That
-  is why this element needs no JavaScript of its own.
+  The prompt file's body is plain text. `highlight` hands it to Chroma as a
+  value, producing a real `.highlight > pre`, which copy-code.js finds and adds
+  a copy button to. That is why this element needs no JavaScript of its own.
+
+  It is deliberately not wrapped in a fence and run through markdownify. A body
+  containing its own ``` would close that outer fence early, truncating the
+  prompt and spilling the rest of it onto the page as loose markdown, with a
+  clean build and a green check. `highlight` never re-parses the body, so a
+  prompt can contain any characters at all.
 
   The Markdown output format has its own variant, prompt.markdown.md, which
   deliberately drops the body so an agent reading index.md is not handed an
@@ -15,7 +20,7 @@
 {{- $id := .Get 0 -}}
 {{- $p := site.GetPage (printf "documentation/headless/prompts/%s" $id) -}}
 {{- if not $p -}}
-  {{- errorf "prompt: no prompt file found for id %q (looked in content/documentation/headless/prompts/). Called from %s" $id .Page.File.Path -}}
+  {{- errorf "prompt: no prompt file found for id %q (looked in content/documentation/headless/prompts/). Called from %s" $id .Page.RelPermalink -}}
 {{- end -}}
 
@@ -27,7 +32,7 @@ {{ $p.Title }}
- {{ printf "```text\n%s\n```" (trim $p.RawContent "\n") | markdownify }} + {{ highlight (trim $p.RawContent "\n") "text" "" }} {{- with $p.Params.skill }}

Uses the