Skip to content

Commit bf76c9f

Browse files
adambaloghbalogh.adam@icloud.com
andauthored
LLM client code refactor (#178)
* llm refactor * refac * async client * format * format * simplify * llm test * format * tests * docs * rm exception * readmes * tool * fix ci test * rm overlapping test * cleanup * docs * c --------- Co-authored-by: balogh.adam@icloud.com <adambalogh@mac.mynetworksettings.com>
1 parent 646c38b commit bf76c9f

40 files changed

Lines changed: 1479 additions & 1126 deletions

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
run: |
2323
python -m pip install --upgrade pip
2424
pip install -e .
25-
pip install pytest
25+
pip install pytest pytest-asyncio
2626
2727
- name: Run tests
2828
run: make test

Makefile

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,8 @@ docs:
3131
# Testing
3232
# ============================================================================
3333

34-
test: utils_test client_test langchain_adapter_test opg_token_test tee_registry_test
35-
36-
utils_test:
37-
pytest tests/utils_test.py -v
38-
39-
client_test:
40-
pytest tests/client_test.py -v
41-
42-
langchain_adapter_test:
43-
pytest tests/langchain_adapter_test.py -v
44-
45-
opg_token_test:
46-
pytest tests/opg_token_test.py -v
47-
48-
tee_registry_test:
49-
pytest tests/tee_registry_test.py -v
34+
test:
35+
pytest tests/ -v
5036

5137
integrationtest:
5238
python integrationtest/agent/test_agent.py
@@ -102,5 +88,5 @@ chat-stream-tool:
10288
--max-tokens 200 \
10389
--stream
10490

105-
.PHONY: install build publish check docs test utils_test client_test langchain_adapter_test opg_token_test integrationtest examples \
91+
.PHONY: install build publish check docs test integrationtest examples \
10692
infer completion chat chat-stream chat-tool chat-stream-tool

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ See [Payment Settlement](#payment-settlement) for details on settlement modes.
9797

9898
### TEE-Secured LLM Chat
9999

100-
OpenGradient provides secure, verifiable inference through Trusted Execution Environments. All supported models include cryptographic attestation verified by the OpenGradient network:
100+
OpenGradient provides secure, verifiable inference through Trusted Execution Environments. All supported models include cryptographic attestation verified by the OpenGradient network. LLM methods are async:
101101
```python
102-
completion = client.llm.chat(
102+
completion = await client.llm.chat(
103103
model=og.TEE_LLM.GPT_5,
104104
messages=[{"role": "user", "content": "Hello!"}],
105105
)
@@ -111,14 +111,14 @@ print(f"Transaction hash: {completion.transaction_hash}")
111111

112112
For real-time generation, enable streaming:
113113
```python
114-
stream = client.llm.chat(
114+
stream = await client.llm.chat(
115115
model=og.TEE_LLM.CLAUDE_SONNET_4_6,
116116
messages=[{"role": "user", "content": "Explain quantum computing"}],
117117
max_tokens=500,
118118
stream=True,
119119
)
120120

121-
for chunk in stream:
121+
async for chunk in stream:
122122
if chunk.choices[0].delta.content:
123123
print(chunk.choices[0].delta.content, end="")
124124
```
@@ -299,7 +299,7 @@ OpenGradient supports multiple settlement modes through the x402 payment protoco
299299

300300
Specify settlement mode in your requests:
301301
```python
302-
result = client.llm.chat(
302+
result = await client.llm.chat(
303303
model=og.TEE_LLM.GPT_5,
304304
messages=[{"role": "user", "content": "Hello"}],
305305
x402_settlement_mode=og.x402SettlementMode.BATCH_HASHED,

dev-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ langgraph
22
pdoc3==0.10.0
33
mypy
44
types-protobuf
5+
pytest-asyncio

docs/CLAUDE_SDK_USERS.md

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ client = og.Client(
2323
private_key=os.environ["OG_PRIVATE_KEY"], # Required: Ethereum private key
2424
)
2525

26-
# LLM Chat (TEE-verified with x402 payments)
27-
result = client.llm.chat(
26+
# LLM Chat (TEE-verified with x402 payments, async)
27+
result = await client.llm.chat(
2828
model=og.TEE_LLM.CLAUDE_HAIKU_4_5,
2929
messages=[{"role": "user", "content": "Hello!"}],
3030
max_tokens=100,
@@ -51,7 +51,7 @@ og.init(private_key="0x...", email="...", password="...")
5151
### LLM Chat
5252

5353
```python
54-
result = client.llm.chat(
54+
result = await client.llm.chat(
5555
model: TEE_LLM, # og.TEE_LLM enum value
5656
messages: List[Dict], # [{"role": "user", "content": "..."}]
5757
max_tokens: int = 100,
@@ -62,7 +62,7 @@ result = client.llm.chat(
6262
x402_settlement_mode: x402SettlementMode = x402SettlementMode.BATCH_HASHED,
6363
stream: bool = False, # Enable streaming responses
6464
)
65-
# Returns: TextGenerationOutput (or TextGenerationStream if stream=True)
65+
# Returns: TextGenerationOutput (or AsyncGenerator[StreamChunk] if stream=True)
6666
# - chat_output: Dict with role, content, tool_calls
6767
# - transaction_hash: str
6868
# - finish_reason: str ("stop", "tool_call")
@@ -72,7 +72,7 @@ result = client.llm.chat(
7272
### LLM Completion
7373

7474
```python
75-
result = client.llm.completion(
75+
result = await client.llm.completion(
7676
model: TEE_LLM,
7777
prompt: str,
7878
max_tokens: int = 100,
@@ -139,7 +139,7 @@ og.TEE_LLM.GROK_4_1_FAST_NON_REASONING
139139
All models are accessed through the OpenGradient TEE infrastructure with x402 payments:
140140

141141
```python
142-
result = client.llm.chat(
142+
result = await client.llm.chat(
143143
model=og.TEE_LLM.GPT_5,
144144
messages=[{"role": "user", "content": "Hello"}],
145145
)
@@ -165,7 +165,7 @@ tools = [{
165165
}
166166
}]
167167

168-
result = client.llm.chat(
168+
result = await client.llm.chat(
169169
model=og.TEE_LLM.CLAUDE_SONNET_4_6,
170170
messages=[{"role": "user", "content": "What's the weather in NYC?"}],
171171
tools=tools,
@@ -180,13 +180,13 @@ if result.chat_output.get("tool_calls"):
180180
### Streaming
181181

182182
```python
183-
stream = client.llm.chat(
183+
stream = await client.llm.chat(
184184
model=og.TEE_LLM.CLAUDE_SONNET_4_6,
185185
messages=[{"role": "user", "content": "Tell me a story"}],
186186
stream=True,
187187
)
188188

189-
for chunk in stream:
189+
async for chunk in stream:
190190
for choice in chunk.choices:
191191
if choice.delta.content:
192192
print(choice.delta.content, end="")
@@ -283,28 +283,15 @@ og.CandleOrder.ASCENDING, .DESCENDING
283283

284284
## Error Handling
285285

286-
```python
287-
from opengradient.client.exceptions import (
288-
OpenGradientError, # Base exception
289-
AuthenticationError,
290-
InferenceError,
291-
InvalidInputError,
292-
NetworkError,
293-
RateLimitError,
294-
TimeoutError,
295-
ServerError,
296-
UnsupportedModelError,
297-
InsufficientCreditsError,
298-
)
286+
LLM methods raise `RuntimeError` on failure and `ValueError` for invalid arguments:
299287

288+
```python
300289
try:
301-
result = client.llm.chat(...)
302-
except RateLimitError:
303-
# Retry with backoff
304-
except InferenceError as e:
305-
print(f"Inference failed: {e.message}")
306-
except OpenGradientError as e:
307-
print(f"Error {e.status_code}: {e.message}")
290+
result = await client.llm.chat(...)
291+
except RuntimeError as e:
292+
print(f"Inference failed: {e}")
293+
except ValueError as e:
294+
print(f"Invalid input: {e}")
308295
```
309296

310297
## Environment Variables

docs/opengradient/client/alpha.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ InferenceResult (InferenceResult): A dataclass object containing the transaction
6363

6464
**Raises**
6565

66-
* **`OpenGradientError`**: If the inference fails.
66+
* **`RuntimeError`**: If the inference fails.
6767

6868
---
6969

docs/opengradient/client/client.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ def __init__(
3636
twins_api_key: Optional[str= None,
3737
rpc_urlstr = 'https://ogevmdevnet.opengradient.ai',
3838
api_urlstr = 'https://sdk-devnet.opengradient.ai',
39-
contract_addressstr = '0x8383C9bD7462F12Eb996DD02F78234C0421A6FaE',
40-
og_llm_server_url: Optional[str= 'https://3.15.214.21:443',
41-
og_llm_streaming_server_url: Optional[str] = 'https://3.15.214.21:443'
39+
inference_contract_addressstr = '0x8383C9bD7462F12Eb996DD02F78234C0421A6FaE',
40+
llm_server_url: Optional[str= None,
41+
tee_registry_addressstr = '0x4e72238852f3c918f4E4e57AeC9280dDB0c80248'
4242
)
4343
```
4444

@@ -49,14 +49,20 @@ def __init__(
4949
* **`alpha_private_key`**: Private key whose wallet holds **OpenGradient testnet
5050
gas tokens** for on-chain inference. Optional -- falls back to
5151
``private_key`` for backward compatibility.
52-
* **`email`**: Email for Model Hub authentication. Optional.
53-
* **`password`**: Password for Model Hub authentication. Optional.
52+
* **`email`**: Email for Model Hub authentication. Must be provided together
53+
with ``password``.
54+
* **`password`**: Password for Model Hub authentication. Must be provided
55+
together with ``email``.
5456
* **`twins_api_key`**: API key for digital twins chat (twin.fun). Optional.
5557
* **`rpc_url`**: RPC URL for the OpenGradient Alpha Testnet.
5658
* **`api_url`**: API URL for the OpenGradient API.
57-
* **`contract_address`**: Inference contract address.
58-
* **`og_llm_server_url`**: OpenGradient LLM server URL.
59-
* **`og_llm_streaming_server_url`**: OpenGradient LLM streaming server URL.
59+
* **`inference_contract_address`**: Inference contract address on the
60+
OpenGradient Alpha Testnet.
61+
* **`llm_server_url`**: Override the LLM server URL instead of using the
62+
registry-discovered endpoint. When set, the TLS certificate is
63+
validated against the system CA bundle rather than the registry.
64+
* **`tee_registry_address`**: Address of the TEERegistry contract used to
65+
discover active LLM proxy endpoints and their verified TLS certs.
6066

6167
#### Methods
6268

@@ -65,7 +71,7 @@ def __init__(
6571
#### `close()`
6672

6773
```python
68-
def close(self) ‑> None
74+
async def close(self) ‑> None
6975
```
7076
Close underlying SDK resources.
7177

docs/opengradient/client/index.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,13 @@ client = og.init(private_key="0xLLM_KEY...", alpha_private_key="0xALPHA_KEY...")
3939
client.llm.ensure_opg_approval(opg_amount=5)
4040

4141
# LLM chat (TEE-verified, streamed)
42-
for chunk in client.llm.chat(
42+
stream = await client.llm.chat(
4343
model=og.TEE_LLM.CLAUDE_HAIKU_4_5,
4444
messages=[{"role": "user", "content": "Hello!"}],
4545
max_tokens=200,
4646
stream=True,
47-
):
47+
)
48+
async for chunk in stream:
4849
if chunk.choices[0].delta.content:
4950
print(chunk.choices[0].delta.content, end="")
5051

@@ -64,10 +65,10 @@ repo = client.model_hub.create_model("my-model", "A price prediction model")
6465

6566
* [alpha](./alpha): Alpha Testnet features for OpenGradient SDK.
6667
* [client](./client): Main Client class that unifies all OpenGradient service namespaces.
67-
* [exceptions](./exceptions): Exception types for OpenGradient SDK errors.
6868
* [llm](./llm): LLM chat and completion via TEE-verified execution with x402 payments.
6969
* [model_hub](./model_hub): Model Hub for creating, versioning, and uploading ML models.
7070
* [opg_token](./opg_token): OPG token Permit2 approval utilities for x402 payments.
71+
* [tee_registry](./tee_registry): TEE Registry client for fetching verified TEE endpoints and TLS certificates.
7172
* [twins](./twins): Digital twins chat via OpenGradient verifiable inference.
7273

7374
## Classes
@@ -98,9 +99,9 @@ def __init__(
9899
twins_api_key: Optional[str= None,
99100
rpc_urlstr = 'https://ogevmdevnet.opengradient.ai',
100101
api_urlstr = 'https://sdk-devnet.opengradient.ai',
101-
contract_addressstr = '0x8383C9bD7462F12Eb996DD02F78234C0421A6FaE',
102-
og_llm_server_url: Optional[str= 'https://3.15.214.21:443',
103-
og_llm_streaming_server_url: Optional[str] = 'https://3.15.214.21:443'
102+
inference_contract_addressstr = '0x8383C9bD7462F12Eb996DD02F78234C0421A6FaE',
103+
llm_server_url: Optional[str= None,
104+
tee_registry_addressstr = '0x4e72238852f3c918f4E4e57AeC9280dDB0c80248'
104105
)
105106
```
106107

@@ -111,14 +112,20 @@ def __init__(
111112
* **`alpha_private_key`**: Private key whose wallet holds **OpenGradient testnet
112113
gas tokens** for on-chain inference. Optional -- falls back to
113114
``private_key`` for backward compatibility.
114-
* **`email`**: Email for Model Hub authentication. Optional.
115-
* **`password`**: Password for Model Hub authentication. Optional.
115+
* **`email`**: Email for Model Hub authentication. Must be provided together
116+
with ``password``.
117+
* **`password`**: Password for Model Hub authentication. Must be provided
118+
together with ``email``.
116119
* **`twins_api_key`**: API key for digital twins chat (twin.fun). Optional.
117120
* **`rpc_url`**: RPC URL for the OpenGradient Alpha Testnet.
118121
* **`api_url`**: API URL for the OpenGradient API.
119-
* **`contract_address`**: Inference contract address.
120-
* **`og_llm_server_url`**: OpenGradient LLM server URL.
121-
* **`og_llm_streaming_server_url`**: OpenGradient LLM streaming server URL.
122+
* **`inference_contract_address`**: Inference contract address on the
123+
OpenGradient Alpha Testnet.
124+
* **`llm_server_url`**: Override the LLM server URL instead of using the
125+
registry-discovered endpoint. When set, the TLS certificate is
126+
validated against the system CA bundle rather than the registry.
127+
* **`tee_registry_address`**: Address of the TEERegistry contract used to
128+
discover active LLM proxy endpoints and their verified TLS certs.
122129

123130
#### Methods
124131

@@ -127,7 +134,7 @@ def __init__(
127134
#### `close()`
128135

129136
```python
130-
def close(self) ‑> None
137+
async def close(self) ‑> None
131138
```
132139
Close underlying SDK resources.
133140

0 commit comments

Comments
 (0)