If your organization deploys DeepSeek models, here is how to prove you did your due diligence.
v0.7.9 RELEASED – DeepSeek adapter with R1 reasoning chain witnessing. Available on PyPI and npm.
Who this is for: Organizations deploying DeepSeek models (R1, V3, chat), compliance leads evaluating cross-border AI risk, legal teams assessing GPAI deployer obligations, and auditors reviewing AI supply chain governance.
Deploying a Chinese-origin GPAI creates specific regulatory obligations. DeepSeek's R1 and V3 models offer competitive performance at lower cost. But deploying a Chinese-origin GPAI model creates specific regulatory obligations under the EU AI Act's GPAI provisions (Art. 53–55). Your compliance team needs evidence that you assessed and governed these deployments -- regardless of where the model originated.
The EU AI Act places obligations on deployers, not only providers. If your organization integrates a GPAI model into a product or service -- regardless of who built that model -- you bear specific compliance responsibilities. The model's country of origin does not change whether these obligations apply. It changes the evidence burden required to satisfy them.
Here is what the EU AI Act requires of organizations deploying GPAI models:
| Article | Obligation | What It Means for Deployers |
|---|---|---|
| Art. 26(1) | Use AI in accordance with instructions | You must document how the model is used, confirm it operates within its intended purpose, and retain evidence of configuration decisions. |
| Art. 26(2) | Monitor AI system operation | You must implement ongoing monitoring for the AI system's behavior. Per-inference witnessing satisfies this directly. |
| Art. 26(5) | Keep logs generated by the AI system | Inference logs must be retained for the period specified by applicable law. Witness anchors provide tamper-evident log records. |
| Art. 53(1) | GPAI transparency requirements | Providers must supply technical documentation. Deployers must verify they received it and that their use is consistent with it. |
| Art. 55 | Systemic risk GPAI obligations | If the GPAI model is classified as posing systemic risk, additional model evaluation and incident reporting obligations apply to the provider -- but deployers must document their awareness of this classification. |
The core principle: you chose to deploy this model. You must prove governance. The provider's obligations are the provider's problem. Your obligations are yours. SWT3 creates the deployer-side evidence trail that proves you governed what you deployed.
This applies to every GPAI model, not only DeepSeek. The obligations above are model-agnostic. DeepSeek's cross-border data routing and content filtering behavior create additional considerations (covered in Sections 4 and 5), but the deployer obligation framework applies equally to GPT-4, Claude, Gemini, and any other GPAI.
DeepSeek exposes an OpenAI-compatible API. The SWT3 DeepSeek adapter wraps the standard OpenAI client pointed at DeepSeek's endpoint. Every inference call gets a witness anchor -- model ID, prompt hash, response hash, latency, token usage -- without changing your application code.
from openai import OpenAI
from swt3_ai import Witness
from swt3_ai.adapters.deepseek import wrap_deepseek
witness = Witness(
endpoint="https://your-instance.example.com/api/v1/witness",
api_key="axm_live_...",
tenant_id="YOUR_TENANT",
)
client = wrap_deepseek(
OpenAI(base_url="https://api.deepseek.com", api_key="sk-..."),
witness,
)
# Or: client = witness.wrap(OpenAI(base_url="https://api.deepseek.com", api_key="sk-..."))
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": "Summarize this contract clause."}],
)
witness.flush()
import OpenAI from 'openai';
import { Witness, wrapDeepSeek } from '@tenova/swt3-ai';
const witness = new Witness({
endpoint: 'https://your-instance.example.com/api/v1/witness',
apiKey: 'axm_live_...',
tenantId: 'YOUR_TENANT',
});
const client = wrapDeepSeek(
new OpenAI({ baseURL: 'https://api.deepseek.com', apiKey: 'sk-...' }),
witness,
);
// Or: const client = witness.wrap(new OpenAI({ baseURL: 'https://api.deepseek.com', apiKey: 'sk-...' }));
const response = await client.chat.completions.create({
model: 'deepseek-chat',
messages: [{ role: 'user', content: 'Summarize this contract clause.' }],
});
await witness.flush();
model_id: deepseek-chat or deepseek-reasoner -- the exact model identifier used for this call.
prompt_hash: SHA-256 of the input messages. Proves what was sent without storing the content.
response_hash: SHA-256 of the complete response body. Creates an immutable record of what the model returned.
latency_ms: Wall-clock inference time. Useful for detecting infrastructure changes or routing anomalies.
The anchor captures the exact model version string and response hash, creating an immutable record of what the model returned at that moment. If DeepSeek updates the model behind the same identifier (a common practice with API-served models), the response hash for identical prompts will change -- providing drift evidence without requiring the assessor to access the raw content.
DeepSeek's API supports the standard OpenAI message format, including role: "system" messages. The adapter extracts and hashes system prompts independently as system_prompt_hash, creating a separate governance signal for prompt configuration integrity.
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "You are a contract analyst. Flag any clause that limits liability below $1M."},
{"role": "user", "content": "Review Section 4.2 of this agreement."},
],
)
# system_prompt_hash captures the analyst instructions for this call
For DeepSeek deployments specifically, system prompt governance has an additional dimension: if the system prompt instructs the model to handle sensitive data categories (PII, financial terms, legal analysis), the system_prompt_hash proves those instructions were active at inference time. Combined with the CJT jurisdiction field (Section 4), this creates evidence that both the behavioral boundary and the jurisdictional context were governed for each call.
DeepSeek R1 is a reasoning model. It returns intermediate thinking tokens wrapped in <think>...</think> tags before the final answer. These reasoning chains reveal the model's step-by-step logic -- and they are part of the model's output.
response = client.chat.completions.create(
model="deepseek-reasoner",
messages=[{"role": "user", "content": "Solve: what is the derivative of x^3 + 2x?"}],
)
# response.choices[0].message.content contains:
# <think>Using the power rule, the derivative of x^3 is 3x^2
# and the derivative of 2x is 2. Combining these...</think>
# The derivative is 3x^2 + 2.
witness.flush()
The adapter hashes the COMPLETE response including thinking tokens. This means the reasoning chain is part of the cryptographic evidence. The <think> block and the final answer are hashed together as a single response body. Nothing is stripped or filtered before fingerprinting.
Why this matters: if DeepSeek modifies or censors the reasoning chain -- removing intermediate steps, altering the logic path, or suppressing certain reasoning patterns -- the response hash changes. Even if the final answer remains identical, a different reasoning chain produces a different hash. This creates tamper evidence at the reasoning level, not just the output level.
The witness anchor for an R1 call covers the full response: thinking tokens + final answer. This is a single hash, not two separate records.
Reasoning chain hashes provide evidence of model behavior transparency (or lack thereof). Compare response_hash values for identical prompts across a multi-day window. If hashes diverge while final answers remain the same, the model's reasoning path changed -- potentially indicating a silent model update, reasoning chain censorship, or content policy modification. This is evidence that would be invisible without decision-level witnessing.
Reasoning chains are model output, not model internals. SWT3 witnesses what the model returns to your application. It does not inspect, interpret, or evaluate the reasoning quality. The hash proves what was returned. Whether the reasoning is sound, complete, or modified is a separate analytical question for your AI governance team.
When you call the DeepSeek API at api.deepseek.com, your inference data routes to DeepSeek's infrastructure in China. This is a factual statement about the API's architecture, not a risk assessment -- your organization must make its own determination about whether this data routing is acceptable for your use case and jurisdiction.
The SWT3 adapter does not change data routing. It witnesses what happens at your application boundary: what was sent, what was returned, when, and which model served the response. The witness anchor is created at your endpoint, in your infrastructure. The adapter does not proxy, redirect, or intercept the API call itself.
Deployers are responsible for:
SWT3 CJT (Compliance Jurisdiction Tracking) fields allow you to record jurisdiction context directly in the witness record:
witness = Witness(
endpoint="https://your-instance.example.com/api/v1/witness",
api_key="axm_live_...",
tenant_id="YOUR_TENANT",
jurisdiction="DE",
legal_basis="legitimate_interest",
purpose_class="contract_analysis",
)
CJT fields (jurisdiction, legal_basis, purpose_class) are embedded in every witness anchor minted by this Witness instance. They survive all processing stages and are queryable in the ledger.
CJT fields in the witness record prove the deployer considered jurisdiction requirements at the time of deployment -- not retroactively. Query the ledger for jurisdiction and legal_basis values. If these fields are empty on DeepSeek inference anchors but populated on other provider anchors, it indicates the organization's cross-border governance was not applied consistently to this deployment.
DeepSeek may apply content filtering that modifies responses. This filtering can take several forms: outright refusal (visible via finish_reason), truncated responses, or silent content modification where the response is altered without any explicit signal in the API metadata.
The adapter handles the detectable case: when the API returns finish_reason="content_filter", the witness record sets has_refusal=true. This creates an automatic audit trail of explicit content policy interventions.
Silent modifications -- where the response content is altered but finish_reason remains "stop" -- are harder to detect in a single call. However, they are captured indirectly via the response hash. If you send identical prompts and receive different response hashes, something changed: the model weights, the content policy, the routing, or some combination. The hash difference is the evidence. The cause requires investigation.
SWT3 witnesses what was returned. It does not evaluate whether the content was modified. Detecting silent content modification requires comparing response hashes across identical prompts over time. The witness record provides the raw data for this analysis. Drawing conclusions from that data is a governance function, not a witnessing function.
DeepSeek publishes open weights for several models. Organizations running these weights locally -- via vLLM, Ollama, or other inference servers -- eliminate cross-border data routing entirely. The inference stays in your infrastructure.
Self-hosted deployments use the adapter that matches your inference server, not the DeepSeek API adapter:
# vLLM serving DeepSeek weights
from swt3_ai.adapters.vllm import wrap_vllm
client = wrap_vllm(
OpenAI(base_url="http://localhost:8000/v1", api_key="unused"),
witness,
)
# Ollama serving DeepSeek weights
from swt3_ai.adapters.ollama import wrap_ollama
client = wrap_ollama(
OpenAI(base_url="http://localhost:11434/v1", api_key="unused"),
witness,
)
| Deployment | Adapter | Data Residency | Provider Tag |
|---|---|---|---|
| DeepSeek API | wrap_deepseek |
DeepSeek infrastructure (China) | deepseek |
| vLLM (local) | wrap_vllm |
Your infrastructure | vllm |
| Ollama (local) | wrap_ollama |
Your infrastructure | ollama |
| Azure AI (hosted) | wrap_deepseek or witness.wrap() |
Azure region | deepseek |
Same witness evidence, different data residency posture. Self-hosted deployments produce the same anchor format as API deployments. The provider tag in the ledger distinguishes the two. An auditor can filter by provider to verify which deployments route data externally and which stay on-premises.
Every witness anchor from a DeepSeek deployment maps to specific regulatory obligations. The table below shows which evidence artifact satisfies which requirement:
| Obligation | Regulation | SWT3 Evidence | Procedure |
|---|---|---|---|
| Monitor AI system operation | EU AI Act Art. 26(2) | Per-inference witness anchor with model ID, response hash, latency | AI-INF.1 |
| Keep AI-generated logs | EU AI Act Art. 26(5) | Tamper-evident ledger with retention policy | AI-INF.1 |
| GPAI transparency | EU AI Act Art. 53 | Model version tracking via model_hash drift detection |
AI-INF.1 |
| Cross-border data transfer | GDPR Art. 44–49 | CJT fields (jurisdiction, legal_basis, purpose_class) in every anchor | AI-DATA.2 |
| Content filtering governance | EU AI Act Art. 14 (human oversight) | has_refusal flag on content-filtered responses |
AI-GRD.1 |
| AI risk management | NIST AI RMF MN 2.2 | Decision-level behavior tracking across inference population | AI-INF.1 |
| Model supply chain documentation | NIST AI RMF MAP 1.5 | Provider tag + model ID + data residency context per anchor | AI-SUPPLY.1 |
| Ongoing model monitoring | SR 11-7 / SR 26-2 | Response hash drift detection across identical prompts | AI-DRIFT.1 |
A complete deployer evidence chain for a DeepSeek deployment includes: (1) inference witnessing (AI-INF.1) proving ongoing monitoring, (2) CJT jurisdiction fields (AI-DATA.2) proving data residency assessment, (3) content filter detection (AI-GRD.1) proving awareness of provider-side filtering, and (4) model hash tracking (AI-DRIFT.1) proving you detect silent model changes.
Request a ledger export filtered by provider="deepseek" for the assessment period. Verify: (1) jurisdiction and legal_basis fields are populated on all anchors, (2) has_refusal values are present (confirming the adapter is detecting content filter events), (3) model_id is consistent with the organization's approved model list. If the organization claims they only use self-hosted weights but the ledger shows provider="deepseek" anchors, their stated architecture does not match observed behavior.
Three lines to deployer accountability.
# Python
pip install swt3-ai openai
# TypeScript
npm install @tenova/swt3-ai openai
from openai import OpenAI
from swt3_ai import Witness
witness = Witness(
endpoint="https://your-instance.example.com/api/v1/witness",
api_key="axm_live_...",
tenant_id="YOUR_TENANT",
jurisdiction="DE",
legal_basis="legitimate_interest",
purpose_class="contract_analysis",
)
client = witness.wrap(OpenAI(base_url="https://api.deepseek.com", api_key="sk-..."))
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": "Summarize this contract clause."}],
)
witness.flush()
# One anchor minted. Model ID, response hash, jurisdiction, legal basis -- all recorded.
Your application code is unchanged. The witness.wrap() call auto-detects DeepSeek via deepseek.com in the base URL. Every inference call from this point forward produces a witness anchor with full deployer accountability metadata.