Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Langfuse Langfuse NormalizeInputOutput

From Leeroopedia
Knowledge Sources
Domains Data Normalization, AI Frameworks, LLM Messaging
Last Updated 2026-02-14 00:00 GMT

Overview

Concrete tool for normalizing diverse LLM provider message formats into unified ChatML arrays provided by Langfuse.

Description

The normalizeInput() and normalizeOutput() functions are the public entry points for ChatML normalization. They share the same architecture:

  1. Build adapter context: Merge the provided NormalizerContext with defaults, setting metadata to the input data itself if not explicitly provided and attaching the raw data.
  2. Select adapter: Call selectAdapter(ctx) which evaluates the ordered adapter registry (langgraph > aisdk > openai > gemini > microsoftAgent > pydanticAI > semanticKernel > generic) and returns the first adapter whose detect(ctx) returns true.
  3. Preprocess: Call adapter.preprocess(data, direction, ctx) where direction is "input" or "output". The adapter transforms the provider-specific format toward ChatML compatibility.
  4. Validate: For input, call mapToChatMl(preprocessed) which validates against ChatMlArraySchema with fallback patterns. For output, call mapOutputToChatMl(preprocessed) which wraps single messages in arrays and handles the messages key extraction.

The functions return a Zod SafeParseReturnType -- either { success: true, data: ChatMlMessage[] } or { success: false, error: ZodError }.

Supporting functions in the same module:

  • mapToChatMl(input): Validates input directly, then tries [[msgs]] -> [msgs] unwrapping, then tries { messages: [...] } extraction.
  • mapOutputToChatMl(output): Handles { messages: [...] } extraction (LangGraph format), then wraps non-array output in an array.
  • cleanLegacyOutput(output, fallback?): Converts legacy { completion: "..." } format.
  • extractAdditionalInput(input): Extracts non-messages keys from input objects.
  • combineInputOutputMessages(inputResult, outputResult, cleanOutput): Merges input and output messages into a single thread, defaulting output role to "assistant".

Usage

These functions are used in the Langfuse web frontend to normalize observation input/output for display in the conversation view, and can be used in evaluation pipelines to ensure consistent message structures regardless of the originating provider.

Code Reference

Source Location

  • Repository: langfuse
  • File: packages/shared/src/utils/chatml/core.ts
  • Lines: 130-158 (normalizeInput and normalizeOutput)

Signature

function normalizeInput(
  input: unknown,
  ctx?: NormalizerContext,
): {
  success: boolean;
  data?: ChatMlMessage[];
  error?: ZodError;
}

function normalizeOutput(
  output: unknown,
  ctx?: NormalizerContext,
): {
  success: boolean;
  data?: ChatMlMessage[];
  error?: ZodError;
}

Import

import {
  normalizeInput,
  normalizeOutput,
  mapToChatMl,
  mapOutputToChatMl,
  cleanLegacyOutput,
  extractAdditionalInput,
  combineInputOutputMessages,
} from "@langfuse/shared/src/utils/chatml/core";

import type { NormalizerContext } from "@langfuse/shared/src/utils/chatml/adapters";

I/O Contract

Inputs

Name Type Required Description
input (for normalizeInput) unknown Yes Raw input data in any supported provider format. Can be a string, array of message objects, nested object with a messages key, or provider-specific structure.
output (for normalizeOutput) unknown Yes Raw output data in any supported provider format. Can be a single message object, string, array, or object with a messages key.
ctx NormalizerContext No Optional context for adapter selection. Includes: framework?: string (explicit adapter override), metadata?: unknown (observation metadata for detection), scopeName?: string (instrumentation scope), and other context fields.

Outputs

Name Type Description
success boolean Whether the normalization and validation succeeded
data ChatMlMessage[] (when success=true) Array of normalized ChatML messages. Each message has at minimum a role field and typically content, with optional tool_calls, tool_call_id, json, and other fields.
error ZodError (when success=false) Zod validation error describing why the data could not be normalized to ChatML format

Usage Examples

Normalizing OpenAI-Format Input

import { normalizeInput } from "@langfuse/shared/src/utils/chatml/core";

const result = normalizeInput([
  { role: "system", content: "You are a helpful assistant." },
  { role: "user", content: "What is the capital of France?" },
]);

// result.success === true
// result.data === [
//   { role: "system", content: "You are a helpful assistant." },
//   { role: "user", content: "What is the capital of France?" },
// ]

Normalizing Gemini-Format Input with Explicit Adapter

import { normalizeInput } from "@langfuse/shared/src/utils/chatml/core";

const result = normalizeInput(
  [{ parts: [{ text: "Hello world" }], role: "user" }],
  { framework: "gemini" },
);

// result.success === true
// result.data === [{ role: "user", content: "Hello world" }]

Normalizing Output with Messages Key (LangGraph)

import { normalizeOutput } from "@langfuse/shared/src/utils/chatml/core";

const result = normalizeOutput({
  messages: [
    { role: "assistant", content: "The capital of France is Paris." },
  ],
});

// result.success === true
// result.data === [
//   { role: "assistant", content: "The capital of France is Paris." },
// ]

Combining Input and Output Messages

import {
  normalizeInput,
  normalizeOutput,
  cleanLegacyOutput,
  combineInputOutputMessages,
} from "@langfuse/shared/src/utils/chatml/core";

const inputResult = normalizeInput([
  { role: "user", content: "Tell me a joke" },
]);

const rawOutput = "Why did the chicken cross the road?";
const cleanOutput = cleanLegacyOutput(rawOutput, rawOutput);
const outputResult = normalizeOutput(rawOutput);

const combined = combineInputOutputMessages(inputResult, outputResult, cleanOutput);
// combined === [
//   { role: "user", content: "Tell me a joke" },
//   { role: "assistant", content: "Why did the chicken cross the road?" },
// ]

Handling Normalization Failure

import { normalizeInput } from "@langfuse/shared/src/utils/chatml/core";

const result = normalizeInput(42); // Not a valid message format

// result.success === false
// result.error contains ZodError describing the validation failure

Related Pages

Implements Principle

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment