mirror of
https://github.com/meta-llama/llama-stack.git
synced 2025-10-05 12:21:52 +00:00
adding GET /prompts/{prompt_id}/versions
Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>
This commit is contained in:
parent
5f3425bb1b
commit
5c02661b79
5 changed files with 147 additions and 1 deletions
51
docs/_static/llama-stack-spec.html
vendored
51
docs/_static/llama-stack-spec.html
vendored
|
@ -3047,6 +3047,49 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/v1/prompts/{prompt_id}/versions": {
|
||||||
|
"get": {
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A ListPromptsResponse containing all versions of the prompt.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ListPromptsResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"$ref": "#/components/responses/BadRequest400"
|
||||||
|
},
|
||||||
|
"429": {
|
||||||
|
"$ref": "#/components/responses/TooManyRequests429"
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"$ref": "#/components/responses/InternalServerError500"
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"$ref": "#/components/responses/DefaultError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Prompts"
|
||||||
|
],
|
||||||
|
"description": "List all versions of a specific prompt.",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "prompt_id",
|
||||||
|
"in": "path",
|
||||||
|
"description": "The identifier of the prompt to list versions for.",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/v1/providers": {
|
"/v1/providers": {
|
||||||
"get": {
|
"get": {
|
||||||
"responses": {
|
"responses": {
|
||||||
|
@ -9976,12 +10019,18 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"description": "Dictionary of prompt variable names and values"
|
"description": "Dictionary of prompt variable names and values"
|
||||||
|
},
|
||||||
|
"is_default": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Boolean indicating whether this version is the default version for this prompt"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": [
|
"required": [
|
||||||
"version",
|
"version",
|
||||||
"prompt_id"
|
"prompt_id",
|
||||||
|
"is_default"
|
||||||
],
|
],
|
||||||
"title": "Prompt",
|
"title": "Prompt",
|
||||||
"description": "A prompt resource representing a stored OpenAI Compatible prompt template in Llama Stack."
|
"description": "A prompt resource representing a stored OpenAI Compatible prompt template in Llama Stack."
|
||||||
|
|
38
docs/_static/llama-stack-spec.yaml
vendored
38
docs/_static/llama-stack-spec.yaml
vendored
|
@ -2132,6 +2132,37 @@ paths:
|
||||||
required: false
|
required: false
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Order'
|
$ref: '#/components/schemas/Order'
|
||||||
|
/v1/prompts/{prompt_id}/versions:
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: >-
|
||||||
|
A ListPromptsResponse containing all versions of the prompt.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ListPromptsResponse'
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/BadRequest400'
|
||||||
|
'429':
|
||||||
|
$ref: >-
|
||||||
|
#/components/responses/TooManyRequests429
|
||||||
|
'500':
|
||||||
|
$ref: >-
|
||||||
|
#/components/responses/InternalServerError500
|
||||||
|
default:
|
||||||
|
$ref: '#/components/responses/DefaultError'
|
||||||
|
tags:
|
||||||
|
- Prompts
|
||||||
|
description: List all versions of a specific prompt.
|
||||||
|
parameters:
|
||||||
|
- name: prompt_id
|
||||||
|
in: path
|
||||||
|
description: >-
|
||||||
|
The identifier of the prompt to list versions for.
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
/v1/providers:
|
/v1/providers:
|
||||||
get:
|
get:
|
||||||
responses:
|
responses:
|
||||||
|
@ -7373,10 +7404,17 @@ components:
|
||||||
type: string
|
type: string
|
||||||
description: >-
|
description: >-
|
||||||
Dictionary of prompt variable names and values
|
Dictionary of prompt variable names and values
|
||||||
|
is_default:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
description: >-
|
||||||
|
Boolean indicating whether this version is the default version for this
|
||||||
|
prompt
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- version
|
- version
|
||||||
- prompt_id
|
- prompt_id
|
||||||
|
- is_default
|
||||||
title: Prompt
|
title: Prompt
|
||||||
description: >-
|
description: >-
|
||||||
A prompt resource representing a stored OpenAI Compatible prompt template
|
A prompt resource representing a stored OpenAI Compatible prompt template
|
||||||
|
|
|
@ -21,6 +21,7 @@ class Prompt(BaseModel):
|
||||||
:param version: Version string (integer start at 1 cast as string, incremented on save)
|
:param version: Version string (integer start at 1 cast as string, incremented on save)
|
||||||
:param prompt_id: Unique identifier formatted as 'pmpt_<48-digit-hash>'
|
:param prompt_id: Unique identifier formatted as 'pmpt_<48-digit-hash>'
|
||||||
:param variables: Dictionary of prompt variable names and values
|
:param variables: Dictionary of prompt variable names and values
|
||||||
|
:param is_default: Boolean indicating whether this version is the default version for this prompt
|
||||||
"""
|
"""
|
||||||
|
|
||||||
prompt: str | None = Field(default=None, description="The system prompt with variable placeholders")
|
prompt: str | None = Field(default=None, description="The system prompt with variable placeholders")
|
||||||
|
@ -29,6 +30,9 @@ class Prompt(BaseModel):
|
||||||
variables: dict[str, str] | None = Field(
|
variables: dict[str, str] | None = Field(
|
||||||
default_factory=dict, description="Variables for dynamic injection using {{variable}} syntax"
|
default_factory=dict, description="Variables for dynamic injection using {{variable}} syntax"
|
||||||
)
|
)
|
||||||
|
is_default: bool = Field(
|
||||||
|
default=False, description="Boolean indicating whether this version is the default version"
|
||||||
|
)
|
||||||
|
|
||||||
@field_validator("prompt_id")
|
@field_validator("prompt_id")
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -158,6 +162,18 @@ class Prompts(Protocol):
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@webmethod(route="/prompts/{prompt_id:path}/versions", method="GET")
|
||||||
|
async def list_prompt_versions(
|
||||||
|
self,
|
||||||
|
prompt_id: str,
|
||||||
|
) -> ListPromptsResponse:
|
||||||
|
"""List all versions of a specific prompt.
|
||||||
|
|
||||||
|
:param prompt_id: The identifier of the prompt to list versions for.
|
||||||
|
:returns: A ListPromptsResponse containing all versions of the prompt.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
@webmethod(route="/prompts/{prompt_id:path}/default-version", method="PUT")
|
@webmethod(route="/prompts/{prompt_id:path}/default-version", method="PUT")
|
||||||
async def set_default_version(
|
async def set_default_version(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -169,6 +169,32 @@ class PromptServiceImpl(Prompts):
|
||||||
for key in keys:
|
for key in keys:
|
||||||
await self.kvstore.delete(key)
|
await self.kvstore.delete(key)
|
||||||
|
|
||||||
|
async def list_prompt_versions(self, prompt_id: str) -> ListPromptsResponse:
|
||||||
|
"""List all versions of a specific prompt."""
|
||||||
|
prefix = f"prompts:v1:{prompt_id}:"
|
||||||
|
keys = await self.kvstore.keys_in_range(prefix, prefix + "\xff")
|
||||||
|
|
||||||
|
default_version = None
|
||||||
|
prompts = []
|
||||||
|
|
||||||
|
for key in keys:
|
||||||
|
data = await self.kvstore.get(key)
|
||||||
|
if key.endswith(":default"):
|
||||||
|
default_version = data
|
||||||
|
else:
|
||||||
|
if data:
|
||||||
|
prompt_obj = self._deserialize_prompt(data)
|
||||||
|
prompts.append(prompt_obj)
|
||||||
|
|
||||||
|
if not prompts:
|
||||||
|
raise ValueError(f"Prompt {prompt_id} not found")
|
||||||
|
|
||||||
|
for prompt in prompts:
|
||||||
|
prompt.is_default = prompt.version == default_version
|
||||||
|
|
||||||
|
prompts.sort(key=lambda x: int(x.version))
|
||||||
|
return ListPromptsResponse(data=prompts)
|
||||||
|
|
||||||
async def set_default_version(self, prompt_id: str, version: str) -> Prompt:
|
async def set_default_version(self, prompt_id: str, version: str) -> Prompt:
|
||||||
"""Set which version of a prompt should be the default (latest)."""
|
"""Set which version of a prompt should be the default (latest)."""
|
||||||
version_key = self._get_version_key(prompt_id, version)
|
version_key = self._get_version_key(prompt_id, version)
|
||||||
|
|
|
@ -100,3 +100,20 @@ class TestPrompts:
|
||||||
response = await store.list_prompts()
|
response = await store.list_prompts()
|
||||||
listed_prompt = response.data[0]
|
listed_prompt = response.data[0]
|
||||||
assert listed_prompt.version == "1" and listed_prompt.prompt == "V1"
|
assert listed_prompt.version == "1" and listed_prompt.prompt == "V1"
|
||||||
|
|
||||||
|
async def test_get_all_prompt_versions(self, store):
|
||||||
|
prompt = await store.create_prompt("V1")
|
||||||
|
await store.update_prompt(prompt.prompt_id, "V2")
|
||||||
|
await store.update_prompt(prompt.prompt_id, "V3")
|
||||||
|
|
||||||
|
versions = (await store.list_prompt_versions(prompt.prompt_id)).data
|
||||||
|
assert len(versions) == 3
|
||||||
|
assert [v.version for v in versions] == ["1", "2", "3"]
|
||||||
|
assert [v.is_default for v in versions] == [False, False, True]
|
||||||
|
|
||||||
|
await store.set_default_version(prompt.prompt_id, "2")
|
||||||
|
versions = (await store.list_prompt_versions(prompt.prompt_id)).data
|
||||||
|
assert [v.is_default for v in versions] == [False, True, False]
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await store.list_prompt_versions("nonexistent")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue