diff --git a/langfuse/_client/client.py b/langfuse/_client/client.py index e926e4571..04ec2e4d9 100644 --- a/langfuse/_client/client.py +++ b/langfuse/_client/client.py @@ -173,6 +173,17 @@ def _serialize_evaluations(evaluations: List[Evaluation]) -> List[Dict[str, Any] ] +def _to_api_chat_messages(messages: List[Any]) -> List[Any]: + # ChatPromptClient.prompt and ChatMessageWithPlaceholdersDict use + # type="message", but the API models only accept "chatmessage". + return [ + {**message, "type": "chatmessage"} + if isinstance(message, dict) and message.get("type") == "message" + else message + for message in messages + ] + + class Langfuse: """Main client for Langfuse tracing and platform features. @@ -3872,7 +3883,9 @@ def get_prompt( fallback_client_args: Dict[str, Any] = { "name": name, - "prompt": fallback, + "prompt": _to_api_chat_messages(fallback) + if isinstance(fallback, list) + else fallback, "type": type, "version": version or 0, "config": {}, @@ -4074,7 +4087,7 @@ def create_prompt( request: Union[CreateChatPromptRequest, CreateTextPromptRequest] = ( CreateChatPromptRequest( name=name, - prompt=cast(Any, prompt), + prompt=_to_api_chat_messages(prompt), labels=labels, tags=tags, config=config or {}, diff --git a/tests/unit/test_prompt.py b/tests/unit/test_prompt.py index eadfb8221..d18570ba6 100644 --- a/tests/unit/test_prompt.py +++ b/tests/unit/test_prompt.py @@ -748,3 +748,67 @@ def test_get_fresh_prompt_when_version_changes(langfuse: Langfuse): result_call_2 = langfuse.get_prompt(prompt_name, version=2) assert mock_server_call.call_count == 2 assert result_call_2 == version_changed_prompt_client + + +def test_create_chat_prompt_from_fetched_chat_prompt(langfuse: Langfuse): + fetched = ChatPromptClient( + Prompt_Chat( + name="source", + version=1, + prompt=[ + {"type": "chatmessage", "role": "system", "content": "Hi {{name}}"}, + {"type": "placeholder", "name": "history"}, + ], + labels=[], + type="chat", + config={}, + tags=[], + ) + ) + assert fetched.prompt[0]["type"] == "message" + + mock_server_call = langfuse.api.prompts.create + mock_server_call.return_value = Prompt_Chat( + name="copy", + version=1, + prompt=[ + {"type": "chatmessage", "role": "system", "content": "Hi {{name}}"}, + {"type": "placeholder", "name": "history"}, + ], + labels=[], + type="chat", + config={}, + tags=[], + ) + + result = langfuse.create_prompt(name="copy", prompt=fetched.prompt, type="chat") + + request = mock_server_call.call_args.kwargs["request"] + assert request.dict()["prompt"] == [ + {"type": "chatmessage", "role": "system", "content": "Hi {{name}}"}, + {"type": "placeholder", "name": "history"}, + ] + assert fetched.prompt[0]["type"] == "message" + assert result.prompt == fetched.prompt + + +def test_get_chat_prompt_fallback_with_message_type(langfuse: Langfuse): + langfuse.api.prompts.get.side_effect = Exception("Prompt not found") + fallback = [ + {"type": "message", "role": "system", "content": "Hi {{name}}"}, + {"type": "placeholder", "name": "history"}, + ] + + result = langfuse.get_prompt( + "chat_fallback_with_message_type", + type="chat", + fallback=fallback, + max_retries=0, + ) + + assert result.is_fallback + assert result.prompt == fallback + assert result.compile(name="Bob", history=[{"role": "user", "content": "yo"}]) == [ + {"role": "system", "content": "Hi Bob"}, + {"role": "user", "content": "yo"}, + ]