fix(langchain): silence intentional placeholder warnings - #1689
Conversation
827acf2 to
66d40d6
Compare
66d40d6 to
7abf847
Compare
|
Ran into the same warning and worked through this patch before finding this PR — the approach looks right to me. Two notes from that, both small: 1. The flag shares a namespace with template variables.
It's an unlikely name, but public def compile(self, **kwargs: Union[str, Any]) -> ...:
return self._compile(kwargs, warn_on_unresolved_placeholders=True)
def _compile(
self,
kwargs: Dict[str, Any],
*,
warn_on_unresolved_placeholders: bool,
) -> ...:and at the call site: compiled_messages = self._compile(kwargs, warn_on_unresolved_placeholders=False)2. Two regression tests worth adding. The current test covers the quiet path. The two behaviours the issue explicitly asks to preserve aren't pinned yet, so a later refactor could silence them without failing anything: def test_compile_still_warns_on_unresolved_placeholders(self, caplog):
with caplog.at_level(logging.WARNING, logger="langfuse"):
prompt_client.compile()
assert "Placeholders ['chat_history'] have not been resolved" in caplog.text
def test_get_langchain_prompt_still_warns_on_malformed_placeholder(self, caplog):
with caplog.at_level(logging.WARNING, logger="langfuse"):
prompt_client.get_langchain_prompt(chat_history="not-a-list")
assert "must contain a list of chat messages" in caplog.text
Happy to hand over the full test bodies if useful. |
Summary
ChatPromptClient.compile()calls.get_langchain_prompt()when unresolved placeholders are intentionally returned as LangChainMessagesPlaceholderobjects.Fixes #1667.
Verification
uv run --frozen pytest tests/unit/test_prompt_compilation.py::TestLangchainPromptCompilation::test_get_langchain_prompt_with_unresolved_placeholders -quv run --frozen pytest tests/unit/test_prompt_compilation.py -quv run --frozen ruff check langfuse/model.py tests/unit/test_prompt_compilation.pyuv run --frozen ruff format --check langfuse/model.py tests/unit/test_prompt_compilation.pyuv run --frozen mypy langfuse --no-error-summarygit diff --checkI also tried
uv run --frozen pytest tests/e2e/test_prompt.py::test_warning_on_unresolved_placeholders -q, but the local run requires Langfuse server credentials/API setup and failed before the assertion path withLangfuse client initialized without public_key.Greptile Summary
This PR fixes spurious
langfuse_logger.warningcalls that fire duringget_langchain_prompt()when unresolved placeholders are intentionally left for LangChain to handle asMessagesPlaceholderobjects.compile()is refactored into a thin wrapper around a new private_compile(warn_on_unresolved_placeholders: bool)method; the public API is unchanged and still warns by default.get_langchain_prompt()now calls_compile(warn_on_unresolved_placeholders=False), suppressing the warning only on the LangChain hand-off path.langfuse_logger.warningis never called duringget_langchain_prompt()when a placeholder is intentionally left unresolved.Confidence Score: 4/5
Safe to merge; the behavioural change is narrow and well-tested.
The refactor correctly isolates warning behaviour behind a flag, public compile() is unchanged, and a targeted regression test covers the silent path. The only finding is a style-level import placed inside a test method body rather than at the module top.
No files require special attention beyond the minor import placement in the test.
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A["compile(kwargs)"] -->|"warn=True"| B["_compile()"] C["get_langchain_prompt(kwargs)"] -->|"warn=False"| B B --> D{placeholder resolved?} D -- Yes --> E[expand messages] D -- No --> F[keep as placeholder dict] F --> G{warn flag set?} G -- Yes --> H["langfuse_logger.warning()"] G -- No --> I[silent] A --> L[return raw dicts] C --> M["convert to LangChain tuples / MessagesPlaceholder"]Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "fix(langchain): silence intentional plac..." | Re-trigger Greptile
Context used:
Learned From
langfuse/langfuse-python#1387