프롬프트를 트레이스에 연결하기
프롬프트를 트레이스에 연결하기 (Link Prompts to Traces)
프롬프트를 트레이스에 연결하면 프롬프트 버전별 지표와 평가를 추적할 수 있어요. 시간이 지나면서 프롬프트 품질을 개선하는 기반이 되죠.
출처: 문서
본문
프롬프트와 트레이스를 연결한 후, Langfuse에서 generation observation으로 이동하면 응답을 생성하는 데 사용된 프롬프트가 강조 표시돼요. 지표에 접근하려면 프롬프트로 이동해 Metrics 탭을 클릭하세요.
프롬프트를 트레이스에 연결하는 방법
Python SDKJS/TS SDKOpenAI SDK (Python)OpenAI SDK (JS/TS)Langchain (Python)Langchain (JS/TS)Vercel AI SDK
Python SDK
Langfuse Python SDK로 생성된 generation의 경우 prompt 키워드 인자로 프롬프트를 generation에 직접 전달하세요. 이렇게 하면 프롬프트가 의도한 generation에만 연결되며 권장되는 방법이에요.
다음 Langfuse Python SDK 메서드 중 하나로 특정 generation에 프롬프트를 설정할 수 있어요. 자세한 내용은 SDK 문서를 참고하세요.
데코레이터 (Decorators)
from langfuse import observe, get_client
langfuse = get_client()
@observe(as_type="generation")
def nested_generation():
prompt = langfuse.get_prompt("movie-critic")
langfuse.update_current_generation(
prompt=prompt,
)
@observe()
def main():
nested_generation()
main()
컨텍스트 매니저 (Context Managers)
from langfuse import get_client
langfuse = get_client()
prompt = langfuse.get_prompt("movie-critic")
with langfuse.start_as_current_observation(
as_type="generation",
name="movie-generation",
model="gpt-4o",
prompt=prompt
) as generation:
# Your LLM call here
generation.update(output="LLM response")
수동 observation (Manual observations)
from langfuse import get_client
langfuse = get_client()
prompt = langfuse.get_prompt("movie-critic")
generation = langfuse.start_observation(
name="movie-generation",
as_type="generation",
model="gpt-4o",
prompt=prompt
)
# Your LLM call here
generation.update(output="LLM response")
generation.end() # Important: manually end the generation
여러 generation에 프롬프트 전파
같은 컨텍스트 안에서 생성된 여러 generation이 같은 프롬프트 버전을 사용한다면 propagate_attributes(prompt=prompt)를 사용하세요. 이 옵션은 Python SDK 4.14.0 이상에서 사용할 수 있어요.
from langfuse import get_client, propagate_attributes
langfuse = get_client()
prompt = langfuse.get_prompt("movie-critic")
with propagate_attributes(prompt=prompt):
with langfuse.start_as_current_observation(
as_type="generation",
name="movie-review",
) as generation:
generation.update(
input=prompt.compile(movie="Dune 2"),
output="A sweeping, ambitious sequel.",
)
with langfuse.start_as_current_observation(
as_type="generation",
name="movie-review",
) as generation:
generation.update(
input=prompt.compile(movie="Arrival"),
output="A thoughtful and moving science-fiction film.",
)
제3자 계측 (Third-party instrumentation)
계측 라이브러리가 당신을 대신해 generation을 생성하고 Langfuse 프롬프트 인자를 노출하지 않을 때 전파가 유용해요. 예를 들어 LiteLLM OpenTelemetry 통합에서:
import litellm
from langfuse import get_client, propagate_attributes
langfuse = get_client()
prompt = langfuse.get_prompt("movie-critic")
litellm.callbacks = ["langfuse_otel"]
with propagate_attributes(prompt=prompt):
response = litellm.completion(
model="gpt-4o",
messages=[
{
"role": "user",
"content": prompt.compile(movie="Dune 2"),
}
],
)
이것은 OpenAI Agents SDK와 Langfuse Python SDK를 통해 내보내진 OpenInference 계측에서도 동작해요. generation observation만 프롬프트에 연결돼요. generation이 자체적으로 프롬프트를 명시적으로 설정하면 그 프롬프트가 전파된 프롬프트보다 우선해요.
JS/TS SDK
Langfuse JS/TS SDK로 트레이스를 만드는 방법은 세 가지가 있어요. 자세한 내용은 SDK 문서를 참고하세요.
Observe 래퍼
import { LangfuseClient } from "@langfuse/client";
import { observe, updateActiveObservation } from "@langfuse/tracing";
const langfuse = new LangfuseClient();
const callLLM = async (input: string) => {
const prompt = await langfuse.prompt.get("my-prompt");
updateActiveObservation({ prompt }, { asType: "generation" });
return await invokeLLM(input);
};
export const observedCallLLM = observe(callLLM);
컨텍스트 매니저
import { LangfuseClient } from "@langfuse/client";
import { startActiveObservation } from "@langfuse/tracing";
const langfuse = new LangfuseClient();
startActiveObservation(
"llm",
async (generation) => {
const prompt = await langfuse.prompt.get("my-prompt");
generation.update({ prompt });
},
{ asType: "generation" },
);
수동 observation
import { LangfuseClient } from "@langfuse/client";
import { startObservation } from "@langfuse/tracing";
const prompt = await new LangfuseClient().prompt.get("my-prompt");
startObservation(
"llm",
{
prompt,
},
{ asType: "generation" },
);
OpenAI SDK (Python)
from langfuse.openai import openai
from langfuse import get_client
langfuse = get_client()
prompt = langfuse.get_prompt("calculator")
openai.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": prompt.compile(base=10)},
{"role": "user", "content": "1 + 1 = "}],
langfuse_prompt=prompt
)
트레이싱을 위해 OpenTelemetry를 이미 설정했는지 확인하세요.
OpenAI SDK (JS/TS)
import { observeOpenAI } from "@langfuse/openai";
import OpenAI from "openai";
const langfusePrompt = await langfuse.prompt.get("prompt-name"); // Fetch a previously created prompt
const res = await observeOpenAI(new OpenAI(), {
langfusePrompt,
}).completions.create({
prompt: langfusePrompt.prompt,
model: "gpt-4o",
max_tokens: 300,
});
Langchain (Python)
from langfuse import get_client
from langfuse.langchain import CallbackHandler
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate
from langchain_openai import ChatOpenAI, OpenAI
langfuse = get_client()
# Initialize the Langfuse handler
langfuse_handler = CallbackHandler()
텍스트 프롬프트
langfuse_text_prompt = langfuse.get_prompt("movie-critic")
## Pass the langfuse_text_prompt to the PromptTemplate as metadata to link it to generations that use it
langchain_text_prompt = PromptTemplate.from_template(
langfuse_text_prompt.get_langchain_prompt(),
metadata={"langfuse_prompt": langfuse_text_prompt},
)
## Use the text prompt in a Langchain chain
llm = OpenAI()
completion_chain = langchain_text_prompt | llm
completion_chain.invoke({"movie": "Dune 2", "criticlevel": "expert"}, config={"callbacks": [langfuse_handler]})
채팅 프롬프트
langfuse_chat_prompt = langfuse.get_prompt("movie-critic-chat", type="chat")
## Manually set the metadata on the langchain_chat_prompt to link it to generations that use it
langchain_chat_prompt = ChatPromptTemplate.from_messages(
langfuse_chat_prompt.get_langchain_prompt()
)
langchain_chat_prompt.metadata = {"langfuse_prompt": langfuse_chat_prompt}
## or use the ChatPromptTemplate constructor directly.
## Note that using ChatPromptTemplate.from_template led to issues in the past
## See: https://github.com/langfuse/langfuse/issues/5374
langchain_chat_prompt = ChatPromptTemplate(
langfuse_chat_prompt.get_langchain_prompt(),
metadata={"langfuse_prompt": langfuse_chat_prompt}
)
## Use the chat prompt in a Langchain chain
chat_llm = ChatOpenAI()
chat_chain = langchain_chat_prompt | chat_llm
chat_chain.invoke({"movie": "Dune 2", "criticlevel": "expert"}, config={"callbacks": [langfuse_handler]})
PromptTemplate에서 with_config 메서드를 사용해 업데이트된 구성으로 새 Langchain Runnable을 만든다면 langfuse_prompt를 metadata 키에도 반드시 전달하세요.
langfuse_prompt 메타데이터 키는 PromptTemplate에만 설정하고, LLM 호출이나 체인의 다른 곳에는 추가로 설정하지 마세요.
트레이싱을 위해 OpenTelemetry를 이미 설정했는지 확인하세요.
Langchain (JS/TS)
import { LangfuseClient } from "@langfuse/client";
import { CallbackHandler } from "@langfuse/langchain";
import { PromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI, OpenAI } from "@langchain/openai";
const langfuseHandler = new CallbackHandler();
const langfuse = new LangfuseClient();
텍스트 프롬프트
const langfuseTextPrompt = await langfuse.prompt.get("movie-critic"); // Fetch a previously created text prompt
// Pass the langfuseTextPrompt to the PromptTemplate as metadata to link it to generations that use it
const langchainTextPrompt = PromptTemplate.fromTemplate(
langfuseTextPrompt.getLangchainPrompt()
).withConfig({
metadata: { langfusePrompt: langfuseTextPrompt },
});
const model = new OpenAI();
const chain = langchainTextPrompt.pipe(model);
await chain.invoke({ movie: "Dune 2", criticlevel: "expert" }, { callbacks: [langfuseHandler] });
채팅 프롬프트
const langfuseChatPrompt = await langfuse.prompt.get(
"movie-critic-chat",
{
type: "chat",
}
); // type option infers the prompt type as chat (default is 'text')
const langchainChatPrompt = ChatPromptTemplate.fromMessages(
langfuseChatPrompt.getLangchainPrompt().map((m) => [m.role, m.content])
).withConfig({
metadata: { langfusePrompt: langfuseChatPrompt },
});
const chatModel = new ChatOpenAI();
const chatChain = langchainChatPrompt.pipe(chatModel);
await chatChain.invoke({ movie: "Dune 2", criticlevel: "expert" }, { callbacks: [langfuseHandler] });
Vercel AI SDK
metadata 필드에 langfusePrompt 속성을 설정해 Langfuse 프롬프트를 Vercel AI SDK generation에 연결하세요:
import { generateText } from "ai";
import { LangfuseClient } from "@langfuse/client";
const langfuse = new LangfuseClient();
const fetchedPrompt = await langfuse.prompt.get("my-prompt");
const result = await generateText({
model: openai("gpt-4o"),
prompt: fetchedPrompt.prompt,
experimental_telemetry: {
isEnabled: true,
metadata: {
langfusePrompt: fetchedPrompt.toJSON(),
},
},
});
폴백 프롬프트를 사용하면 연결이 생성되지 않아요.
지표 레퍼런스
프롬프트를 트레이스에 연결하면 Langfuse가 프롬프트 버전별로 다음 지표를 자동으로 집계해요. Langfuse UI의 Metrics 탭에서 프롬프트 버전 간 비교할 수 있어요:
- 중앙값 세대 지연 (Median generation latency)
- 중앙값 세대 입력 토큰 (Median generation input tokens)
- 중앙값 세대 출력 토큰 (Median generation output tokens)
- 중앙값 세대 비용 (Median generation costs)
- 세대 수 (Generation count)
- 중앙값 점수 값
- 첫 번째 및 마지막 세대 타임스탬프