PromptCue - Classify and enrich prompts with routing cues for LLM pipelines
Project description
PromptCue — Prompt Intent Classifier for LLM Pipelines
PromptCue classifies the intent behind a natural-language prompt and returns structured routing cues — telling your LLM pipeline, RAG system, or query router not just what the user asked, but how it should be answered: retrieve, reason, compare, enumerate, check recency, or ask for clarification.
How it works
PromptCue uses a cascade classifier:
- Deterministic pass — scores the query against a YAML registry of query types using trigger-phrase matching and vocabulary overlap. Fast, zero ML dependencies, returns immediately when confidence is high.
- Semantic fallback — when the deterministic result is ambiguous or below threshold,
sentence-level embeddings (
all-MiniLM-L6-v2) re-score the query against example sentences per type. Activates automatically whensentence-transformersis installed.
The result is a Pydantic model (PromptCueQueryObject) carrying the classification, confidence,
scope, routing hints, action directives, and any enrichment you have enabled.
Requirements
- Python 3.13+
- Core dependencies:
pydantic,PyYAML,numpy(always installed) - All ML/NLP components are optional — the package installs and runs without them
Install
Core install — deterministic classifier only, no ML dependencies:
pip install promptcue
With semantic scoring (sentence-transformers):
pip install "promptcue[semantic]"
With language detection (langdetect):
pip install "promptcue[detection]"
With linguistic enrichment (spaCy):
pip install "promptcue[linguistic]"
python -m spacy download en_core_web_sm
With keyword extraction (KeyBERT):
pip install "promptcue[keywords]"
With everything:
pip install "promptcue[all]"
python -m spacy download en_core_web_sm
Development install (editable, with test and lint tools):
pip install -e ".[dev]"
Quick start
Basic — no ML dependencies required
from promptcue import PromptCueAnalyzer
analyzer = PromptCueAnalyzer()
result = analyzer.analyze('Compare Aurora and OpenSearch for RAG on AWS')
print(result.primary_query_type) # comparison
print(result.scope) # comparative
print(result.confidence) # 0.9
print(result.routing_hints) # {'needs_retrieval': True, 'needs_reasoning': True, ...}
print(result.action_hints) # {'should_compare': True, ...}
With semantic scoring — requires pip install "promptcue[semantic]"
Semantic scoring is enabled automatically when sentence-transformers is installed.
Call warm_up() at startup to pre-load the model and avoid first-query latency.
from promptcue import PromptCueAnalyzer
analyzer = PromptCueAnalyzer()
analyzer.warm_up() # loads ~90 MB model once; cached after first download
result = analyzer.analyze('Should we use DynamoDB or RDS for a high-read catalog?')
print(result.primary_query_type) # recommendation
print(result.classification_basis) # semantic_similarity
print(result.confidence) # 0.25
With full enrichment
from promptcue import PromptCueAnalyzer, PromptCueConfig
analyzer = PromptCueAnalyzer(PromptCueConfig(
enable_language_detection = True, # requires promptcue[detection]
enable_linguistic_extraction = True, # requires promptcue[linguistic]
enable_keyword_extraction = True, # requires promptcue[keywords]
))
analyzer.warm_up()
result = analyzer.analyze(
'How do I set up a VPC with private subnets and NAT gateway step by step?'
)
print(result.language) # en
print(result.main_verbs) # ['set']
print(result.noun_phrases) # ['a VPC', 'private subnets', 'NAT gateway']
print(result.keywords) # [PromptCueKeyword(text='vpc private subnets', weight=0.72, ...), ...]
print(result.entities) # [] (no named entities in this query)
Full JSON output
print(result.model_dump_json(indent=2))
Query types
PromptCue ships with a default registry of 9 query types:
| Label | Scope | Description |
|---|---|---|
lookup |
focused | Factual question with a single direct answer |
comparison |
comparative | Asks to compare two or more options |
recommendation |
focused | Asks for a decision or suggestion given constraints |
troubleshooting |
focused | Diagnosing or fixing a problem |
procedure |
focused | Step-by-step instructions for a task |
analysis |
exploratory | Deep evaluation of a system, architecture, or decision |
coverage |
broad | Broad overview or "tell me everything" request |
update |
focused | Latest news, releases, or changes |
chitchat |
focused | Social or conversational, not a knowledge query |
You can replace or extend the registry by pointing PromptCueConfig.registry_path at your
own YAML file — the schema is documented in src/promptcue/data/query_types.yaml.
Public API
PromptCueAnalyzer
PromptCueAnalyzer(config: PromptCueConfig | None = None)
| Method | Description |
|---|---|
.analyze(text: str) -> PromptCueQueryObject |
Analyze a query and return structured result |
.warm_up() -> None |
Pre-load all enabled models at startup |
PromptCueConfig fields
| Field | Type | Default | Description |
|---|---|---|---|
registry_path |
Path | None |
None |
Custom YAML registry path; uses bundled default when None |
similarity_threshold |
float |
0.55 |
Minimum score for a deterministic match to be accepted |
semantic_similarity_threshold |
float |
0.20 |
Minimum score for a semantic match to be accepted |
ambiguity_margin |
float |
0.08 |
Min gap between top-2 scores before clarification is flagged |
semantic_fallback_threshold |
float |
0.75 |
Deterministic score above which the semantic pass is skipped |
enable_semantic_scoring |
bool |
auto | True when sentence-transformers is installed, else False |
embedding_model |
str |
all-MiniLM-L6-v2 |
HuggingFace model name for semantic scoring |
enable_language_detection |
bool |
False |
Detect BCP-47 language code; requires promptcue[detection] |
enable_linguistic_extraction |
bool |
False |
Extract verbs, noun phrases, named entities; requires promptcue[linguistic] |
enable_keyword_extraction |
bool |
False |
Extract keyphrases via KeyBERT; requires promptcue[keywords] |
max_keywords |
int |
8 |
Maximum number of keyphrases to extract |
spacy_model |
str |
en_core_web_sm |
spaCy model name for linguistic extraction |
PromptCueQueryObject fields
| Field | Type | Description |
|---|---|---|
schema_version |
str |
Output schema version ("1.0") |
input_text |
str |
Original query as provided by the caller |
normalized_text |
str |
Unicode-normalised, whitespace-collapsed query |
language |
str |
BCP-47 language code ("en") or "unknown" when detection is off |
primary_query_type |
str |
Top classified query type label, or "unknown" |
classification_basis |
str |
How the result was reached: label_match, trigger_match, word_overlap, semantic_similarity, below_threshold |
candidate_query_types |
list[PromptCueCandidate] |
All types ranked by score |
confidence |
float |
Score of the top candidate (0.0–1.0) |
ambiguity_score |
float |
How close the top-2 candidates are (0.0 = clear, 1.0 = identical) |
scope |
str |
Query scope: broad, focused, comparative, exploratory, or unknown |
main_verbs |
list[str] |
Root verbs extracted by spaCy (empty when enrichment is off) |
noun_phrases |
list[str] |
Noun chunks extracted by spaCy (empty when enrichment is off) |
named_entities |
list[str] |
Named entity surface texts, plain strings (backward compat) |
entities |
list[PromptCueEntity] |
Named entities with text and entity_type (spaCy label) |
keywords |
list[PromptCueKeyword] |
Keyphrases with text, weight, and kind from KeyBERT |
routing_hints |
dict[str, bool] |
needs_retrieval, needs_reasoning, needs_current_info, needs_clarification |
action_hints |
dict[str, bool] |
Response-generation directives: should_survey, should_enumerate, should_compare, should_direct_answer, should_check_recency, should_clarify, should_respond_conversationally |
constraints |
list[str] |
Reserved for future use |
Development
git clone https://github.com/informity/informity-promptcue.git
cd informity-promptcue
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev,semantic,linguistic,keywords,detection]"
python -m spacy download en_core_web_sm
pytest
ruff check src/ tests/ examples/
Contributing
See CONTRIBUTING.md.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file promptcue-0.1.1.tar.gz.
File metadata
- Download URL: promptcue-0.1.1.tar.gz
- Upload date:
- Size: 29.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
517adf6450608d035ce88ba8e52863368b9d172c692adb7d0e98ac11f23c5757
|
|
| MD5 |
ab13d58224987ebd6c7d8887dd199da8
|
|
| BLAKE2b-256 |
40e56b55856a321b73a7faf279db4956bbd99c2910411fead772a2f350b8d9d9
|
Provenance
The following attestation bundles were made for promptcue-0.1.1.tar.gz:
Publisher:
publish.yml on informity/informity-promptcue
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
promptcue-0.1.1.tar.gz -
Subject digest:
517adf6450608d035ce88ba8e52863368b9d172c692adb7d0e98ac11f23c5757 - Sigstore transparency entry: 1170440049
- Sigstore integration time:
-
Permalink:
informity/informity-promptcue@7930d7639e67d93500829fe8f1dc944d42af5803 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/informity
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7930d7639e67d93500829fe8f1dc944d42af5803 -
Trigger Event:
push
-
Statement type:
File details
Details for the file promptcue-0.1.1-py3-none-any.whl.
File metadata
- Download URL: promptcue-0.1.1-py3-none-any.whl
- Upload date:
- Size: 27.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f6b24ba5cd55ac84954e39986c9dcc0f3eb120381d9b6c185534c8fc25823c7
|
|
| MD5 |
badf246e509ea7a39571ff6af20e3280
|
|
| BLAKE2b-256 |
dffa8cbc5c36d2cd000acc763614e86651a8a4a37d03888c14dd6493254c5419
|
Provenance
The following attestation bundles were made for promptcue-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on informity/informity-promptcue
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
promptcue-0.1.1-py3-none-any.whl -
Subject digest:
6f6b24ba5cd55ac84954e39986c9dcc0f3eb120381d9b6c185534c8fc25823c7 - Sigstore transparency entry: 1170440087
- Sigstore integration time:
-
Permalink:
informity/informity-promptcue@7930d7639e67d93500829fe8f1dc944d42af5803 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/informity
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7930d7639e67d93500829fe8f1dc944d42af5803 -
Trigger Event:
push
-
Statement type: