Skip to content

Commit 309d856

Browse files
authored
Merge branch 'main' into kyle/structured-output
Signed-off-by: Kyle Qian <kylexqian@gmail.com>
2 parents a9d16bc + 940432c commit 309d856

11 files changed

Lines changed: 576 additions & 123 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ OpenGradient enables developers to build AI applications with verifiable executi
2424
pip install opengradient
2525
```
2626

27-
**Note**: > **Windows users:** See the [Windows Installation Guide](./WINDOWS_INSTALL.md) for step-by-step setup instructions.
27+
> **Note for Windows users:** See the [Windows Installation Guide](./WINDOWS_INSTALL.md) for step-by-step setup instructions.
2828
2929
### Claude Code Integration
3030

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
"""
2+
Multi-turn conversation example with OpenGradient TEE-verified LLM.
3+
4+
Demonstrates how to maintain conversation history across multiple turns,
5+
enabling context-aware responses with full cryptographic verification
6+
of every inference step.
7+
8+
Usage:
9+
export OG_PRIVATE_KEY="your_private_key"
10+
python examples/llm_multi_turn_conversation.py
11+
"""
12+
13+
import asyncio
14+
import os
15+
16+
import opengradient as og
17+
18+
19+
def add_user_message(history: list, content: str) -> list:
20+
"""Append a user message to the conversation history."""
21+
return history + [{"role": "user", "content": content}]
22+
23+
24+
def add_assistant_message(history: list, content: str) -> list:
25+
"""Append an assistant message to the conversation history."""
26+
return history + [{"role": "assistant", "content": content}]
27+
28+
29+
async def chat_turn(
30+
llm: og.LLM,
31+
history: list,
32+
user_input: str,
33+
model: og.TEE_LLM = og.TEE_LLM.GEMINI_2_5_FLASH,
34+
) -> tuple[str, list, str]:
35+
"""
36+
Execute a single conversation turn.
37+
38+
Args:
39+
llm: Initialized LLM client.
40+
history: Current conversation history.
41+
user_input: The user's message for this turn.
42+
model: TEE_LLM model to use.
43+
44+
Returns:
45+
Tuple of (assistant_reply, updated_history, transaction_hash).
46+
"""
47+
history = add_user_message(history, user_input)
48+
49+
result = await llm.chat(
50+
model=model,
51+
messages=history,
52+
max_tokens=500,
53+
temperature=0.7,
54+
)
55+
assert isinstance(result, og.TextGenerationOutput)
56+
57+
assert result.chat_output is not None
58+
reply = str(result.chat_output["content"])
59+
history = add_assistant_message(history, reply)
60+
61+
return reply, history, result.transaction_hash
62+
63+
64+
async def main():
65+
private_key = os.environ.get("OG_PRIVATE_KEY")
66+
if not private_key:
67+
raise ValueError("OG_PRIVATE_KEY environment variable is not set.")
68+
69+
llm = og.LLM(private_key=private_key)
70+
llm.ensure_opg_approval(min_allowance=0.5)
71+
72+
model = og.TEE_LLM.GEMINI_2_5_FLASH
73+
print(f"Model : {model.value}")
74+
print(f"Mode : Multi-turn conversation with TEE verification")
75+
print("=" * 60)
76+
77+
# System prompt sets the assistant persona for the whole conversation
78+
history = [
79+
{
80+
"role": "system",
81+
"content": ("You are a concise Python tutor. Give short, clear answers with code examples when helpful."),
82+
}
83+
]
84+
85+
# --- Turn 1 ---
86+
question_1 = "What is a Python decorator?"
87+
print(f"\nUser : {question_1}")
88+
89+
reply_1, history, tx_1 = await chat_turn(llm, history, question_1, model)
90+
print(f"Assistant : {reply_1}")
91+
print(f"[tx: {tx_1}]")
92+
93+
# --- Turn 2 — follow-up referencing Turn 1 ---
94+
question_2 = "Can you show me a real-world example of one?"
95+
print(f"\nUser : {question_2}")
96+
97+
reply_2, history, tx_2 = await chat_turn(llm, history, question_2, model)
98+
print(f"Assistant : {reply_2}")
99+
print(f"[tx: {tx_2}]")
100+
101+
# --- Turn 3 — deeper follow-up ---
102+
question_3 = "How would I stack two decorators on the same function?"
103+
print(f"\nUser : {question_3}")
104+
105+
reply_3, history, tx_3 = await chat_turn(llm, history, question_3, model)
106+
print(f"Assistant : {reply_3}")
107+
print(f"[tx: {tx_3}]")
108+
109+
# Summary
110+
print("\n" + "=" * 60)
111+
print(f"Total turns : {len([m for m in history if m['role'] == 'user'])}")
112+
print(f"Total messages : {len(history)}")
113+
print("Transaction hashes (verifiable on-chain):")
114+
for i, tx in enumerate([tx_1, tx_2, tx_3], 1):
115+
print(f" Turn {i}: {tx}")
116+
117+
118+
if __name__ == "__main__":
119+
asyncio.run(main())

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "opengradient"
7-
version = "0.9.5"
7+
version = "0.9.6"
88
description = "Python SDK for OpenGradient decentralized model management & inference services"
99
authors = [{name = "OpenGradient", email = "adam@vannalabs.ai"}]
1010
readme = "README.md"
@@ -76,6 +76,9 @@ target-version = "py310"
7676
select = ["E", "F", "I", "N"]
7777
ignore = []
7878

79+
[tool.uv]
80+
exclude-newer = "7d"
81+
7982
[tool.ruff.mccabe]
8083
max-complexity = 10
8184

src/opengradient/agents/__init__.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,24 @@
66
into existing applications and agent frameworks.
77
"""
88

9+
from typing import Optional, Union
10+
11+
from ..client.llm import LLM
912
from ..types import TEE_LLM, x402SettlementMode
1013
from .og_langchain import *
1114

1215

1316
def langchain_adapter(
14-
private_key: str,
15-
model_cid: TEE_LLM,
17+
private_key: Optional[str] = None,
18+
model_cid: Optional[Union[TEE_LLM, str]] = None,
19+
model: Optional[Union[TEE_LLM, str]] = None,
1620
max_tokens: int = 300,
21+
temperature: float = 0.0,
1722
x402_settlement_mode: x402SettlementMode = x402SettlementMode.BATCH_HASHED,
23+
client: Optional[LLM] = None,
24+
rpc_url: Optional[str] = None,
25+
tee_registry_address: Optional[str] = None,
26+
llm_server_url: Optional[str] = None,
1827
) -> OpenGradientChatModel:
1928
"""
2029
Returns an OpenGradient LLM that implements LangChain's LLM interface
@@ -23,8 +32,14 @@ def langchain_adapter(
2332
return OpenGradientChatModel(
2433
private_key=private_key,
2534
model_cid=model_cid,
35+
model=model,
2636
max_tokens=max_tokens,
37+
temperature=temperature,
2738
x402_settlement_mode=x402_settlement_mode,
39+
client=client,
40+
rpc_url=rpc_url,
41+
tee_registry_address=tee_registry_address,
42+
llm_server_url=llm_server_url,
2843
)
2944

3045

0 commit comments

Comments
 (0)