From 539949065e06d552654164d5fd30aca91719b931 Mon Sep 17 00:00:00 2001 From: Dustin Ngo Date: Tue, 17 Dec 2024 17:41:56 -0500 Subject: [PATCH 1/5] Add PromptVersion query --- app/schema.graphql | 44 ++++++++++ src/phoenix/server/api/queries.py | 86 ++++++++++++++++++- src/phoenix/server/api/types/Prompt.py | 2 + src/phoenix/server/api/types/PromptVersion.py | 35 ++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 src/phoenix/server/api/types/PromptVersion.py diff --git a/app/schema.graphql b/app/schema.graphql index a9e7dcbc7f..a0054357f9 100644 --- a/app/schema.graphql +++ b/app/schema.graphql @@ -1402,6 +1402,49 @@ type PromptResponse { response: String } +enum PromptTemplateFormat { + MUSTACHE + FSTRING +} + +enum PromptTemplateType { + TEXT + JSON +} + +type PromptVersion implements Node { + """The Globally Unique ID of this object""" + id: GlobalID! + user: String + description: String! + templateType: PromptTemplateType! + templateFormat: PromptTemplateFormat! + template: JSON! + invocationParameters: JSON + tools: JSON + outputSchema: JSON + modelName: String! + modelProvider: String! +} + +"""A connection to a list of items.""" +type PromptVersionConnection { + """Pagination data for this connection""" + pageInfo: PageInfo! + + """Contains the nodes in this connection""" + edges: [PromptVersionEdge!]! +} + +"""An edge in a connection.""" +type PromptVersionEdge { + """A cursor for use in pagination""" + cursor: String! + + """The item at the end of the edge""" + node: PromptVersion! +} + type Query { modelProviders: [GenerativeProvider!]! models(input: ModelsInput = null): [GenerativeModel!]! @@ -1420,6 +1463,7 @@ type Query { node(id: GlobalID!): Node! viewer: User prompts(first: Int = 50, last: Int, after: String, before: String): PromptConnection! + promptVersions(first: Int = 50, last: Int, after: String, before: String): PromptVersionConnection! clusters(clusters: [ClusterInput!]!): [Cluster!]! hdbscanClustering( """Event ID of the coordinates""" diff --git a/src/phoenix/server/api/queries.py b/src/phoenix/server/api/queries.py index 74fed3c521..9ec863dd88 100644 --- a/src/phoenix/server/api/queries.py +++ b/src/phoenix/server/api/queries.py @@ -80,6 +80,11 @@ from phoenix.server.api.types.Project import Project from phoenix.server.api.types.ProjectSession import ProjectSession, to_gql_project_session from phoenix.server.api.types.Prompt import Prompt +from phoenix.server.api.types.PromptVersion import ( + PromptTemplateFormat, + PromptTemplateType, + PromptVersion, +) from phoenix.server.api.types.SortDir import SortDir from phoenix.server.api.types.Span import Span, to_gql_span from phoenix.server.api.types.SystemApiKey import SystemApiKey @@ -580,7 +585,7 @@ async def viewer(self, info: Info[Context, None]) -> Optional[User]: return to_gql_user(user) @strawberry.field - def prompts( + async def prompts( self, info: Info[Context, None], first: Optional[int] = 50, @@ -612,6 +617,85 @@ def prompts( args=args, ) + @strawberry.field + async def prompt_versions( + self, + info: Info[Context, None], + first: Optional[int] = 50, + last: Optional[int] = UNSET, + after: Optional[CursorString] = UNSET, + before: Optional[CursorString] = UNSET, + ) -> Connection[PromptVersion]: + args = ConnectionArgs( + first=first, + after=after if isinstance(after, CursorString) else None, + last=last, + before=before if isinstance(before, CursorString) else None, + ) + + dummy_data = [ + PromptVersion( + id_attr=2, + user="alice", + description="A dummy prompt version", + template_type=PromptTemplateType.TEXT, + template_format=PromptTemplateFormat.MUSTACHE, + template={ + "_version": "messages-v1", + "messages": [ + {"role": "user", "content": "Hello what's the weather in Antarctica like?"} + ], + }, + invocation_parameters={"temperature": 0.5}, + tools={ + "_version": "tools-v1", + "tools": [ + { + "definition": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "A location in the world", + }, + "unit": { + "type": "string", + "enum": ["celsius", "fahrenheit"], + "default": "fahrenheit", + "description": "The unit of temperature", + }, + }, + "required": ["location"], + }, + } + } + ], + }, + model_name="gpt-4o", + model_provider="openai", + ), + PromptVersion( + id_attr=1, + user="alice", + description="A dummy prompt version", + template_type=PromptTemplateType.TEXT, + template_format=PromptTemplateFormat.MUSTACHE, + template={ + "_version": "messages-v1", + "messages": [ + {"role": "user", "content": "Hello what's the weather in Antarctica like?"} + ], + }, + model_name="gpt-4o", + model_provider="openai", + ), + ] + + return connection_from_list(data=dummy_data, args=args) + @strawberry.field def clusters( self, diff --git a/src/phoenix/server/api/types/Prompt.py b/src/phoenix/server/api/types/Prompt.py index 1dec517f5d..0d49d2e063 100644 --- a/src/phoenix/server/api/types/Prompt.py +++ b/src/phoenix/server/api/types/Prompt.py @@ -1,3 +1,5 @@ +# Part of the Phoenix PromptHub feature set + from datetime import datetime from typing import Optional diff --git a/src/phoenix/server/api/types/PromptVersion.py b/src/phoenix/server/api/types/PromptVersion.py new file mode 100644 index 0000000000..a1e3600077 --- /dev/null +++ b/src/phoenix/server/api/types/PromptVersion.py @@ -0,0 +1,35 @@ +# Part of the Phoenix PromptHub feature set + +from enum import Enum +from typing import Optional + +import strawberry +from strawberry.relay import Node, NodeID +from strawberry.scalars import JSON + + +@strawberry.enum +class PromptTemplateType(str, Enum): + TEXT = "text" + JSON = "json" + + +@strawberry.enum +class PromptTemplateFormat(str, Enum): + MUSTACHE = "mustache" + FSTRING = "fstring" + + +@strawberry.type +class PromptVersion(Node): + id_attr: NodeID[int] + user: Optional[str] + description: str + template_type: PromptTemplateType + template_format: PromptTemplateFormat + template: JSON + invocation_parameters: Optional[JSON] + tools: Optional[JSON] + output_schema: Optional[JSON] + model_name: str + model_provider: str From 6a6eb5dbd8ea71cbe2eeef05765f944d71125fa4 Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Tue, 17 Dec 2024 15:31:02 -0800 Subject: [PATCH 2/5] Update src/phoenix/server/api/types/PromptVersion.py --- src/phoenix/server/api/types/PromptVersion.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/phoenix/server/api/types/PromptVersion.py b/src/phoenix/server/api/types/PromptVersion.py index a1e3600077..0526f201d5 100644 --- a/src/phoenix/server/api/types/PromptVersion.py +++ b/src/phoenix/server/api/types/PromptVersion.py @@ -18,6 +18,7 @@ class PromptTemplateType(str, Enum): class PromptTemplateFormat(str, Enum): MUSTACHE = "mustache" FSTRING = "fstring" + NONE = "none" @strawberry.type From 039cb4dad4cd3c304367874dc0ea7336a739ca8b Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Tue, 17 Dec 2024 16:11:32 -0800 Subject: [PATCH 3/5] reorganize --- src/phoenix/server/api/queries.py | 84 ---------------- src/phoenix/server/api/types/Prompt.py | 95 +++++++++++++++++++ src/phoenix/server/api/types/PromptVersion.py | 4 +- 3 files changed, 97 insertions(+), 86 deletions(-) diff --git a/src/phoenix/server/api/queries.py b/src/phoenix/server/api/queries.py index 9ec863dd88..d942ad754a 100644 --- a/src/phoenix/server/api/queries.py +++ b/src/phoenix/server/api/queries.py @@ -80,11 +80,6 @@ from phoenix.server.api.types.Project import Project from phoenix.server.api.types.ProjectSession import ProjectSession, to_gql_project_session from phoenix.server.api.types.Prompt import Prompt -from phoenix.server.api.types.PromptVersion import ( - PromptTemplateFormat, - PromptTemplateType, - PromptVersion, -) from phoenix.server.api.types.SortDir import SortDir from phoenix.server.api.types.Span import Span, to_gql_span from phoenix.server.api.types.SystemApiKey import SystemApiKey @@ -617,85 +612,6 @@ async def prompts( args=args, ) - @strawberry.field - async def prompt_versions( - self, - info: Info[Context, None], - first: Optional[int] = 50, - last: Optional[int] = UNSET, - after: Optional[CursorString] = UNSET, - before: Optional[CursorString] = UNSET, - ) -> Connection[PromptVersion]: - args = ConnectionArgs( - first=first, - after=after if isinstance(after, CursorString) else None, - last=last, - before=before if isinstance(before, CursorString) else None, - ) - - dummy_data = [ - PromptVersion( - id_attr=2, - user="alice", - description="A dummy prompt version", - template_type=PromptTemplateType.TEXT, - template_format=PromptTemplateFormat.MUSTACHE, - template={ - "_version": "messages-v1", - "messages": [ - {"role": "user", "content": "Hello what's the weather in Antarctica like?"} - ], - }, - invocation_parameters={"temperature": 0.5}, - tools={ - "_version": "tools-v1", - "tools": [ - { - "definition": { - "name": "get_current_weather", - "description": "Get the current weather in a given location", - "parameters": { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "A location in the world", - }, - "unit": { - "type": "string", - "enum": ["celsius", "fahrenheit"], - "default": "fahrenheit", - "description": "The unit of temperature", - }, - }, - "required": ["location"], - }, - } - } - ], - }, - model_name="gpt-4o", - model_provider="openai", - ), - PromptVersion( - id_attr=1, - user="alice", - description="A dummy prompt version", - template_type=PromptTemplateType.TEXT, - template_format=PromptTemplateFormat.MUSTACHE, - template={ - "_version": "messages-v1", - "messages": [ - {"role": "user", "content": "Hello what's the weather in Antarctica like?"} - ], - }, - model_name="gpt-4o", - model_provider="openai", - ), - ] - - return connection_from_list(data=dummy_data, args=args) - @strawberry.field def clusters( self, diff --git a/src/phoenix/server/api/types/Prompt.py b/src/phoenix/server/api/types/Prompt.py index 0d49d2e063..f2e911a47f 100644 --- a/src/phoenix/server/api/types/Prompt.py +++ b/src/phoenix/server/api/types/Prompt.py @@ -4,7 +4,22 @@ from typing import Optional import strawberry +from strawberry import UNSET from strawberry.relay import Node, NodeID +from strawberry.types import Connection, Info + +from phoenix.server.api.context import Context +from phoenix.server.api.types.pagination import ( + ConnectionArgs, + CursorString, + connection_from_list, +) + +from .PromptVersion import ( + PromptTemplateFormat, + PromptTemplateType, + PromptVersion, +) @strawberry.type @@ -13,3 +28,83 @@ class Prompt(Node): name: str description: Optional[str] created_at: datetime + + @strawberry.field + async def prompt_versions( + self, + info: Info[Context, None], + first: Optional[int] = 50, + last: Optional[int] = UNSET, + after: Optional[CursorString] = UNSET, + before: Optional[CursorString] = UNSET, + ) -> Connection[PromptVersion]: + args = ConnectionArgs( + first=first, + after=after if isinstance(after, CursorString) else None, + last=last, + before=before if isinstance(before, CursorString) else None, + ) + + dummy_data = [ + PromptVersion( + id_attr=2, + user="alice", + description="A dummy prompt version", + template_type=PromptTemplateType.TEXT, + template_format=PromptTemplateFormat.MUSTACHE, + template={ + "_version": "messages-v1", + "messages": [ + {"role": "user", "content": "Hello what's the weather in Antarctica like?"} + ], + }, + invocation_parameters={"temperature": 0.5}, + tools={ + "_version": "tools-v1", + "tools": [ + { + "definition": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "A location in the world", + }, + "unit": { + "type": "string", + "enum": ["celsius", "fahrenheit"], + "default": "fahrenheit", + "description": "The unit of temperature", + }, + }, + "required": ["location"], + }, + } + } + ], + }, + output_schema=UNSET, + model_name="gpt-4o", + model_provider="openai", + ), + PromptVersion( + id_attr=1, + user="alice", + description="A dummy prompt version", + template_type=PromptTemplateType.TEXT, + template_format=PromptTemplateFormat.MUSTACHE, + template={ + "_version": "messages-v1", + "messages": [ + {"role": "user", "content": "Hello what's the weather in Antarctica like?"} + ], + }, + model_name="gpt-4o", + model_provider="openai", + ), + ] + + return connection_from_list(data=dummy_data, args=args) diff --git a/src/phoenix/server/api/types/PromptVersion.py b/src/phoenix/server/api/types/PromptVersion.py index 0526f201d5..7f0f9b32a6 100644 --- a/src/phoenix/server/api/types/PromptVersion.py +++ b/src/phoenix/server/api/types/PromptVersion.py @@ -10,8 +10,8 @@ @strawberry.enum class PromptTemplateType(str, Enum): - TEXT = "text" - JSON = "json" + STRING = "str" + CHAT = "chat" @strawberry.enum From 8f87e952b88baab4c244b86977c16f1db4d24be1 Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Tue, 17 Dec 2024 16:26:31 -0800 Subject: [PATCH 4/5] cleanup --- src/phoenix/server/api/types/Prompt.py | 9 ++++----- src/phoenix/server/api/types/PromptVersion.py | 7 ++++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/phoenix/server/api/types/Prompt.py b/src/phoenix/server/api/types/Prompt.py index f2e911a47f..5ee691584a 100644 --- a/src/phoenix/server/api/types/Prompt.py +++ b/src/phoenix/server/api/types/Prompt.py @@ -5,8 +5,8 @@ import strawberry from strawberry import UNSET -from strawberry.relay import Node, NodeID -from strawberry.types import Connection, Info +from strawberry.relay import Connection, Node, NodeID +from strawberry.types import Info from phoenix.server.api.context import Context from phoenix.server.api.types.pagination import ( @@ -50,7 +50,7 @@ async def prompt_versions( id_attr=2, user="alice", description="A dummy prompt version", - template_type=PromptTemplateType.TEXT, + template_type=PromptTemplateType.CHAT, template_format=PromptTemplateFormat.MUSTACHE, template={ "_version": "messages-v1", @@ -86,7 +86,6 @@ async def prompt_versions( } ], }, - output_schema=UNSET, model_name="gpt-4o", model_provider="openai", ), @@ -94,7 +93,7 @@ async def prompt_versions( id_attr=1, user="alice", description="A dummy prompt version", - template_type=PromptTemplateType.TEXT, + template_type=PromptTemplateType.CHAT, template_format=PromptTemplateFormat.MUSTACHE, template={ "_version": "messages-v1", diff --git a/src/phoenix/server/api/types/PromptVersion.py b/src/phoenix/server/api/types/PromptVersion.py index 7f0f9b32a6..00ad26c3ff 100644 --- a/src/phoenix/server/api/types/PromptVersion.py +++ b/src/phoenix/server/api/types/PromptVersion.py @@ -4,6 +4,7 @@ from typing import Optional import strawberry +from strawberry import UNSET from strawberry.relay import Node, NodeID from strawberry.scalars import JSON @@ -29,8 +30,8 @@ class PromptVersion(Node): template_type: PromptTemplateType template_format: PromptTemplateFormat template: JSON - invocation_parameters: Optional[JSON] - tools: Optional[JSON] - output_schema: Optional[JSON] + invocation_parameters: Optional[JSON] = UNSET + tools: Optional[JSON] = UNSET + output_schema: Optional[JSON] = UNSET model_name: str model_provider: str From 45fb1f8ce617a1175f9c044a3416970dac49fffe Mon Sep 17 00:00:00 2001 From: Mikyo King Date: Tue, 17 Dec 2024 16:57:01 -0800 Subject: [PATCH 5/5] Update the schema --- app/schema.graphql | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/schema.graphql b/app/schema.graphql index a0054357f9..d425048b59 100644 --- a/app/schema.graphql +++ b/app/schema.graphql @@ -1374,6 +1374,7 @@ type Prompt implements Node { name: String! description: String createdAt: DateTime! + promptVersions(first: Int = 50, last: Int, after: String, before: String): PromptVersionConnection! } """A connection to a list of items.""" @@ -1405,11 +1406,12 @@ type PromptResponse { enum PromptTemplateFormat { MUSTACHE FSTRING + NONE } enum PromptTemplateType { - TEXT - JSON + STRING + CHAT } type PromptVersion implements Node { @@ -1463,7 +1465,6 @@ type Query { node(id: GlobalID!): Node! viewer: User prompts(first: Int = 50, last: Int, after: String, before: String): PromptConnection! - promptVersions(first: Int = 50, last: Int, after: String, before: String): PromptVersionConnection! clusters(clusters: [ClusterInput!]!): [Cluster!]! hdbscanClustering( """Event ID of the coordinates"""