entroplain 0.1.0 → 0.1.1
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.
- package/dist/entroplain-0.1.1-py3-none-any.whl +0 -0
- package/dist/entroplain-0.1.1.tar.gz +0 -0
- package/docs/AGENT_USAGE.md +178 -0
- package/entroplain/__init__.py +4 -1
- package/entroplain/proxy.py +278 -0
- package/package.json +1 -1
- package/pyproject.toml +5 -1
- package/dist/entroplain-0.1.0-py3-none-any.whl +0 -0
- package/dist/entroplain-0.1.0.tar.gz +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Entroplain Usage Guide for Agents
|
|
2
|
+
|
|
3
|
+
## Quick Setup
|
|
4
|
+
|
|
5
|
+
### For OpenClaw/Claude Code (Proxy Method)
|
|
6
|
+
|
|
7
|
+
Run the entropy proxy and point your agent to it:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Start the proxy (monitors entropy, enables early exit)
|
|
11
|
+
python -m entroplain.proxy --port 8765 --log-entropy
|
|
12
|
+
|
|
13
|
+
# Set environment to use proxy
|
|
14
|
+
export OPENAI_BASE_URL=http://localhost:8765/v1
|
|
15
|
+
# or for NVIDIA:
|
|
16
|
+
export NVIDIA_BASE_URL=http://localhost:8765/v1
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Now OpenClaw/Claude Code will automatically have entropy monitoring!
|
|
20
|
+
|
|
21
|
+
### How the Proxy Works
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Agent -> Proxy (localhost:8765) -> Real API
|
|
25
|
+
|
|
|
26
|
+
v
|
|
27
|
+
Entropy Monitor
|
|
28
|
+
|
|
|
29
|
+
v
|
|
30
|
+
Early Exit Check
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The proxy:
|
|
34
|
+
1. Intercepts all chat completion requests
|
|
35
|
+
2. Enables logprobs automatically
|
|
36
|
+
3. Calculates entropy for each token
|
|
37
|
+
4. Terminates stream when reasoning converges
|
|
38
|
+
5. Passes everything through unchanged to the agent
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Direct Usage (Python)
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from entroplain import EntropyMonitor, NVIDIAProvider
|
|
46
|
+
|
|
47
|
+
monitor = EntropyMonitor()
|
|
48
|
+
provider = NVIDIAProvider()
|
|
49
|
+
|
|
50
|
+
for token in provider.stream_with_entropy(
|
|
51
|
+
model="meta/llama-3.1-70b-instruct",
|
|
52
|
+
messages=[{"role": "user", "content": "Solve: x^2 = 16"}]
|
|
53
|
+
):
|
|
54
|
+
monitor.track(token.token, token.entropy)
|
|
55
|
+
print(token.token, end="")
|
|
56
|
+
|
|
57
|
+
if monitor.should_exit():
|
|
58
|
+
print("\n[Early exit - reasoning converged]")
|
|
59
|
+
break
|
|
60
|
+
|
|
61
|
+
print(f"\nStats: {monitor.get_stats()}")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Supported Providers
|
|
67
|
+
|
|
68
|
+
| Provider | Works? | How |
|
|
69
|
+
|----------|--------|-----|
|
|
70
|
+
| OpenAI | YES | `logprobs: true` |
|
|
71
|
+
| NVIDIA NIM | YES | OpenAI-compatible |
|
|
72
|
+
| Anthropic Claude 4 | YES | `logprobs: True` |
|
|
73
|
+
| Google Gemini | YES | `response_logprobs=True` |
|
|
74
|
+
| Ollama (local) | YES | Built-in logit access |
|
|
75
|
+
| llama.cpp | YES | Built-in logit access |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Configuration
|
|
80
|
+
|
|
81
|
+
### Exit Conditions
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
monitor = EntropyMonitor(
|
|
85
|
+
entropy_threshold=0.15, # Exit when entropy drops below this
|
|
86
|
+
min_valleys=2, # Require N reasoning milestones
|
|
87
|
+
min_tokens=50, # Don't exit before this many tokens
|
|
88
|
+
velocity_threshold=0.05, # Exit when change rate stabilizes
|
|
89
|
+
exit_condition="combined" # or: "valleys_plateau", "entropy_drop", "velocity_zero"
|
|
90
|
+
)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Environment Variables
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# API keys (used by providers)
|
|
97
|
+
export OPENAI_API_KEY=sk-...
|
|
98
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
99
|
+
export NVIDIA_API_KEY=nvapi-...
|
|
100
|
+
export GOOGLE_API_KEY=...
|
|
101
|
+
|
|
102
|
+
# For proxy
|
|
103
|
+
export ENTROPPLAIN_PORT=8765
|
|
104
|
+
export ENTROPPLAIN_LOG_ENTROPY=true
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## CLI
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Analyze a prompt
|
|
113
|
+
entroplain analyze "What is 2+2?" --model gpt-4o
|
|
114
|
+
|
|
115
|
+
# Stream with early exit
|
|
116
|
+
entroplain stream "Explain quantum computing" --exit-on-converge
|
|
117
|
+
|
|
118
|
+
# Run proxy
|
|
119
|
+
entroplain proxy --port 8765 --log-entropy
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Agent Integration Examples
|
|
125
|
+
|
|
126
|
+
### OpenClaw with Proxy
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
# In config.yaml
|
|
130
|
+
llm:
|
|
131
|
+
provider: openai-compatible
|
|
132
|
+
base_url: http://localhost:8765/v1 # Point to proxy
|
|
133
|
+
primary_model: meta/llama-3.1-70b-instruct
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Claude Code with Proxy
|
|
137
|
+
|
|
138
|
+
Set environment before running:
|
|
139
|
+
```bash
|
|
140
|
+
export ANTHROPIC_BASE_URL=http://localhost:8765/v1
|
|
141
|
+
claude
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Custom Agent
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from entroplain.hooks import EntropyHook
|
|
148
|
+
|
|
149
|
+
hook = EntropyHook(config={"entropy_threshold": 0.15})
|
|
150
|
+
|
|
151
|
+
for token in your_agent.generate_stream():
|
|
152
|
+
result = hook.on_token(token.text, token.entropy)
|
|
153
|
+
|
|
154
|
+
if result["should_exit"]:
|
|
155
|
+
print(f"Early exit at token {result['index']}")
|
|
156
|
+
break
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Troubleshooting
|
|
162
|
+
|
|
163
|
+
### "No logprobs returned"
|
|
164
|
+
Some models don't support logprobs. Try a different model or check provider docs.
|
|
165
|
+
|
|
166
|
+
### "Entropy is always 0"
|
|
167
|
+
Make sure `logprobs: true` and `top_logprobs: 5` are set in your API request.
|
|
168
|
+
|
|
169
|
+
### "Proxy won't start"
|
|
170
|
+
Install dependencies: `pip install entroplain[all] fastapi uvicorn httpx`
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Learn More
|
|
175
|
+
|
|
176
|
+
- GitHub: https://github.com/entroplain/entroplain
|
|
177
|
+
- PyPI: https://pypi.org/project/entroplain/
|
|
178
|
+
- npm: https://www.npmjs.com/package/entroplain
|
package/entroplain/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Entroplain — Entropy-based early exit for efficient agent reasoning.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
__version__ = "0.1.
|
|
5
|
+
__version__ = "0.1.1"
|
|
6
6
|
__author__ = "Entroplain Contributors"
|
|
7
7
|
|
|
8
8
|
from .monitor import EntropyMonitor, calculate_entropy
|
|
@@ -15,6 +15,7 @@ from .providers import (
|
|
|
15
15
|
LlamaCppProvider,
|
|
16
16
|
)
|
|
17
17
|
from .hooks import track_entropy, early_exit
|
|
18
|
+
from .proxy import EntropyProxy, ProxyConfig
|
|
18
19
|
|
|
19
20
|
__all__ = [
|
|
20
21
|
"EntropyMonitor",
|
|
@@ -27,4 +28,6 @@ __all__ = [
|
|
|
27
28
|
"LlamaCppProvider",
|
|
28
29
|
"track_entropy",
|
|
29
30
|
"early_exit",
|
|
31
|
+
"EntropyProxy",
|
|
32
|
+
"ProxyConfig",
|
|
30
33
|
]
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Entropy Monitoring Proxy for OpenClaw/Claude Code.
|
|
3
|
+
|
|
4
|
+
This proxy intercepts LLM API calls and adds entropy monitoring,
|
|
5
|
+
enabling early exit without modifying the agent framework itself.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
# Set as your API endpoint
|
|
9
|
+
export OPENAI_BASE_URL=http://localhost:8765
|
|
10
|
+
|
|
11
|
+
# Run the proxy
|
|
12
|
+
python -m entroplain.proxy --port 8765 --provider openai
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import asyncio
|
|
17
|
+
import logging
|
|
18
|
+
from typing import Optional, Dict, Any, AsyncIterator
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
import httpx
|
|
21
|
+
from fastapi import FastAPI, Request, Response
|
|
22
|
+
from fastapi.responses import StreamingResponse
|
|
23
|
+
import uvicorn
|
|
24
|
+
|
|
25
|
+
from .monitor import EntropyMonitor
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class ProxyConfig:
|
|
32
|
+
"""Configuration for the entropy proxy."""
|
|
33
|
+
port: int = 8765
|
|
34
|
+
provider: str = "openai" # openai, anthropic, nvidia
|
|
35
|
+
api_base: str = "https://api.openai.com/v1"
|
|
36
|
+
entropy_threshold: float = 0.15
|
|
37
|
+
min_valleys: int = 2
|
|
38
|
+
min_tokens: int = 50
|
|
39
|
+
velocity_threshold: float = 0.05
|
|
40
|
+
enable_early_exit: bool = True
|
|
41
|
+
log_entropy: bool = True
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class EntropyProxy:
|
|
45
|
+
"""
|
|
46
|
+
Proxy that adds entropy monitoring to LLM API calls.
|
|
47
|
+
|
|
48
|
+
Intercepts streaming responses, calculates entropy, and can
|
|
49
|
+
terminate early when reasoning has converged.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(self, config: ProxyConfig):
|
|
53
|
+
self.config = config
|
|
54
|
+
self.monitor = EntropyMonitor(
|
|
55
|
+
entropy_threshold=config.entropy_threshold,
|
|
56
|
+
min_valleys=config.min_valleys,
|
|
57
|
+
min_tokens=config.min_tokens,
|
|
58
|
+
velocity_threshold=config.velocity_threshold
|
|
59
|
+
)
|
|
60
|
+
self.app = FastAPI(title="Entroplain Proxy")
|
|
61
|
+
self._setup_routes()
|
|
62
|
+
|
|
63
|
+
def _setup_routes(self):
|
|
64
|
+
@self.app.post("/v1/chat/completions")
|
|
65
|
+
async def chat_completions(request: Request):
|
|
66
|
+
return await self._handle_chat(request)
|
|
67
|
+
|
|
68
|
+
@self.app.get("/health")
|
|
69
|
+
async def health():
|
|
70
|
+
return {"status": "ok", "monitor": self.monitor.get_stats()}
|
|
71
|
+
|
|
72
|
+
@self.app.post("/reset")
|
|
73
|
+
async def reset():
|
|
74
|
+
self.monitor.reset()
|
|
75
|
+
return {"status": "reset"}
|
|
76
|
+
|
|
77
|
+
async def _handle_chat(self, request: Request):
|
|
78
|
+
"""Handle chat completion requests with entropy monitoring."""
|
|
79
|
+
body = await request.json()
|
|
80
|
+
|
|
81
|
+
# Ensure logprobs are enabled for entropy calculation
|
|
82
|
+
if "logprobs" not in body:
|
|
83
|
+
body["logprobs"] = True
|
|
84
|
+
if "top_logprobs" not in body:
|
|
85
|
+
body["top_logprobs"] = 5
|
|
86
|
+
|
|
87
|
+
# Reset monitor for new request
|
|
88
|
+
self.monitor.reset()
|
|
89
|
+
|
|
90
|
+
# Forward request to actual API
|
|
91
|
+
async with httpx.AsyncClient() as client:
|
|
92
|
+
response = await client.post(
|
|
93
|
+
f"{self.config.api_base}/chat/completions",
|
|
94
|
+
json=body,
|
|
95
|
+
headers={
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
"Authorization": request.headers.get("Authorization", "")
|
|
98
|
+
},
|
|
99
|
+
timeout=120.0
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
if not body.get("stream", False):
|
|
103
|
+
# Non-streaming: just return response
|
|
104
|
+
return Response(
|
|
105
|
+
content=response.content,
|
|
106
|
+
status_code=response.status_code,
|
|
107
|
+
headers=dict(response.headers)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# Streaming: monitor entropy and potentially exit early
|
|
111
|
+
return StreamingResponse(
|
|
112
|
+
self._stream_with_entropy(response),
|
|
113
|
+
media_type="text/event-stream"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
async def _stream_with_entropy(
|
|
117
|
+
self, response: httpx.Response
|
|
118
|
+
) -> AsyncIterator[str]:
|
|
119
|
+
"""Stream response with entropy monitoring."""
|
|
120
|
+
exited_early = False
|
|
121
|
+
full_content = ""
|
|
122
|
+
|
|
123
|
+
async for line in response.aiter_lines():
|
|
124
|
+
if not line.startswith("data: "):
|
|
125
|
+
yield line + "\n"
|
|
126
|
+
continue
|
|
127
|
+
|
|
128
|
+
data = line[6:] # Remove "data: " prefix
|
|
129
|
+
if data == "[DONE]":
|
|
130
|
+
yield line + "\n"
|
|
131
|
+
break
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
chunk = json.loads(data)
|
|
135
|
+
except json.JSONDecodeError:
|
|
136
|
+
yield line + "\n"
|
|
137
|
+
continue
|
|
138
|
+
|
|
139
|
+
# Extract token and logprobs
|
|
140
|
+
if chunk.get("choices"):
|
|
141
|
+
choice = chunk["choices"][0]
|
|
142
|
+
|
|
143
|
+
# Get token content
|
|
144
|
+
if choice.get("delta", {}).get("content"):
|
|
145
|
+
token = choice["delta"]["content"]
|
|
146
|
+
full_content += token
|
|
147
|
+
|
|
148
|
+
# Calculate entropy from logprobs
|
|
149
|
+
if choice.get("logprobs", {}).get("content"):
|
|
150
|
+
logprobs_data = choice["logprobs"]["content"]
|
|
151
|
+
if logprobs_data:
|
|
152
|
+
entropy = self._calculate_entropy(logprobs_data[0])
|
|
153
|
+
self.monitor.track(token, entropy)
|
|
154
|
+
|
|
155
|
+
if self.config.log_entropy:
|
|
156
|
+
logger.info(
|
|
157
|
+
f"Token: {repr(token)}, Entropy: {entropy:.4f}, "
|
|
158
|
+
f"Valleys: {len(self.monitor.get_valleys())}"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Check for early exit
|
|
162
|
+
if (
|
|
163
|
+
self.config.enable_early_exit
|
|
164
|
+
and self.monitor.should_exit()
|
|
165
|
+
):
|
|
166
|
+
logger.info(
|
|
167
|
+
f"Early exit triggered! "
|
|
168
|
+
f"Tokens: {len(full_content)}, "
|
|
169
|
+
f"Valleys: {len(self.monitor.get_valleys())}"
|
|
170
|
+
)
|
|
171
|
+
exited_early = True
|
|
172
|
+
yield "data: [DONE]\n\n"
|
|
173
|
+
break
|
|
174
|
+
|
|
175
|
+
yield line + "\n"
|
|
176
|
+
|
|
177
|
+
if not exited_early:
|
|
178
|
+
logger.info(
|
|
179
|
+
f"Stream completed. "
|
|
180
|
+
f"Tokens: {self.monitor.get_stats()['token_count']}, "
|
|
181
|
+
f"Valleys: {len(self.monitor.get_valleys())}"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def _calculate_entropy(self, logprobs_data: Dict) -> float:
|
|
185
|
+
"""Calculate Shannon entropy from logprobs."""
|
|
186
|
+
import math
|
|
187
|
+
|
|
188
|
+
if not logprobs_data or "top_logprobs" not in logprobs_data:
|
|
189
|
+
return 0.0
|
|
190
|
+
|
|
191
|
+
entropy = 0.0
|
|
192
|
+
for lp in logprobs_data["top_logprobs"]:
|
|
193
|
+
prob = math.exp(lp["logprob"])
|
|
194
|
+
if prob > 0:
|
|
195
|
+
entropy -= prob * math.log2(prob + 1e-10)
|
|
196
|
+
|
|
197
|
+
return entropy
|
|
198
|
+
|
|
199
|
+
def run(self):
|
|
200
|
+
"""Start the proxy server."""
|
|
201
|
+
uvicorn.run(self.app, host="0.0.0.0", port=self.config.port)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def main():
|
|
205
|
+
"""CLI entry point for running the proxy."""
|
|
206
|
+
import argparse
|
|
207
|
+
|
|
208
|
+
parser = argparse.ArgumentParser(description="Entropy Monitoring Proxy")
|
|
209
|
+
parser.add_argument("--port", type=int, default=8765, help="Proxy port")
|
|
210
|
+
parser.add_argument(
|
|
211
|
+
"--provider",
|
|
212
|
+
default="openai",
|
|
213
|
+
choices=["openai", "anthropic", "nvidia"],
|
|
214
|
+
help="LLM provider"
|
|
215
|
+
)
|
|
216
|
+
parser.add_argument(
|
|
217
|
+
"--api-base",
|
|
218
|
+
default="https://api.openai.com/v1",
|
|
219
|
+
help="API base URL"
|
|
220
|
+
)
|
|
221
|
+
parser.add_argument(
|
|
222
|
+
"--entropy-threshold",
|
|
223
|
+
type=float,
|
|
224
|
+
default=0.15,
|
|
225
|
+
help="Entropy threshold for early exit"
|
|
226
|
+
)
|
|
227
|
+
parser.add_argument(
|
|
228
|
+
"--min-valleys",
|
|
229
|
+
type=int,
|
|
230
|
+
default=2,
|
|
231
|
+
help="Minimum valleys before early exit"
|
|
232
|
+
)
|
|
233
|
+
parser.add_argument(
|
|
234
|
+
"--no-early-exit",
|
|
235
|
+
action="store_true",
|
|
236
|
+
help="Disable early exit (monitor only)"
|
|
237
|
+
)
|
|
238
|
+
parser.add_argument(
|
|
239
|
+
"--log-entropy",
|
|
240
|
+
action="store_true",
|
|
241
|
+
help="Log entropy values to console"
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
args = parser.parse_args()
|
|
245
|
+
|
|
246
|
+
config = ProxyConfig(
|
|
247
|
+
port=args.port,
|
|
248
|
+
provider=args.provider,
|
|
249
|
+
api_base=args.api_base,
|
|
250
|
+
entropy_threshold=args.entropy_threshold,
|
|
251
|
+
min_valleys=args.min_valleys,
|
|
252
|
+
enable_early_exit=not args.no_early_exit,
|
|
253
|
+
log_entropy=args.log_entropy
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
proxy = EntropyProxy(config)
|
|
257
|
+
|
|
258
|
+
print(f"""
|
|
259
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
260
|
+
║ ENTROPPLAIN ENTROPY MONITORING PROXY ║
|
|
261
|
+
╠═══════════════════════════════════════════════════════════╣
|
|
262
|
+
║ Proxy running on: http://localhost:{args.port} ║
|
|
263
|
+
║ Provider: {args.provider:<10} ║
|
|
264
|
+
║ API Base: {args.api_base:<30} ║
|
|
265
|
+
║ Early Exit: {'DISABLED' if args.no_early_exit else 'ENABLED'} ║
|
|
266
|
+
╠═══════════════════════════════════════════════════════════╣
|
|
267
|
+
║ Set your agent's API endpoint to: ║
|
|
268
|
+
║ export OPENAI_BASE_URL=http://localhost:{args.port} ║
|
|
269
|
+
║ # or for NVIDIA: ║
|
|
270
|
+
║ export NVIDIA_BASE_URL=http://localhost:{args.port} ║
|
|
271
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
272
|
+
""")
|
|
273
|
+
|
|
274
|
+
proxy.run()
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
if __name__ == "__main__":
|
|
278
|
+
main()
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "entroplain"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "Entropy-based early exit for efficient agent reasoning"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -44,6 +44,9 @@ all = [
|
|
|
44
44
|
"requests>=2.28.0",
|
|
45
45
|
"aiohttp>=3.8.0",
|
|
46
46
|
"llama-cpp-python>=0.2.0",
|
|
47
|
+
"fastapi>=0.100.0",
|
|
48
|
+
"uvicorn>=0.23.0",
|
|
49
|
+
"httpx>=0.24.0",
|
|
47
50
|
]
|
|
48
51
|
dev = [
|
|
49
52
|
"pytest>=7.0.0",
|
|
@@ -61,6 +64,7 @@ Issues = "https://github.com/entroplain/entroplain/issues"
|
|
|
61
64
|
|
|
62
65
|
[project.scripts]
|
|
63
66
|
entroplain = "entroplain.cli:main"
|
|
67
|
+
entroplain-proxy = "entroplain.proxy:main"
|
|
64
68
|
|
|
65
69
|
[tool.setuptools.packages.find]
|
|
66
70
|
where = ["."]
|
|
Binary file
|
|
Binary file
|