diff --git a/app/schema.graphql b/app/schema.graphql index 63ad2f144c..7b48e4b491 100644 --- a/app/schema.graphql +++ b/app/schema.graphql @@ -110,6 +110,7 @@ input ChatCompletionInput { tools: [JSON!] apiKey: String = null template: TemplateOptions + promptId: GlobalID = null } input ChatCompletionMessageInput { @@ -159,6 +160,7 @@ input ChatCompletionOverDatasetInput { experimentName: String = null experimentDescription: String = null experimentMetadata: JSON = {} + promptId: GlobalID = null } type ChatCompletionOverDatasetMutationExamplePayload { diff --git a/app/src/pages/playground/__generated__/PlaygroundDatasetExamplesTableMutation.graphql.ts b/app/src/pages/playground/__generated__/PlaygroundDatasetExamplesTableMutation.graphql.ts index 5b7de8b8e9..5b61f2369d 100644 --- a/app/src/pages/playground/__generated__/PlaygroundDatasetExamplesTableMutation.graphql.ts +++ b/app/src/pages/playground/__generated__/PlaygroundDatasetExamplesTableMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<83115a7d0cd41610c964392fd634b548>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -23,6 +23,7 @@ export type ChatCompletionOverDatasetInput = { invocationParameters?: ReadonlyArray; messages: ReadonlyArray; model: GenerativeModelInput; + promptId?: string | null; templateLanguage: TemplateLanguage; tools?: ReadonlyArray | null; }; diff --git a/app/src/pages/playground/__generated__/PlaygroundDatasetExamplesTableSubscription.graphql.ts b/app/src/pages/playground/__generated__/PlaygroundDatasetExamplesTableSubscription.graphql.ts index e0c90fe5c7..0dde71abe7 100644 --- a/app/src/pages/playground/__generated__/PlaygroundDatasetExamplesTableSubscription.graphql.ts +++ b/app/src/pages/playground/__generated__/PlaygroundDatasetExamplesTableSubscription.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<8e709a5628ea7235eacc28dfa5bb7277>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -23,6 +23,7 @@ export type ChatCompletionOverDatasetInput = { invocationParameters?: ReadonlyArray; messages: ReadonlyArray; model: GenerativeModelInput; + promptId?: string | null; templateLanguage: TemplateLanguage; tools?: ReadonlyArray | null; }; diff --git a/app/src/pages/playground/__generated__/PlaygroundOutputMutation.graphql.ts b/app/src/pages/playground/__generated__/PlaygroundOutputMutation.graphql.ts index ffdcfdccb6..8de30e93fd 100644 --- a/app/src/pages/playground/__generated__/PlaygroundOutputMutation.graphql.ts +++ b/app/src/pages/playground/__generated__/PlaygroundOutputMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -18,6 +18,7 @@ export type ChatCompletionInput = { invocationParameters?: ReadonlyArray; messages: ReadonlyArray; model: GenerativeModelInput; + promptId?: string | null; template?: TemplateOptions | null; tools?: ReadonlyArray | null; }; diff --git a/app/src/pages/playground/__generated__/PlaygroundOutputSubscription.graphql.ts b/app/src/pages/playground/__generated__/PlaygroundOutputSubscription.graphql.ts index afb378f0e0..5c811039d0 100644 --- a/app/src/pages/playground/__generated__/PlaygroundOutputSubscription.graphql.ts +++ b/app/src/pages/playground/__generated__/PlaygroundOutputSubscription.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<3274cb65871ec27834fd3163e1e79dea>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -18,6 +18,7 @@ export type ChatCompletionInput = { invocationParameters?: ReadonlyArray; messages: ReadonlyArray; model: GenerativeModelInput; + promptId?: string | null; template?: TemplateOptions | null; tools?: ReadonlyArray | null; }; diff --git a/app/src/pages/playground/playgroundUtils.ts b/app/src/pages/playground/playgroundUtils.ts index 99af6a1eb0..06625cf4ad 100644 --- a/app/src/pages/playground/playgroundUtils.ts +++ b/app/src/pages/playground/playgroundUtils.ts @@ -980,7 +980,8 @@ const getBaseChatCompletionInput = ({ ? instance.tools.map((tool) => tool.definition) : undefined, apiKey: credentials[instance.model.provider] || null, - } as const; + promptId: instance.prompt?.id, + } satisfies Partial; }; /** diff --git a/src/phoenix/server/api/helpers/playground_spans.py b/src/phoenix/server/api/helpers/playground_spans.py index 4625a0c655..97980426f3 100644 --- a/src/phoenix/server/api/helpers/playground_spans.py +++ b/src/phoenix/server/api/helpers/playground_spans.py @@ -26,6 +26,7 @@ ) from opentelemetry.sdk.trace.id_generator import RandomIdGenerator as DefaultOTelIDGenerator from opentelemetry.trace import StatusCode +from strawberry.relay.types import GlobalID from strawberry.scalars import JSON as JSONScalarType from typing_extensions import Self, TypeAlias, assert_never @@ -70,8 +71,10 @@ def __init__( ) -> None: self._input = input self._attributes: dict[str, Any] = attributes if attributes is not None else {} + self._attributes.update( chain( + prompt_id_metadata(input.prompt_id), llm_span_kind(), llm_model_name(input.model.name), llm_tools(input.tools or []), @@ -264,6 +267,10 @@ def input_value_and_mime_type( yield INPUT_VALUE, safe_json_dumps(input_data) +def prompt_id_metadata(prompt_id: Optional[GlobalID]) -> Iterator[tuple[str, Any]]: + yield METADATA, {"phoenix-prompt-id": str(prompt_id)} + + def _merge_tool_call_chunks( chunks_by_id: defaultdict[str, list[ToolCallChunk]], ) -> list[dict[str, Any]]: @@ -442,6 +449,7 @@ def _serialize_event(event: SpanEvent) -> dict[str, Any]: LLM_TOOLS = SpanAttributes.LLM_TOOLS LLM_TOKEN_COUNT_PROMPT = SpanAttributes.LLM_TOKEN_COUNT_PROMPT LLM_TOKEN_COUNT_COMPLETION = SpanAttributes.LLM_TOKEN_COUNT_COMPLETION +METADATA = SpanAttributes.METADATA MESSAGE_CONTENT = MessageAttributes.MESSAGE_CONTENT MESSAGE_ROLE = MessageAttributes.MESSAGE_ROLE diff --git a/src/phoenix/server/api/input_types/ChatCompletionInput.py b/src/phoenix/server/api/input_types/ChatCompletionInput.py index dfce76a540..7aba5ae1bb 100644 --- a/src/phoenix/server/api/input_types/ChatCompletionInput.py +++ b/src/phoenix/server/api/input_types/ChatCompletionInput.py @@ -21,6 +21,7 @@ class ChatCompletionInput: tools: Optional[list[JSON]] = UNSET api_key: Optional[str] = strawberry.field(default=None) template: Optional[TemplateOptions] = UNSET + prompt_id: Optional[GlobalID] = None @strawberry.input @@ -36,3 +37,4 @@ class ChatCompletionOverDatasetInput: experiment_name: Optional[str] = None experiment_description: Optional[str] = None experiment_metadata: Optional[JSON] = strawberry.field(default_factory=dict) + prompt_id: Optional[GlobalID] = None