hypnex-openai 0.1.0__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.
- hypnex_openai-0.1.0/.gitignore +66 -0
- hypnex_openai-0.1.0/PKG-INFO +150 -0
- hypnex_openai-0.1.0/README.md +121 -0
- hypnex_openai-0.1.0/examples/01_basic_chat.py +21 -0
- hypnex_openai-0.1.0/examples/02_streaming.py +22 -0
- hypnex_openai-0.1.0/examples/03_langchain.py +28 -0
- hypnex_openai-0.1.0/examples/04_crewai.py +35 -0
- hypnex_openai-0.1.0/examples/05_morpheus_extras.py +45 -0
- hypnex_openai-0.1.0/examples/06_async.py +34 -0
- hypnex_openai-0.1.0/examples/07_tools.py +70 -0
- hypnex_openai-0.1.0/examples/08_embeddings.py +22 -0
- hypnex_openai-0.1.0/pyproject.toml +55 -0
- hypnex_openai-0.1.0/src/hypnex_openai/__init__.py +50 -0
- hypnex_openai-0.1.0/src/hypnex_openai/__main__.py +90 -0
- hypnex_openai-0.1.0/src/hypnex_openai/_constants.py +24 -0
- hypnex_openai-0.1.0/src/hypnex_openai/_morpheus.py +263 -0
- hypnex_openai-0.1.0/src/hypnex_openai/client.py +93 -0
- hypnex_openai-0.1.0/tests/test_client.py +103 -0
- hypnex_openai-0.1.0/uv.lock +702 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# --- Python ---
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.eggs/
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
.ruff_cache/
|
|
11
|
+
.tox/
|
|
12
|
+
.coverage
|
|
13
|
+
.coverage.*
|
|
14
|
+
htmlcov/
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
env/
|
|
18
|
+
|
|
19
|
+
# --- Node / TypeScript ---
|
|
20
|
+
node_modules/
|
|
21
|
+
*.tsbuildinfo
|
|
22
|
+
.npm/
|
|
23
|
+
.yarn/
|
|
24
|
+
.pnpm-store/
|
|
25
|
+
.parcel-cache/
|
|
26
|
+
|
|
27
|
+
# --- Next.js (apps/stake) ---
|
|
28
|
+
.next/
|
|
29
|
+
out/
|
|
30
|
+
.vercel/
|
|
31
|
+
|
|
32
|
+
# --- Wrangler / Cloudflare ---
|
|
33
|
+
.wrangler/
|
|
34
|
+
|
|
35
|
+
# --- Foundry (registry-contracts) ---
|
|
36
|
+
forge-cache/
|
|
37
|
+
broadcast/
|
|
38
|
+
|
|
39
|
+
# --- Editor / OS ---
|
|
40
|
+
.idea/
|
|
41
|
+
.vscode/
|
|
42
|
+
.DS_Store
|
|
43
|
+
*.swp
|
|
44
|
+
*.swo
|
|
45
|
+
*~
|
|
46
|
+
|
|
47
|
+
# --- Local secrets — never commit ---
|
|
48
|
+
.env
|
|
49
|
+
.env.*
|
|
50
|
+
!.env.example
|
|
51
|
+
.env.local
|
|
52
|
+
.env.production
|
|
53
|
+
|
|
54
|
+
# --- Log + tmp ---
|
|
55
|
+
*.log
|
|
56
|
+
logs/
|
|
57
|
+
tmp/
|
|
58
|
+
|
|
59
|
+
# --- Build outputs in apps/bench ---
|
|
60
|
+
apps/bench/out/
|
|
61
|
+
|
|
62
|
+
# --- Generated bench data is committed (audit trail) but local runs aren't ---
|
|
63
|
+
python-bench/data/*.jsonl
|
|
64
|
+
|
|
65
|
+
# Claude Code session artifacts — never commit
|
|
66
|
+
.claude/
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hypnex-openai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Drop-in OpenAI client for the Morpheus decentralized inference network (mor.org)
|
|
5
|
+
Project-URL: Homepage, https://hypnex.xyz
|
|
6
|
+
Project-URL: Documentation, https://docs.hypnex.xyz
|
|
7
|
+
Project-URL: Repository, https://github.com/hypnex-labs/hypnex
|
|
8
|
+
Project-URL: Issues, https://github.com/hypnex-labs/hypnex/issues
|
|
9
|
+
Author: Hypnex Labs
|
|
10
|
+
License: MIT
|
|
11
|
+
Keywords: agents,ai,crypto,decentralized,llm,morpheus,openai
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Requires-Dist: httpx>=0.27.0
|
|
23
|
+
Requires-Dist: openai<2.0.0,>=1.50.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# hypnex-openai (Python)
|
|
31
|
+
|
|
32
|
+
Drop-in OpenAI client for the Morpheus decentralized inference network ([mor.org](https://mor.org)).
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install hypnex-openai
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from hypnex_openai import HypnexOpenAI
|
|
40
|
+
|
|
41
|
+
client = HypnexOpenAI(api_key="mor_...") # get one at https://app.mor.org
|
|
42
|
+
|
|
43
|
+
response = client.chat.completions.create(
|
|
44
|
+
model="mistral-31-24b",
|
|
45
|
+
messages=[{"role": "user", "content": "Hello"}],
|
|
46
|
+
)
|
|
47
|
+
print(response.choices[0].message.content)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`HypnexOpenAI` subclasses `openai.OpenAI` and points it at `https://api.mor.org/api/v1`. Streaming, tools, async, structured output — all work unchanged.
|
|
51
|
+
|
|
52
|
+
## Models on the Morpheus network
|
|
53
|
+
|
|
54
|
+
The network exposes 60+ models via OpenAI-compatible endpoints. List them:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
hypnex models
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Or programmatically:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
client.morpheus.active_models() # full registry
|
|
64
|
+
client.morpheus.models_by_type("LLM") # filter
|
|
65
|
+
client.morpheus.find_model("glm-5") # lookup
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Featured LLMs: `mistral-31-24b`, `glm-5`, `qwen3-235b`, `qwen3-coder-480b-a35b-instruct`, `deepseek-r1:70b`, `minimax-m25`. Embeddings: `text-embedding-bge-m3`. TTS: `tts-kokoro`. STT: `whisper-1`.
|
|
69
|
+
|
|
70
|
+
## Drop-in for popular frameworks
|
|
71
|
+
|
|
72
|
+
Any framework that accepts a `base_url` accepts Morpheus:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
# LangChain
|
|
76
|
+
from langchain_openai import ChatOpenAI
|
|
77
|
+
llm = ChatOpenAI(
|
|
78
|
+
model="qwen3-235b",
|
|
79
|
+
api_key=os.environ["HYPNEX_API_KEY"],
|
|
80
|
+
base_url="https://api.mor.org/api/v1",
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# CrewAI
|
|
84
|
+
from crewai import LLM
|
|
85
|
+
llm = LLM(
|
|
86
|
+
model="openai/qwen3-235b",
|
|
87
|
+
api_key=os.environ["HYPNEX_API_KEY"],
|
|
88
|
+
base_url="https://api.mor.org/api/v1",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# llama-index
|
|
92
|
+
from llama_index.llms.openai_like import OpenAILike
|
|
93
|
+
llm = OpenAILike(
|
|
94
|
+
model="qwen3-235b",
|
|
95
|
+
api_base="https://api.mor.org/api/v1",
|
|
96
|
+
api_key=os.environ["HYPNEX_API_KEY"],
|
|
97
|
+
is_chat_model=True,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# instructor
|
|
101
|
+
import instructor
|
|
102
|
+
client = instructor.from_openai(HypnexOpenAI())
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Morpheus-specific endpoints
|
|
106
|
+
|
|
107
|
+
`client.morpheus.*` exposes endpoints that have no OpenAI equivalent:
|
|
108
|
+
|
|
109
|
+
| Method | What it does |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `balance()` | Current MOR balance |
|
|
112
|
+
| `transactions(limit=50)` | Billing history |
|
|
113
|
+
| `spending()` | Cumulative usage |
|
|
114
|
+
| `me()` | User profile |
|
|
115
|
+
| `list_keys()` / `create_key(name)` / `delete_key(id)` / `set_default_key(id)` | API keys |
|
|
116
|
+
| `link_wallet(addr, sig, msg)` / `get_wallet()` / `unlink_wallet()` | Wallet binding |
|
|
117
|
+
| `active_models()` / `find_model(name)` / `models_by_type(type)` | Public registry |
|
|
118
|
+
|
|
119
|
+
## CLI
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
hypnex models # list
|
|
123
|
+
hypnex health # show api.mor.org health
|
|
124
|
+
hypnex chat "Hello" --model glm-5 # one-shot
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Async
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from hypnex_openai import AsyncHypnexOpenAI
|
|
131
|
+
client = AsyncHypnexOpenAI(api_key="mor_...")
|
|
132
|
+
r = await client.chat.completions.create(...)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Environment
|
|
136
|
+
|
|
137
|
+
- `HYPNEX_API_KEY` — your API key (required)
|
|
138
|
+
- `HYPNEX_BASE_URL` — override base URL (default `https://api.mor.org/api/v1`)
|
|
139
|
+
|
|
140
|
+
## Tests
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
pip install -e ".[dev]"
|
|
144
|
+
pytest # public smoke tests
|
|
145
|
+
HYPNEX_API_KEY=mor_... pytest # also run authenticated tests
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# hypnex-openai (Python)
|
|
2
|
+
|
|
3
|
+
Drop-in OpenAI client for the Morpheus decentralized inference network ([mor.org](https://mor.org)).
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install hypnex-openai
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
from hypnex_openai import HypnexOpenAI
|
|
11
|
+
|
|
12
|
+
client = HypnexOpenAI(api_key="mor_...") # get one at https://app.mor.org
|
|
13
|
+
|
|
14
|
+
response = client.chat.completions.create(
|
|
15
|
+
model="mistral-31-24b",
|
|
16
|
+
messages=[{"role": "user", "content": "Hello"}],
|
|
17
|
+
)
|
|
18
|
+
print(response.choices[0].message.content)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`HypnexOpenAI` subclasses `openai.OpenAI` and points it at `https://api.mor.org/api/v1`. Streaming, tools, async, structured output — all work unchanged.
|
|
22
|
+
|
|
23
|
+
## Models on the Morpheus network
|
|
24
|
+
|
|
25
|
+
The network exposes 60+ models via OpenAI-compatible endpoints. List them:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
hypnex models
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or programmatically:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
client.morpheus.active_models() # full registry
|
|
35
|
+
client.morpheus.models_by_type("LLM") # filter
|
|
36
|
+
client.morpheus.find_model("glm-5") # lookup
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Featured LLMs: `mistral-31-24b`, `glm-5`, `qwen3-235b`, `qwen3-coder-480b-a35b-instruct`, `deepseek-r1:70b`, `minimax-m25`. Embeddings: `text-embedding-bge-m3`. TTS: `tts-kokoro`. STT: `whisper-1`.
|
|
40
|
+
|
|
41
|
+
## Drop-in for popular frameworks
|
|
42
|
+
|
|
43
|
+
Any framework that accepts a `base_url` accepts Morpheus:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
# LangChain
|
|
47
|
+
from langchain_openai import ChatOpenAI
|
|
48
|
+
llm = ChatOpenAI(
|
|
49
|
+
model="qwen3-235b",
|
|
50
|
+
api_key=os.environ["HYPNEX_API_KEY"],
|
|
51
|
+
base_url="https://api.mor.org/api/v1",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# CrewAI
|
|
55
|
+
from crewai import LLM
|
|
56
|
+
llm = LLM(
|
|
57
|
+
model="openai/qwen3-235b",
|
|
58
|
+
api_key=os.environ["HYPNEX_API_KEY"],
|
|
59
|
+
base_url="https://api.mor.org/api/v1",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# llama-index
|
|
63
|
+
from llama_index.llms.openai_like import OpenAILike
|
|
64
|
+
llm = OpenAILike(
|
|
65
|
+
model="qwen3-235b",
|
|
66
|
+
api_base="https://api.mor.org/api/v1",
|
|
67
|
+
api_key=os.environ["HYPNEX_API_KEY"],
|
|
68
|
+
is_chat_model=True,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# instructor
|
|
72
|
+
import instructor
|
|
73
|
+
client = instructor.from_openai(HypnexOpenAI())
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Morpheus-specific endpoints
|
|
77
|
+
|
|
78
|
+
`client.morpheus.*` exposes endpoints that have no OpenAI equivalent:
|
|
79
|
+
|
|
80
|
+
| Method | What it does |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `balance()` | Current MOR balance |
|
|
83
|
+
| `transactions(limit=50)` | Billing history |
|
|
84
|
+
| `spending()` | Cumulative usage |
|
|
85
|
+
| `me()` | User profile |
|
|
86
|
+
| `list_keys()` / `create_key(name)` / `delete_key(id)` / `set_default_key(id)` | API keys |
|
|
87
|
+
| `link_wallet(addr, sig, msg)` / `get_wallet()` / `unlink_wallet()` | Wallet binding |
|
|
88
|
+
| `active_models()` / `find_model(name)` / `models_by_type(type)` | Public registry |
|
|
89
|
+
|
|
90
|
+
## CLI
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
hypnex models # list
|
|
94
|
+
hypnex health # show api.mor.org health
|
|
95
|
+
hypnex chat "Hello" --model glm-5 # one-shot
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Async
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from hypnex_openai import AsyncHypnexOpenAI
|
|
102
|
+
client = AsyncHypnexOpenAI(api_key="mor_...")
|
|
103
|
+
r = await client.chat.completions.create(...)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Environment
|
|
107
|
+
|
|
108
|
+
- `HYPNEX_API_KEY` — your API key (required)
|
|
109
|
+
- `HYPNEX_BASE_URL` — override base URL (default `https://api.mor.org/api/v1`)
|
|
110
|
+
|
|
111
|
+
## Tests
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install -e ".[dev]"
|
|
115
|
+
pytest # public smoke tests
|
|
116
|
+
HYPNEX_API_KEY=mor_... pytest # also run authenticated tests
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Basic chat completion against the Morpheus inference network.
|
|
2
|
+
|
|
3
|
+
Run: HYPNEX_API_KEY=mor_... python examples/01_basic_chat.py
|
|
4
|
+
Get a key at https://app.mor.org.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
from hypnex_openai import HypnexOpenAI
|
|
10
|
+
|
|
11
|
+
client = HypnexOpenAI(api_key=os.environ["HYPNEX_API_KEY"])
|
|
12
|
+
|
|
13
|
+
response = client.chat.completions.create(
|
|
14
|
+
model="mistral-31-24b",
|
|
15
|
+
messages=[
|
|
16
|
+
{"role": "system", "content": "You are a concise assistant."},
|
|
17
|
+
{"role": "user", "content": "Explain Morpheus AI in one sentence."},
|
|
18
|
+
],
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
print(response.choices[0].message.content)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Streaming chat completion (SSE).
|
|
2
|
+
|
|
3
|
+
Run: HYPNEX_API_KEY=mor_... python examples/02_streaming.py
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
|
|
8
|
+
from hypnex_openai import HypnexOpenAI
|
|
9
|
+
|
|
10
|
+
client = HypnexOpenAI(api_key=os.environ["HYPNEX_API_KEY"])
|
|
11
|
+
|
|
12
|
+
stream = client.chat.completions.create(
|
|
13
|
+
model="qwen3-235b",
|
|
14
|
+
messages=[{"role": "user", "content": "Count from 1 to 10, one per line."}],
|
|
15
|
+
stream=True,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
for chunk in stream:
|
|
19
|
+
delta = chunk.choices[0].delta
|
|
20
|
+
if delta and delta.content:
|
|
21
|
+
print(delta.content, end="", flush=True)
|
|
22
|
+
print()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""LangChain integration — point ChatOpenAI at Morpheus.
|
|
2
|
+
|
|
3
|
+
ChatOpenAI accepts a base_url and api_key, so swapping providers is a
|
|
4
|
+
2-line change. Use any Morpheus model in the `model=` field.
|
|
5
|
+
|
|
6
|
+
Install: pip install langchain langchain-openai
|
|
7
|
+
Run: HYPNEX_API_KEY=mor_... python examples/03_langchain.py
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
from langchain_core.messages import HumanMessage, SystemMessage
|
|
13
|
+
from langchain_openai import ChatOpenAI
|
|
14
|
+
|
|
15
|
+
llm = ChatOpenAI(
|
|
16
|
+
model="qwen3-235b",
|
|
17
|
+
api_key=os.environ["HYPNEX_API_KEY"],
|
|
18
|
+
base_url="https://api.mor.org/api/v1",
|
|
19
|
+
temperature=0.7,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
response = llm.invoke(
|
|
23
|
+
[
|
|
24
|
+
SystemMessage(content="You are concise."),
|
|
25
|
+
HumanMessage(content="Why is decentralized inference important?"),
|
|
26
|
+
]
|
|
27
|
+
)
|
|
28
|
+
print(response.content)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""CrewAI integration — replace OpenAI LLM with Morpheus.
|
|
2
|
+
|
|
3
|
+
CrewAI uses a "provider/model" naming convention; "openai/<morpheus-model>"
|
|
4
|
+
routes through the OpenAI-compatible client at the supplied base_url.
|
|
5
|
+
|
|
6
|
+
Install: pip install crewai
|
|
7
|
+
Run: HYPNEX_API_KEY=mor_... python examples/04_crewai.py
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
from crewai import LLM, Agent, Crew, Task
|
|
13
|
+
|
|
14
|
+
morpheus_llm = LLM(
|
|
15
|
+
model="openai/qwen3-coder-480b-a35b-instruct",
|
|
16
|
+
api_key=os.environ["HYPNEX_API_KEY"],
|
|
17
|
+
base_url="https://api.mor.org/api/v1",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
researcher = Agent(
|
|
21
|
+
role="Researcher",
|
|
22
|
+
goal="Produce concise, accurate summaries.",
|
|
23
|
+
backstory="A meticulous researcher who values brevity.",
|
|
24
|
+
llm=morpheus_llm,
|
|
25
|
+
allow_delegation=False,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
task = Task(
|
|
29
|
+
description="Summarize the four pools of the Morpheus protocol.",
|
|
30
|
+
expected_output="A 3-sentence summary covering Capital, Code, Compute, Community.",
|
|
31
|
+
agent=researcher,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
crew = Crew(agents=[researcher], tasks=[task], verbose=False)
|
|
35
|
+
print(crew.kickoff())
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Demonstrate Morpheus-specific endpoints (no OpenAI equivalent).
|
|
2
|
+
|
|
3
|
+
Most of these require a valid HYPNEX_API_KEY:
|
|
4
|
+
- balance() / transactions() / spending()
|
|
5
|
+
- me() / list_keys() / create_key() / delete_key()
|
|
6
|
+
- link_wallet() / get_wallet() / unlink_wallet()
|
|
7
|
+
|
|
8
|
+
These do NOT require auth (they hit the public registry):
|
|
9
|
+
- active_models() / find_model() / models_by_type()
|
|
10
|
+
|
|
11
|
+
Run: python examples/05_morpheus_extras.py
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
|
|
16
|
+
from hypnex_openai import HypnexOpenAI
|
|
17
|
+
|
|
18
|
+
# A dummy key works for the public registry calls. Use a real key for
|
|
19
|
+
# authenticated endpoints.
|
|
20
|
+
client = HypnexOpenAI(
|
|
21
|
+
api_key=os.environ.get("HYPNEX_API_KEY", "dummy-for-public-calls")
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
print("First 10 active models:\n")
|
|
25
|
+
for m in client.morpheus.active_models()[:10]:
|
|
26
|
+
fee_mor = (m.get("fee") or 0) / 1e18
|
|
27
|
+
print(f" {m['name']:<42} type={m['type']:<10} fee={fee_mor:.4f} MOR")
|
|
28
|
+
|
|
29
|
+
print("\nLLMs only:")
|
|
30
|
+
for m in client.morpheus.models_by_type("LLM"):
|
|
31
|
+
print(f" {m['name']}")
|
|
32
|
+
|
|
33
|
+
print("\nLook up a specific model:")
|
|
34
|
+
mistral = client.morpheus.find_model("mistral-31-24b")
|
|
35
|
+
print(f" mistral-31-24b → owner {mistral['owner']}" if mistral else " not found")
|
|
36
|
+
|
|
37
|
+
if os.environ.get("HYPNEX_API_KEY"):
|
|
38
|
+
print("\nAuthenticated calls:")
|
|
39
|
+
try:
|
|
40
|
+
print(f" me(): {client.morpheus.me()}")
|
|
41
|
+
print(f" balance(): {client.morpheus.balance()}")
|
|
42
|
+
except Exception as e:
|
|
43
|
+
print(f" call failed (likely invalid API key): {e}")
|
|
44
|
+
else:
|
|
45
|
+
print("\n(set HYPNEX_API_KEY to also see balance / me / keys)")
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Async client example.
|
|
2
|
+
|
|
3
|
+
Run: HYPNEX_API_KEY=mor_... python examples/06_async.py
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import asyncio
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
from hypnex_openai import AsyncHypnexOpenAI
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def main() -> None:
|
|
13
|
+
client = AsyncHypnexOpenAI(api_key=os.environ["HYPNEX_API_KEY"])
|
|
14
|
+
try:
|
|
15
|
+
# Run two requests concurrently.
|
|
16
|
+
a, b = await asyncio.gather(
|
|
17
|
+
client.chat.completions.create(
|
|
18
|
+
model="mistral-31-24b",
|
|
19
|
+
messages=[{"role": "user", "content": "Say hello in French."}],
|
|
20
|
+
),
|
|
21
|
+
client.chat.completions.create(
|
|
22
|
+
model="qwen3-235b",
|
|
23
|
+
messages=[{"role": "user", "content": "Say hello in Japanese."}],
|
|
24
|
+
),
|
|
25
|
+
)
|
|
26
|
+
print("mistral:", a.choices[0].message.content)
|
|
27
|
+
print("qwen: ", b.choices[0].message.content)
|
|
28
|
+
finally:
|
|
29
|
+
await client.close()
|
|
30
|
+
await client.morpheus.aclose()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if __name__ == "__main__":
|
|
34
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Tool / function calling. Works with any Morpheus model that supports tools.
|
|
2
|
+
|
|
3
|
+
Run: HYPNEX_API_KEY=mor_... python examples/07_tools.py
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
from hypnex_openai import HypnexOpenAI
|
|
10
|
+
|
|
11
|
+
client = HypnexOpenAI(api_key=os.environ["HYPNEX_API_KEY"])
|
|
12
|
+
|
|
13
|
+
tools = [
|
|
14
|
+
{
|
|
15
|
+
"type": "function",
|
|
16
|
+
"function": {
|
|
17
|
+
"name": "get_weather",
|
|
18
|
+
"description": "Get the current weather for a city.",
|
|
19
|
+
"parameters": {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"properties": {
|
|
22
|
+
"city": {"type": "string", "description": "City name"},
|
|
23
|
+
"units": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"enum": ["celsius", "fahrenheit"],
|
|
26
|
+
"default": "celsius",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
"required": ["city"],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_weather(city: str, units: str = "celsius") -> dict:
|
|
37
|
+
return {"city": city, "temp": 22 if units == "celsius" else 72, "units": units}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
messages = [{"role": "user", "content": "What's the weather in Paris?"}]
|
|
41
|
+
|
|
42
|
+
resp = client.chat.completions.create(
|
|
43
|
+
model="qwen3-coder-480b-a35b-instruct",
|
|
44
|
+
messages=messages,
|
|
45
|
+
tools=tools,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
msg = resp.choices[0].message
|
|
49
|
+
|
|
50
|
+
if msg.tool_calls:
|
|
51
|
+
for call in msg.tool_calls:
|
|
52
|
+
args = json.loads(call.function.arguments)
|
|
53
|
+
result = get_weather(**args)
|
|
54
|
+
messages.append(msg.model_dump())
|
|
55
|
+
messages.append(
|
|
56
|
+
{
|
|
57
|
+
"role": "tool",
|
|
58
|
+
"tool_call_id": call.id,
|
|
59
|
+
"content": json.dumps(result),
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
final = client.chat.completions.create(
|
|
64
|
+
model="qwen3-coder-480b-a35b-instruct",
|
|
65
|
+
messages=messages,
|
|
66
|
+
tools=tools,
|
|
67
|
+
)
|
|
68
|
+
print(final.choices[0].message.content)
|
|
69
|
+
else:
|
|
70
|
+
print(msg.content)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Embeddings via the Morpheus network.
|
|
2
|
+
|
|
3
|
+
Run: HYPNEX_API_KEY=mor_... python examples/08_embeddings.py
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
|
|
8
|
+
from hypnex_openai import HypnexOpenAI
|
|
9
|
+
|
|
10
|
+
client = HypnexOpenAI(api_key=os.environ["HYPNEX_API_KEY"])
|
|
11
|
+
|
|
12
|
+
resp = client.embeddings.create(
|
|
13
|
+
model="text-embedding-bge-m3",
|
|
14
|
+
input=[
|
|
15
|
+
"Morpheus is a decentralized AI network.",
|
|
16
|
+
"Bittensor is a decentralized ML network.",
|
|
17
|
+
],
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
for i, item in enumerate(resp.data):
|
|
21
|
+
vec = item.embedding
|
|
22
|
+
print(f"vector {i}: dim={len(vec)} first5={vec[:5]}")
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "hypnex-openai"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Drop-in OpenAI client for the Morpheus decentralized inference network (mor.org)"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = { text = "MIT" }
|
|
7
|
+
requires-python = ">=3.9"
|
|
8
|
+
authors = [{ name = "Hypnex Labs" }]
|
|
9
|
+
keywords = ["openai", "morpheus", "llm", "ai", "decentralized", "crypto", "agents"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"Intended Audience :: Developers",
|
|
13
|
+
"License :: OSI Approved :: MIT License",
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.9",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"openai>=1.50.0,<2.0.0",
|
|
23
|
+
"httpx>=0.27.0",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.optional-dependencies]
|
|
27
|
+
dev = [
|
|
28
|
+
"pytest>=8.0",
|
|
29
|
+
"pytest-asyncio>=0.23",
|
|
30
|
+
"ruff>=0.5",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
hypnex = "hypnex_openai.__main__:main"
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://hypnex.xyz"
|
|
38
|
+
Documentation = "https://docs.hypnex.xyz"
|
|
39
|
+
Repository = "https://github.com/hypnex-labs/hypnex"
|
|
40
|
+
Issues = "https://github.com/hypnex-labs/hypnex/issues"
|
|
41
|
+
|
|
42
|
+
[build-system]
|
|
43
|
+
requires = ["hatchling"]
|
|
44
|
+
build-backend = "hatchling.build"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
packages = ["src/hypnex_openai"]
|
|
48
|
+
|
|
49
|
+
[tool.pytest.ini_options]
|
|
50
|
+
testpaths = ["tests"]
|
|
51
|
+
asyncio_mode = "auto"
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
line-length = 100
|
|
55
|
+
target-version = "py39"
|