OpenTelemetry instrumentation for DeepSeek - chat completions and reasoning models
Project description
TraceAI DeepSeek Instrumentation
OpenTelemetry instrumentation for DeepSeek - chat completions, reasoning models, and function calling.
Installation
pip install traceai-deepseek
Features
- Automatic tracing of DeepSeek API calls via OpenAI SDK
- Support for DeepSeek Chat, Coder, and Reasoner (R1) models
- Streaming response support
- Token usage tracking including prompt cache metrics
- Reasoning content extraction for R1 models
- Function/tool calling support
- Full OpenTelemetry semantic conventions compliance
Usage
Basic Setup
from openai import OpenAI
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
from traceai_deepseek import DeepSeekInstrumentor
# Set up tracing
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)
# Instrument DeepSeek
DeepSeekInstrumentor().instrument(tracer_provider=provider)
# Use DeepSeek via OpenAI SDK
client = OpenAI(
api_key="your-deepseek-api-key",
base_url="https://api.deepseek.com/v1"
)
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
DeepSeek Chat
from openai import OpenAI
client = OpenAI(
api_key="your-deepseek-api-key",
base_url="https://api.deepseek.com/v1"
)
# Simple chat
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is machine learning?"}
],
temperature=0.7,
max_tokens=1024
)
print(response.choices[0].message.content)
DeepSeek Reasoner (R1 Models)
DeepSeek R1 models provide reasoning capabilities with detailed thought processes.
from openai import OpenAI
client = OpenAI(
api_key="your-deepseek-api-key",
base_url="https://api.deepseek.com/v1"
)
# Using DeepSeek Reasoner
response = client.chat.completions.create(
model="deepseek-reasoner",
messages=[
{"role": "user", "content": "Solve this step by step: If a train travels 120 km in 2 hours, what is its average speed?"}
]
)
# Access the reasoning content (thought process)
message = response.choices[0].message
print("Reasoning:", message.reasoning_content)
print("Answer:", message.content)
# Token usage includes reasoning tokens
print(f"Reasoning tokens: {response.usage.completion_tokens_details.reasoning_tokens}")
Streaming Responses
from openai import OpenAI
client = OpenAI(
api_key="your-deepseek-api-key",
base_url="https://api.deepseek.com/v1"
)
# Streaming chat
stream = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": "Tell me a story"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
print()
# Streaming with R1 (includes reasoning)
stream = client.chat.completions.create(
model="deepseek-reasoner",
messages=[{"role": "user", "content": "What is 15% of 240?"}],
stream=True
)
reasoning_content = ""
content = ""
for chunk in stream:
delta = chunk.choices[0].delta
if hasattr(delta, 'reasoning_content') and delta.reasoning_content:
reasoning_content += delta.reasoning_content
if delta.content:
content += delta.content
print("Reasoning:", reasoning_content)
print("Answer:", content)
Function Calling / Tools
from openai import OpenAI
import json
client = OpenAI(
api_key="your-deepseek-api-key",
base_url="https://api.deepseek.com/v1"
)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["location"]
}
}
}
]
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": "What's the weather in Paris?"}],
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
if message.tool_calls:
for tool_call in message.tool_calls:
print(f"Function: {tool_call.function.name}")
print(f"Arguments: {tool_call.function.arguments}")
Async Usage
import asyncio
from openai import AsyncOpenAI
async def main():
client = AsyncOpenAI(
api_key="your-deepseek-api-key",
base_url="https://api.deepseek.com/v1"
)
response = await client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
asyncio.run(main())
JSON Mode
from openai import OpenAI
client = OpenAI(
api_key="your-deepseek-api-key",
base_url="https://api.deepseek.com/v1"
)
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "Output valid JSON only."},
{"role": "user", "content": "List 3 programming languages with their main use cases"}
],
response_format={"type": "json_object"}
)
import json
data = json.loads(response.choices[0].message.content)
print(data)
Configuration Options
TraceConfig
from fi_instrumentation import TraceConfig
from traceai_deepseek import DeepSeekInstrumentor
config = TraceConfig(
hide_inputs=False,
hide_outputs=False,
)
DeepSeekInstrumentor().instrument(
tracer_provider=provider,
config=config
)
Captured Attributes
Common Attributes
| Attribute | Description |
|---|---|
fi.span.kind |
"LLM" |
llm.system |
"deepseek" |
llm.provider |
"deepseek" |
llm.model |
Model name (deepseek-chat, deepseek-reasoner, etc.) |
llm.token_count.prompt |
Input token count |
llm.token_count.completion |
Output token count |
llm.token_count.total |
Total token count |
DeepSeek-Specific Attributes
| Attribute | Description |
|---|---|
deepseek.response_id |
Unique response ID |
deepseek.finish_reason |
Response finish reason (stop, tool_calls, length) |
deepseek.prompt_cache_hit_tokens |
Tokens served from cache |
deepseek.prompt_cache_miss_tokens |
Tokens not in cache |
deepseek.reasoning_tokens |
Tokens used for reasoning (R1 models) |
deepseek.reasoning_content |
Full reasoning text (R1 models) |
deepseek.tool_calls_count |
Number of tool calls |
deepseek.tools_count |
Number of tools provided |
Available Models
| Model | Description |
|---|---|
deepseek-chat |
General chat model |
deepseek-coder |
Code-focused model |
deepseek-reasoner |
Reasoning model (R1) with chain-of-thought |
Prompt Caching
DeepSeek supports prompt caching to reduce costs and latency for repeated prompts. The instrumentation tracks cache hit/miss metrics:
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "You are a helpful assistant."}, # Cached
{"role": "user", "content": "Hello!"}
]
)
# Access cache metrics from usage
print(f"Cache hits: {response.usage.prompt_cache_hit_tokens}")
print(f"Cache misses: {response.usage.prompt_cache_miss_tokens}")
Important Notes
-
OpenAI SDK Required: DeepSeek uses the OpenAI-compatible API, so you need the
openaipackage installed. -
Base URL: Always set
base_url="https://api.deepseek.com/v1"when creating the client. -
API Key: Get your API key from the DeepSeek Platform.
-
Selective Instrumentation: The instrumentor only traces calls to DeepSeek's API. Regular OpenAI API calls are not affected.
-
R1 Models: When using
deepseek-reasoner, thereasoning_contentfield contains the model's thought process before the final answer.
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file traceai_deepseek-0.1.0.tar.gz.
File metadata
- Download URL: traceai_deepseek-0.1.0.tar.gz
- Upload date:
- Size: 11.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
defb6770f46edd90df57cfffee27f1d7ff5670fd434089c75384a99c51951742
|
|
| MD5 |
08425714d2a116a69700a01439e17ab5
|
|
| BLAKE2b-256 |
a6d5b846b0d67033a05cedd99e42fd9a8efd292ed134f9358ac9b7bb8215c65b
|
File details
Details for the file traceai_deepseek-0.1.0-py3-none-any.whl.
File metadata
- Download URL: traceai_deepseek-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0faf9da9d7e5f7c81144d3c8fcb2460eff3693667f9ba9751f202ed3998acf58
|
|
| MD5 |
244ca39505e43b8d2486b0bbfc878237
|
|
| BLAKE2b-256 |
1fe78b33ac9a713e7e943e480e70b76ac56e5d8c453a1b0c3359e7f78ca912f1
|