Skip to content

Getting started — semantic-tracing

Install

Packages are hosted on the internal Ramboll Artifactory registry. Authenticate once via ~/.netrc:

machine artifactory.ramboll.com
  login    <your-email-or-empty-string>
  password <your-artifactory-token>

Generate a personal access token in the Artifactory UI under Edit Profile → Authentication Settings.

Declare the Artifactory index in your project's uv.toml (uv reads ~/.netrc automatically). Omitting default = true keeps PyPI as the default for all other dependencies:

[[index]]
name = "ramtech-pypi"
url  = "https://artifactory.ramboll.com/artifactory/api/pypi/ramtech-pypi-internal/simple"

Then add the package:

uv add semantic-tracing

Or install without modifying uv.toml using --extra-index-url:

# uv
uv add semantic-tracing --extra-index-url https://artifactory.ramboll.com/artifactory/api/pypi/ramtech-pypi-internal/simple

# pip
pip install semantic-tracing \
  --extra-index-url https://artifactory.ramboll.com/artifactory/api/pypi/ramtech-pypi-internal/simple

Environment variables

setup_tracing() reads these from the environment at call time:

Variable Required Description
LANGFUSE_SECRET_KEY yes Secret key from your Langfuse project settings
LANGFUSE_PUBLIC_KEY yes Public key from your Langfuse project settings
LANGFUSE_BASE_URL no Langfuse instance URL; defaults to https://cloud.langfuse.com. The Langfuse SDK still reads the older LANGFUSE_HOST as a deprecated fallback, only when LANGFUSE_BASE_URL is unset

Store these in a .env file at the project root and load with python-dotenv or pass them as environment variables directly.

Minimal example

import asyncio
from semantic_tracing import flush, setup_tracing, step, update_current_step

setup_tracing(service_name="my-app", environment="development")

@step("answer_question", as_type="generation")
async def answer(query: str) -> str:
    # Replace with your actual LLM call
    result = await call_llm(query)
    # Attach model and token usage to the span (optional)
    update_current_step(model="gpt-4o", usage={"input": 100, "output": 50})
    return result

async def main() -> None:
    response = await answer("What is the capital of Denmark?")
    print(response)
    flush()  # send buffered spans to Langfuse before process exit

asyncio.run(main())

This creates one trace with one child span in Langfuse. The span type "generation" tells Langfuse to display token usage and model information in the UI.

Nesting spans

Calls to @step-decorated functions inside other @step functions form a parent–child tree automatically via OTel context propagation — no manual wiring needed:

@step("retrieve_documents")
async def retrieve(query: str) -> list[str]:
    return await vector_search(query)

@step("generate_answer", as_type="generation")
async def generate(query: str, docs: list[str]) -> str:
    return await call_llm(query, context=docs)

@step("rag_pipeline")
async def rag(query: str) -> str:
    docs = await retrieve(query)           # child span
    return await generate(query, docs)    # child span

Reading traces back

After a trace is complete, trace_reader helpers retrieve structured data from Langfuse — useful in offline evaluation predictors:

from semantic_tracing.trace_reader import fetch_trace, find_observations

trace = await fetch_trace(trace_id)
# find specific observations by name
steps = find_observations(trace, name_in={"answer_question"})

Reading these docs from the installed package

The package carries these pages as they were when the installed version was built, so they can be read without a network or a checkout of this repository:

uv run python -m semantic_tracing.docs list            # every page, by name and title
uv run python -m semantic_tracing.docs show tracing-setup
uv run python -m semantic_tracing.docs path            # where the files are

A project that also installs semantic-evaluation has eval-docs, which reads these pages as well and can search them. In show output, a link to page:<name> is another shipped page and repo:<path> is a file in the SDK's source repository that is not shipped.

Full reference