gateforge-sdk 0.2.5__tar.gz → 0.2.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gateforge_sdk-0.2.7/PKG-INFO +624 -0
- gateforge_sdk-0.2.7/README.md +575 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/__init__.py +16 -11
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/client.py +1 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/features/__init__.py +3 -0
- gateforge_sdk-0.2.7/gateforge/prompt.py +537 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/wrappers/gemini.py +58 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/pyproject.toml +2 -2
- gateforge_sdk-0.2.7/tests/test_phase3.py +630 -0
- gateforge_sdk-0.2.5/PKG-INFO +0 -666
- gateforge_sdk-0.2.5/README.md +0 -617
- gateforge_sdk-0.2.5/gateforge/prompt.py +0 -46
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/.env.example +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/.gitignore +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/.pypirc.example +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/INSTALL.md +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/LICENSE +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/MANIFEST.in +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/PUBLISHING.md +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/PUBLISH_NOW.md +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/ab/__init__.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/ab/engine.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/config.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/context.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/guardrails/__init__.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/guardrails/engine.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/metrics.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/options.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/pii.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/pricing.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/providers/__init__.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/providers/anthropic.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/providers/gemini.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/providers/openai.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/response.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/session_manager.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/tracing.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/wrappers/__init__.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/wrappers/anthropic.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/gateforge/wrappers/openai.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/tests/__init__.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/tests/test_metrics.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/tests/test_phase1.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/tests/test_phase2.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/tests/test_pii.py +0 -0
- {gateforge_sdk-0.2.5 → gateforge_sdk-0.2.7}/tests/test_providers.py +0 -0
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gateforge-sdk
|
|
3
|
+
Version: 0.2.7
|
|
4
|
+
Summary: Privacy-first LLMOps SDK — Auto-init, decorators, session management, prompt system with cache
|
|
5
|
+
Project-URL: Homepage, https://gateforge.dev
|
|
6
|
+
Project-URL: Documentation, https://gateforge.dev/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/gateforge/gateforge-sdk
|
|
8
|
+
Project-URL: Dashboard, https://app.gateforge.dev
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/gateforge/gateforge-sdk/issues
|
|
10
|
+
Author-email: Gateforge Team <support@gateforge.dev>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: anthropic,gemini,llm,llmops,mlops,openai,pii,privacy
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: httpx>=0.27.0
|
|
25
|
+
Requires-Dist: pii-firewall[langdetect,presidio,transformers]
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: anthropic>=0.40.0; extra == 'all'
|
|
28
|
+
Requires-Dist: google-genai>=1.0.0; extra == 'all'
|
|
29
|
+
Requires-Dist: openai>=1.0.0; extra == 'all'
|
|
30
|
+
Requires-Dist: opentelemetry-api>=1.20.0; extra == 'all'
|
|
31
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20.0; extra == 'all'
|
|
32
|
+
Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'all'
|
|
33
|
+
Provides-Extra: anthropic
|
|
34
|
+
Requires-Dist: anthropic>=0.40.0; extra == 'anthropic'
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: build>=1.0.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: twine>=5.0.0; extra == 'dev'
|
|
40
|
+
Provides-Extra: gemini
|
|
41
|
+
Requires-Dist: google-genai>=1.0.0; extra == 'gemini'
|
|
42
|
+
Provides-Extra: openai
|
|
43
|
+
Requires-Dist: openai>=1.0.0; extra == 'openai'
|
|
44
|
+
Provides-Extra: otel
|
|
45
|
+
Requires-Dist: opentelemetry-api>=1.20.0; extra == 'otel'
|
|
46
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20.0; extra == 'otel'
|
|
47
|
+
Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'otel'
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# Gateforge SDK (Python)
|
|
51
|
+
|
|
52
|
+
**Privacy-first LLMOps SDK** — Transparent client wrapping with automatic PII masking, cost tracking, A/B testing, guardrails, agent tracing, and prompt management.
|
|
53
|
+
|
|
54
|
+
[](https://www.python.org/downloads/)
|
|
55
|
+
[](https://pypi.org/project/gateforge-sdk/)
|
|
56
|
+
[](LICENSE)
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## What it does
|
|
61
|
+
|
|
62
|
+
Gateforge wraps your existing provider client (OpenAI, Anthropic, Gemini) with a transparent proxy. Your code is unchanged — the SDK intercepts each call to run the full pipeline locally:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
Your code
|
|
66
|
+
│
|
|
67
|
+
▼
|
|
68
|
+
pre-call → A/B variant selection → system prompt injection
|
|
69
|
+
→ PII anonymize (local)
|
|
70
|
+
→ input guardrail check
|
|
71
|
+
│
|
|
72
|
+
▼
|
|
73
|
+
LLM provider (sees masked content only)
|
|
74
|
+
│
|
|
75
|
+
▼
|
|
76
|
+
post-call → PII rehydrate (local)
|
|
77
|
+
→ output guardrail check
|
|
78
|
+
→ cost + latency compute
|
|
79
|
+
→ span emission (metadata only)
|
|
80
|
+
│
|
|
81
|
+
▼
|
|
82
|
+
Your code receives: original PII restored, guardrails applied
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Content never leaves your environment.** Only metadata (tokens, cost, latency, PII types) is sent to Gateforge.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Installation
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pip install gateforge-sdk
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
With provider extras:
|
|
96
|
+
```bash
|
|
97
|
+
pip install gateforge-sdk[openai] # OpenAI only
|
|
98
|
+
pip install gateforge-sdk[anthropic] # Anthropic only
|
|
99
|
+
pip install gateforge-sdk[gemini] # Google Gemini only
|
|
100
|
+
pip install gateforge-sdk[all] # All providers
|
|
101
|
+
pip install gateforge-sdk[dev] # Development tools
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Get your API key at [https://app.gateforge.dev/dashboard/keys](https://app.gateforge.dev/dashboard/keys).
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Quick Start
|
|
109
|
+
|
|
110
|
+
### Option 1: Auto-Init (Recommended)
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
import gateforge
|
|
114
|
+
|
|
115
|
+
# Auto-initialize from environment variables
|
|
116
|
+
# Reads: GATEFORGE_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY
|
|
117
|
+
gateforge.auto_init()
|
|
118
|
+
|
|
119
|
+
# Now you can use providers directly
|
|
120
|
+
from openai import OpenAI
|
|
121
|
+
client = OpenAI(api_key="sk-...") # Works without explicit wrapping!
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Option 2: Manual Init with Wrapping
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
import gateforge
|
|
128
|
+
from openai import OpenAI
|
|
129
|
+
|
|
130
|
+
gateforge.init(api_key="gf-live-YOUR_KEY")
|
|
131
|
+
|
|
132
|
+
# Wrap your client
|
|
133
|
+
client = gateforge.wrap_openai(OpenAI(api_key="sk-..."))
|
|
134
|
+
|
|
135
|
+
# Use exactly as before — pipeline runs automatically
|
|
136
|
+
response = client.chat.completions.create(
|
|
137
|
+
model="gpt-4o-mini",
|
|
138
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
139
|
+
)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Option 3: Auto-Detection
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
import gateforge
|
|
146
|
+
from openai import OpenAI
|
|
147
|
+
from anthropic import Anthropic
|
|
148
|
+
from google import genai
|
|
149
|
+
|
|
150
|
+
gateforge.init(api_key="gf-live-...")
|
|
151
|
+
|
|
152
|
+
# Auto-detects provider
|
|
153
|
+
client1 = gateforge.wrap(OpenAI(api_key="sk-..."))
|
|
154
|
+
client2 = gateforge.wrap(Anthropic(api_key="sk-ant-..."))
|
|
155
|
+
client3 = gateforge.wrap(genai.Client(api_key="AIza-..."))
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Key Features
|
|
161
|
+
|
|
162
|
+
### 1. Auto-Initialization
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
import gateforge
|
|
166
|
+
|
|
167
|
+
# Set environment variables:
|
|
168
|
+
# export GATEFORGE_API_KEY=gf-live-xxx
|
|
169
|
+
# export OPENAI_API_KEY=sk-xxx
|
|
170
|
+
|
|
171
|
+
gateforge.auto_init(enable_pii=False, enable_guardrails=False)
|
|
172
|
+
# Privacy-first: PII and guardrails disabled by default
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 2. Decorator-Based Tracing
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
import gateforge
|
|
179
|
+
|
|
180
|
+
# Tool with automatic tracing
|
|
181
|
+
@gateforge.tool()
|
|
182
|
+
def get_weather(location: str) -> str:
|
|
183
|
+
import requests
|
|
184
|
+
return requests.get(f"https://wttr.in/{location}?format=3").text
|
|
185
|
+
|
|
186
|
+
# Agent with automatic tracing
|
|
187
|
+
@gateforge.agent()
|
|
188
|
+
def weather_agent(message: str) -> str:
|
|
189
|
+
return get_weather("Madrid")
|
|
190
|
+
|
|
191
|
+
# Session to group multiple calls
|
|
192
|
+
with gateforge.session(user_id="user-123"):
|
|
193
|
+
response = weather_agent("What's the weather?")
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 3. Conversation Management
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
from gateforge import SessionManager, trace
|
|
200
|
+
|
|
201
|
+
# Manage sessions
|
|
202
|
+
manager = SessionManager()
|
|
203
|
+
session = manager.create_session(
|
|
204
|
+
user_id="user-123",
|
|
205
|
+
tags=["weather-chat"],
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# Use in trace
|
|
209
|
+
with trace(conversation_id=session.conversation_id):
|
|
210
|
+
response = run_agent(message)
|
|
211
|
+
|
|
212
|
+
# Track activity
|
|
213
|
+
manager.touch(session.conversation_id)
|
|
214
|
+
session.set_metadata("last_model", "gpt-4o-mini")
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 4. Prompt System
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
from gateforge import Prompt, PromptBuilder, PromptCache
|
|
221
|
+
|
|
222
|
+
# Create prompt with variables
|
|
223
|
+
prompt = Prompt(
|
|
224
|
+
name="greeting",
|
|
225
|
+
content="Hello, {{name}}! You are {{role}}.",
|
|
226
|
+
variables={"name": "User", "role": "a developer"},
|
|
227
|
+
)
|
|
228
|
+
rendered = prompt.render(name="Alice") # "Hello, Alice!..."
|
|
229
|
+
|
|
230
|
+
# Compose prompts
|
|
231
|
+
builder = PromptBuilder()
|
|
232
|
+
builder.add_system("You are helpful")
|
|
233
|
+
builder.add_user("What's the weather?")
|
|
234
|
+
builder.add_variable("location", "Madrid")
|
|
235
|
+
prompt = builder.build()
|
|
236
|
+
|
|
237
|
+
# Cache prompts (memory + file + backend)
|
|
238
|
+
cache = PromptCache(memory_ttl=300, file_ttl=3600)
|
|
239
|
+
cache.set(prompt)
|
|
240
|
+
retrieved = cache.get("greeting")
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Provider Wrappers
|
|
246
|
+
|
|
247
|
+
All wrappers are transparent — input params and return types match the underlying SDK.
|
|
248
|
+
|
|
249
|
+
### OpenAI
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
import gateforge
|
|
253
|
+
from openai import OpenAI, AsyncOpenAI
|
|
254
|
+
|
|
255
|
+
gateforge.init(api_key="gf-live-...")
|
|
256
|
+
|
|
257
|
+
# Sync
|
|
258
|
+
client = gateforge.wrap_openai(OpenAI(api_key="sk-..."))
|
|
259
|
+
response = client.chat.completions.create(
|
|
260
|
+
model="gpt-4o-mini",
|
|
261
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
# Async
|
|
265
|
+
async_client = gateforge.wrap_openai(AsyncOpenAI(api_key="sk-..."))
|
|
266
|
+
response = await async_client.chat.completions.create(...)
|
|
267
|
+
|
|
268
|
+
# Streaming
|
|
269
|
+
for chunk in client.chat.completions.create(..., stream=True):
|
|
270
|
+
print(chunk.choices[0].delta.content, end="")
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Anthropic
|
|
274
|
+
|
|
275
|
+
```python
|
|
276
|
+
import gateforge
|
|
277
|
+
from anthropic import Anthropic
|
|
278
|
+
|
|
279
|
+
client = gateforge.wrap_anthropic(Anthropic(api_key="sk-ant-..."))
|
|
280
|
+
response = client.messages.create(
|
|
281
|
+
model="claude-haiku-4-5",
|
|
282
|
+
max_tokens=512,
|
|
283
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
284
|
+
)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Gemini
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
import gateforge
|
|
291
|
+
from google import genai
|
|
292
|
+
|
|
293
|
+
client = gateforge.wrap_gemini(genai.Client(api_key="AIza-..."))
|
|
294
|
+
response = client.models.generate_content(
|
|
295
|
+
model="gemini-2.5-flash",
|
|
296
|
+
contents=[{"role": "user", "parts": [{"text": "Hello!"}]}],
|
|
297
|
+
)
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Agent Tracing
|
|
303
|
+
|
|
304
|
+
### Basic Multi-Step Trace
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
import gateforge
|
|
308
|
+
from openai import OpenAI
|
|
309
|
+
|
|
310
|
+
gateforge.init(api_key="gf-live-...")
|
|
311
|
+
client = gateforge.wrap_openai(OpenAI(api_key="sk-..."))
|
|
312
|
+
|
|
313
|
+
with gateforge.trace(conversation_id="conv_abc123"):
|
|
314
|
+
# Each LLM call gets auto-incremented step number
|
|
315
|
+
r1 = client.chat.completions.create(...) # step 1
|
|
316
|
+
r2 = client.chat.completions.create(...) # step 2
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Agent with Tool Calls
|
|
320
|
+
|
|
321
|
+
```python
|
|
322
|
+
import gateforge
|
|
323
|
+
|
|
324
|
+
@gateforge.tool()
|
|
325
|
+
def search_flights(destination: str, date: str) -> list:
|
|
326
|
+
...
|
|
327
|
+
|
|
328
|
+
@gateforge.tool()
|
|
329
|
+
def book_flight(flight_id: str, passenger: str) -> str:
|
|
330
|
+
...
|
|
331
|
+
|
|
332
|
+
@gateforge.agent()
|
|
333
|
+
def travel_agent(request: str) -> str:
|
|
334
|
+
flights = search_flights("Paris", "2026-06-10")
|
|
335
|
+
confirmation = book_flight(flights[0]["id"], "John Doe")
|
|
336
|
+
return f"Booked: {confirmation}"
|
|
337
|
+
|
|
338
|
+
# All tool calls automatically traced
|
|
339
|
+
with gateforge.session(user_id="user-123"):
|
|
340
|
+
response = travel_agent("Book me a flight to Paris")
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Session Management
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
from gateforge import SessionManager, get_current_conversation_id
|
|
347
|
+
|
|
348
|
+
manager = SessionManager()
|
|
349
|
+
|
|
350
|
+
# Create session
|
|
351
|
+
session = manager.create_session(user_id="user-123")
|
|
352
|
+
|
|
353
|
+
# Get current conversation from active trace
|
|
354
|
+
cid = get_current_conversation_id()
|
|
355
|
+
|
|
356
|
+
# List sessions
|
|
357
|
+
sessions = manager.list_sessions(user_id="user-123", limit=10)
|
|
358
|
+
|
|
359
|
+
# Serialize for persistence
|
|
360
|
+
data = manager.to_dict() # Save to DB
|
|
361
|
+
manager2 = SessionManager.from_dict(data) # Load
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## A/B Testing
|
|
367
|
+
|
|
368
|
+
```python
|
|
369
|
+
from gateforge import CallOptions
|
|
370
|
+
|
|
371
|
+
response = client.chat.completions.create(
|
|
372
|
+
model="gpt-4o-mini",
|
|
373
|
+
messages=[{"role": "user", "content": "Help me write an email"}],
|
|
374
|
+
gateforge_options=CallOptions(
|
|
375
|
+
experiment_id="exp_email_v2",
|
|
376
|
+
session_id="user_123", # Deterministic variant
|
|
377
|
+
),
|
|
378
|
+
)
|
|
379
|
+
# Variant A or B injected automatically
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## Guardrails
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
from gateforge import CallOptions, GuardrailBlocked
|
|
388
|
+
|
|
389
|
+
try:
|
|
390
|
+
response = client.chat.completions.create(
|
|
391
|
+
model="gpt-4o-mini",
|
|
392
|
+
messages=[{"role": "user", "content": "..."}],
|
|
393
|
+
gateforge_options=CallOptions(guardrails=True),
|
|
394
|
+
)
|
|
395
|
+
except GuardrailBlocked as e:
|
|
396
|
+
print(f"Blocked by rule: {e.rule_id}")
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## PII Protection
|
|
402
|
+
|
|
403
|
+
### Detected Entities
|
|
404
|
+
|
|
405
|
+
| Category | Examples |
|
|
406
|
+
|----------|----------|
|
|
407
|
+
| **Personal** | Names, emails, phones, addresses |
|
|
408
|
+
| **Financial** | Credit cards, bank accounts, SSN |
|
|
409
|
+
| **Healthcare** | Medical records, symptoms, diagnoses |
|
|
410
|
+
| **Technical** | IP addresses, URLs, API keys |
|
|
411
|
+
| **Custom** | Your own regex patterns |
|
|
412
|
+
|
|
413
|
+
### Direct Anonymization
|
|
414
|
+
|
|
415
|
+
```python
|
|
416
|
+
import gateforge
|
|
417
|
+
|
|
418
|
+
result = gateforge.anonymize("My email is john@example.com")
|
|
419
|
+
print(result["sanitized"]) # "My email is [EMAIL_001]"
|
|
420
|
+
print(result["entities"]) # ["EMAIL"]
|
|
421
|
+
|
|
422
|
+
original = gateforge.rehydrate("[EMAIL_001]", context=result["context"])
|
|
423
|
+
print(original) # "john@example.com"
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## CallOptions Reference
|
|
429
|
+
|
|
430
|
+
```python
|
|
431
|
+
from gateforge import CallOptions
|
|
432
|
+
|
|
433
|
+
response = client.chat.completions.create(
|
|
434
|
+
model="gpt-4o-mini",
|
|
435
|
+
messages=[...],
|
|
436
|
+
gateforge_options=CallOptions(
|
|
437
|
+
# Trace grouping
|
|
438
|
+
conversation_id="conv_abc",
|
|
439
|
+
|
|
440
|
+
# A/B testing
|
|
441
|
+
experiment_id="exp_abc",
|
|
442
|
+
session_id="user_123",
|
|
443
|
+
|
|
444
|
+
# Feature overrides
|
|
445
|
+
pii=True,
|
|
446
|
+
guardrails=True,
|
|
447
|
+
track_cost=False,
|
|
448
|
+
),
|
|
449
|
+
)
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## API Reference
|
|
455
|
+
|
|
456
|
+
### Initialization
|
|
457
|
+
|
|
458
|
+
| Function | Description |
|
|
459
|
+
|----------|-------------|
|
|
460
|
+
| `gateforge.init(api_key, ...)` | Manual initialization |
|
|
461
|
+
| `gateforge.auto_init()` | Auto from environment |
|
|
462
|
+
|
|
463
|
+
### Wrapping
|
|
464
|
+
|
|
465
|
+
| Function | Description |
|
|
466
|
+
|----------|-------------|
|
|
467
|
+
| `gateforge.wrap(client)` | Auto-detect provider |
|
|
468
|
+
| `gateforge.wrap_openai(client)` | Wrap OpenAI |
|
|
469
|
+
| `gateforge.wrap_anthropic(client)` | Wrap Anthropic |
|
|
470
|
+
| `gateforge.wrap_gemini(client)` | Wrap Gemini |
|
|
471
|
+
|
|
472
|
+
### Tracing
|
|
473
|
+
|
|
474
|
+
| Function | Description |
|
|
475
|
+
|----------|-------------|
|
|
476
|
+
| `gateforge.trace(conversation_id)` | Context manager for traces |
|
|
477
|
+
| `gateforge.continue_session(id)` | Resume existing conversation |
|
|
478
|
+
| `gateforge.session(user_id)` | Session context manager |
|
|
479
|
+
| `gateforge.tool()` | Decorator for tool tracing |
|
|
480
|
+
| `gateforge.agent()` | Decorator for agent tracing |
|
|
481
|
+
|
|
482
|
+
### Session Management
|
|
483
|
+
|
|
484
|
+
| Function | Description |
|
|
485
|
+
|----------|-------------|
|
|
486
|
+
| `SessionManager()` | Create session manager |
|
|
487
|
+
| `manager.create_session()` | Create new session |
|
|
488
|
+
| `manager.get_session(id)` | Get existing session |
|
|
489
|
+
| `manager.list_sessions()` | List with filters |
|
|
490
|
+
| `get_current_conversation_id()` | Get active trace ID |
|
|
491
|
+
| `get_current_trace_info()` | Get full trace info |
|
|
492
|
+
|
|
493
|
+
### Prompts
|
|
494
|
+
|
|
495
|
+
| Function | Description |
|
|
496
|
+
|----------|-------------|
|
|
497
|
+
| `Prompt(...)` | Create prompt |
|
|
498
|
+
| `PromptBuilder()` | Compose prompts |
|
|
499
|
+
| `PromptCache()` | Multi-level cache |
|
|
500
|
+
| `gateforge.get_prompt(name)` | Get from cache/backend |
|
|
501
|
+
| `gateforge.set_prompt(prompt)` | Set in cache |
|
|
502
|
+
|
|
503
|
+
### Utilities
|
|
504
|
+
|
|
505
|
+
| Function | Description |
|
|
506
|
+
|----------|-------------|
|
|
507
|
+
| `gateforge.anonymize(text)` | Anonymize PII |
|
|
508
|
+
| `gateforge.rehydrate(text, ctx)` | Restore PII |
|
|
509
|
+
| `gateforge.track_metrics(data)` | Send metadata |
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## Supported Models
|
|
514
|
+
|
|
515
|
+
### OpenAI
|
|
516
|
+
- GPT-4o, GPT-4o-mini
|
|
517
|
+
- GPT-4.1, GPT-4.1-mini, GPT-4.1-nano
|
|
518
|
+
|
|
519
|
+
### Anthropic
|
|
520
|
+
- Claude Haiku 4-5
|
|
521
|
+
- Claude Sonnet 4-5
|
|
522
|
+
- Claude Opus 4
|
|
523
|
+
|
|
524
|
+
### Google Gemini
|
|
525
|
+
- Gemini 2.5 Flash
|
|
526
|
+
- Gemini 2.5 Pro
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
## Dashboard
|
|
531
|
+
|
|
532
|
+
[https://app.gateforge.dev/dashboard](https://app.gateforge.dev/dashboard)
|
|
533
|
+
|
|
534
|
+
- Request volume and trends
|
|
535
|
+
- Cost breakdown by model/provider
|
|
536
|
+
- Latency analytics
|
|
537
|
+
- PII detection statistics
|
|
538
|
+
- A/B experiment results
|
|
539
|
+
- Guardrail violation alerts
|
|
540
|
+
- Agent waterfall traces
|
|
541
|
+
- API key management
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## Changelog
|
|
546
|
+
|
|
547
|
+
### 0.2.6 (2026-06-07) - Phase 3 Complete
|
|
548
|
+
- ✅ `Prompt` class with variables and rendering
|
|
549
|
+
- ✅ `PromptCache` with multi-level caching (memory + file)
|
|
550
|
+
- ✅ `PromptBuilder` for prompt composition
|
|
551
|
+
- ✅ `get_prompt()` / `set_prompt()` helpers
|
|
552
|
+
- ✅ 40 tests for Phase 3 features
|
|
553
|
+
|
|
554
|
+
### 0.2.5 (2026-06-07) - Phase 2 Complete
|
|
555
|
+
- ✅ `SessionManager` for session lifecycle
|
|
556
|
+
- ✅ `SessionState` with metadata, tags, timestamps
|
|
557
|
+
- ✅ `get_current_conversation_id()` helper
|
|
558
|
+
- ✅ `get_current_trace_info()` helper
|
|
559
|
+
- ✅ Conversation threading support
|
|
560
|
+
- ✅ 35 tests for Phase 2 features
|
|
561
|
+
|
|
562
|
+
### 0.2.4 (2026-06-07)
|
|
563
|
+
- ✅ Fixed `@agent()` to use active conversation_id when nested
|
|
564
|
+
- ✅ Added `nested` metadata for agent events
|
|
565
|
+
|
|
566
|
+
### 0.2.3 (2026-06-07) - Phase 1 Complete
|
|
567
|
+
- ✅ `auto_init()` for environment-based initialization
|
|
568
|
+
- ✅ `@gateforge.tool()` decorator
|
|
569
|
+
- ✅ `@gateforge.agent()` decorator
|
|
570
|
+
- ✅ `gateforge.session()` context manager
|
|
571
|
+
- ✅ 24 tests for Phase 1 features
|
|
572
|
+
|
|
573
|
+
### 0.2.2 and earlier
|
|
574
|
+
- Auto-download spaCy model
|
|
575
|
+
- PII firewall integration
|
|
576
|
+
- Provider wrappers (OpenAI, Anthropic, Gemini)
|
|
577
|
+
- A/B testing, guardrails, tracing
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
## Documentation
|
|
582
|
+
|
|
583
|
+
- [Phase 1 Complete](https://github.com/gateforge/gateforge-sdk/blob/main/PHASE1_COMPLETE.md)
|
|
584
|
+
- [Phase 2 Complete](https://github.com/gateforge/gateforge-sdk/blob/main/PHASE2_COMPLETE.md)
|
|
585
|
+
- [Phase 3 Complete](https://github.com/gateforge/gateforge-sdk/blob/main/PHASE3_COMPLETE.md)
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
## Troubleshooting
|
|
590
|
+
|
|
591
|
+
**`ImportError: No module named 'gateforge'`**
|
|
592
|
+
```bash
|
|
593
|
+
pip install gateforge-sdk
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
**`RuntimeError: Call gateforge.init() first`**
|
|
597
|
+
```python
|
|
598
|
+
gateforge.init(api_key="gf-live-...")
|
|
599
|
+
# Or use auto_init:
|
|
600
|
+
gateforge.auto_init()
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**PII not detected**
|
|
604
|
+
1. Check domain setting matches your data
|
|
605
|
+
2. Add custom patterns in dashboard
|
|
606
|
+
|
|
607
|
+
**Steps not appearing in trace**
|
|
608
|
+
1. Ensure `tracing_enabled=True`
|
|
609
|
+
2. Confirm `conversation_id` is active
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
## Links
|
|
614
|
+
|
|
615
|
+
- [Website](https://gateforge.dev)
|
|
616
|
+
- [Dashboard](https://app.gateforge.dev)
|
|
617
|
+
- [PyPI](https://pypi.org/project/gateforge-sdk/)
|
|
618
|
+
- [Issues](https://github.com/gateforge/gateforge-sdk/issues)
|
|
619
|
+
|
|
620
|
+
---
|
|
621
|
+
|
|
622
|
+
## License
|
|
623
|
+
|
|
624
|
+
MIT — see [LICENSE](LICENSE). The SDK is open source; the Gateforge service is commercial with a free tier (1,000 requests/month).
|