Update server.py
Browse files
server.py
CHANGED
|
@@ -1,4 +1,12 @@
|
|
| 1 |
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
from flask import Flask, request, jsonify, Response
|
| 4 |
from huggingface_hub import snapshot_download
|
|
@@ -16,6 +24,7 @@ import platform
|
|
| 16 |
import shutil
|
| 17 |
import shlex
|
| 18 |
import torch
|
|
|
|
| 19 |
|
| 20 |
API_DB_PATH = os.environ.get("API_DB_PATH", "./api_keys.sqlite3")
|
| 21 |
|
|
@@ -1680,48 +1689,41 @@ def assist_rewrite():
|
|
| 1680 |
out = llm_generate_text_exact(model, sys, user, max_new_tokens={"short":400,"medium":1200,"long":2400,"xl":4800}[length])
|
| 1681 |
return jsonify({"new_content": _sanitize_generated_content(None, "text", out)})
|
| 1682 |
|
| 1683 |
-
|
| 1684 |
-
def home():
|
| 1685 |
-
# Content negotiation: keep JSON for scripts/health probes
|
| 1686 |
-
accept = (request.headers.get("accept") or "").lower()
|
| 1687 |
-
if "application/json" in accept or request.args.get("format") == "json":
|
| 1688 |
-
return jsonify(ok=True, model=MODEL_NAME, endpoints=["/infer", "/execute", "/gen", "/status"])
|
| 1689 |
-
|
| 1690 |
-
html = f"""<!doctype html>
|
| 1691 |
<html lang="en">
|
| 1692 |
<head>
|
| 1693 |
<meta charset="utf-8"/>
|
| 1694 |
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
| 1695 |
<title>Axis Β· Llama3 Agent API</title>
|
| 1696 |
<style>
|
| 1697 |
-
:root {
|
| 1698 |
-
* {
|
| 1699 |
-
body {
|
| 1700 |
-
header {
|
| 1701 |
-
.badge {
|
| 1702 |
-
h1 {
|
| 1703 |
-
.sub {
|
| 1704 |
-
.grid {
|
| 1705 |
-
.card {
|
| 1706 |
-
.card h3 {
|
| 1707 |
-
pre, code, textarea {
|
| 1708 |
-
pre {
|
| 1709 |
-
.row {
|
| 1710 |
-
textarea {
|
| 1711 |
-
input[type="password"] {
|
| 1712 |
-
button {
|
| 1713 |
-
button:disabled {
|
| 1714 |
-
.muted {
|
| 1715 |
-
footer {
|
| 1716 |
-
a {
|
| 1717 |
-
.ok {
|
| 1718 |
</style>
|
| 1719 |
</head>
|
| 1720 |
<body>
|
| 1721 |
<header>
|
| 1722 |
<span class="badge">Axis Β· Llama3 Agent API</span>
|
| 1723 |
<h1>Welcome π</h1>
|
| 1724 |
-
<p class="sub">This Space exposes a tiny agent server powered by <b
|
| 1725 |
Use it with our CLI client, or hit the HTTP endpoints directly.</p>
|
| 1726 |
<div class="row muted">
|
| 1727 |
<div>Live status: <span class="ok">Running</span></div>
|
|
@@ -1742,17 +1744,17 @@ python3 client.py</pre>
|
|
| 1742 |
<pre>curl -X POST "$LLAMA_SERVER/infer" \
|
| 1743 |
-H "content-type: application/json" \
|
| 1744 |
-H "authorization: Bearer <your-key>" \
|
| 1745 |
-
-d '{
|
| 1746 |
|
| 1747 |
<pre>curl -X POST "$LLAMA_SERVER/execute" \
|
| 1748 |
-H "content-type: application/json" \
|
| 1749 |
-H "authorization: Bearer <your-key>" \
|
| 1750 |
-
-d '{
|
| 1751 |
|
| 1752 |
<pre>curl -X POST "$LLAMA_SERVER/gen" \
|
| 1753 |
-H "content-type: application/json" \
|
| 1754 |
-H "authorization: Bearer <your-key>" \
|
| 1755 |
-
-d '{
|
| 1756 |
</div>
|
| 1757 |
|
| 1758 |
<div class="card">
|
|
@@ -1774,9 +1776,9 @@ python3 client.py</pre>
|
|
| 1774 |
<div class="card">
|
| 1775 |
<h3>Endpoint contract</h3>
|
| 1776 |
<ul class="muted">
|
| 1777 |
-
<li><code>POST /infer</code> β <code>{
|
| 1778 |
-
<li><code>POST /execute</code> with <code>{
|
| 1779 |
-
<li><code>POST /gen</code> with <code>{
|
| 1780 |
<li><code>GET /status</code> β JSON status</li>
|
| 1781 |
<li><span class="muted">Send <code>Authorization: Bearer <token></code> if your server enforces API keys.</span></li>
|
| 1782 |
</ul>
|
|
@@ -1784,37 +1786,43 @@ python3 client.py</pre>
|
|
| 1784 |
</section>
|
| 1785 |
|
| 1786 |
<footer>
|
| 1787 |
-
<p>Built by TanDev Β· Axis server Β· Model: <b
|
| 1788 |
</footer>
|
| 1789 |
|
| 1790 |
<script>
|
| 1791 |
const $ = (id)=>document.getElementById(id);
|
| 1792 |
-
$("run").addEventListener("click", async () => {
|
| 1793 |
$("run").disabled = true; $("status").textContent = "Calling /inferβ¦";
|
| 1794 |
$("out").textContent = "";
|
| 1795 |
-
try {
|
| 1796 |
-
const headers = {
|
| 1797 |
const key = $("key").value.trim();
|
| 1798 |
if (key) headers["authorization"] = key.startsWith("Bearer ") ? key : ("Bearer " + key);
|
| 1799 |
-
const r = await fetch("/infer", {
|
| 1800 |
-
method:"POST", headers, body: JSON.stringify({
|
| 1801 |
-
}
|
| 1802 |
const txt = await r.text();
|
| 1803 |
$("out").textContent = txt;
|
| 1804 |
$("status").textContent = r.ok ? "OK" : ("HTTP " + r.status);
|
| 1805 |
-
}
|
| 1806 |
$("status").textContent = "Error";
|
| 1807 |
$("out").textContent = String(e);
|
| 1808 |
-
}
|
| 1809 |
$("run").disabled = false;
|
| 1810 |
-
}
|
| 1811 |
-
}
|
| 1812 |
</script>
|
| 1813 |
</body>
|
| 1814 |
-
</html>"""
|
| 1815 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1816 |
|
| 1817 |
-
# Optional: keep a fixed JSON status endpoint for monitors
|
| 1818 |
@app.get("/status")
|
| 1819 |
def status():
|
| 1820 |
return jsonify(ok=True, model=MODEL_NAME)
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Llama 3 CLI-Agent Server
|
| 4 |
+
ββββββββββββββββββββββββ
|
| 5 |
+
Gemini-CLI style planner + executor:
|
| 6 |
+
β’ plan with Meta-Llama-3-8B-Instruct
|
| 7 |
+
β’ steps: shell, read_file, write_file, edit_file, append_file, list_dir, python, respond
|
| 8 |
+
β’ robust JSON extraction (balanced braces) to avoid parse failures
|
| 9 |
+
"""
|
| 10 |
|
| 11 |
from flask import Flask, request, jsonify, Response
|
| 12 |
from huggingface_hub import snapshot_download
|
|
|
|
| 24 |
import shutil
|
| 25 |
import shlex
|
| 26 |
import torch
|
| 27 |
+
from string import Template
|
| 28 |
|
| 29 |
API_DB_PATH = os.environ.get("API_DB_PATH", "./api_keys.sqlite3")
|
| 30 |
|
|
|
|
| 1689 |
out = llm_generate_text_exact(model, sys, user, max_new_tokens={"short":400,"medium":1200,"long":2400,"xl":4800}[length])
|
| 1690 |
return jsonify({"new_content": _sanitize_generated_content(None, "text", out)})
|
| 1691 |
|
| 1692 |
+
HOME_HTML = Template(r"""<!doctype html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1693 |
<html lang="en">
|
| 1694 |
<head>
|
| 1695 |
<meta charset="utf-8"/>
|
| 1696 |
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
| 1697 |
<title>Axis Β· Llama3 Agent API</title>
|
| 1698 |
<style>
|
| 1699 |
+
:root { --bg:#0b0f17; --fg:#e6eef8; --muted:#a9b7c6; --card:#121825; --accent:#7aa2f7; --ok:#38d39f; --bad:#ff6b6b; }
|
| 1700 |
+
* { box-sizing:border-box; }
|
| 1701 |
+
body { margin:0; font:15px/1.55 system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, 'Helvetica Neue', Arial; background:radial-gradient(1200px 600px at 10% -10%, #122034, transparent), var(--bg); color:var(--fg); }
|
| 1702 |
+
header { padding:36px 20px 10px; max-width:980px; margin:0 auto; }
|
| 1703 |
+
.badge { display:inline-block; padding:4px 10px; border:1px solid #2c3650; border-radius:999px; font-size:12px; color:var(--muted); }
|
| 1704 |
+
h1 { margin:12px 0 8px; font-size:28px; letter-spacing:.2px; }
|
| 1705 |
+
.sub { color:var(--muted); margin:0 0 18px; }
|
| 1706 |
+
.grid { display:grid; grid-template-columns: 1.1fr 1fr; gap:18px; max-width:980px; padding:0 20px 36px; margin:0 auto; }
|
| 1707 |
+
.card { background:linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.00)); border:1px solid #1a2336; border-radius:14px; padding:16px; }
|
| 1708 |
+
.card h3 { margin:0 0 8px; font-size:16px; }
|
| 1709 |
+
pre, code, textarea { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; }
|
| 1710 |
+
pre { background:#0e1422; color:#cfe3ff; padding:12px; border-radius:10px; overflow:auto; border:1px solid #1a2336; }
|
| 1711 |
+
.row { display:flex; gap:10px; align-items:center; flex-wrap:wrap; }
|
| 1712 |
+
textarea { width:100%; min-height:120px; padding:10px; border-radius:10px; border:1px solid #202a40; background:#0e1422; color:#e6eef8; }
|
| 1713 |
+
input[type="password"] { width:100%; padding:10px; border-radius:10px; border:1px solid #202a40; background:#0e1422; color:#e6eef8; }
|
| 1714 |
+
button { background:var(--accent); color:#0b0f17; border:none; padding:10px 14px; border-radius:10px; cursor:pointer; font-weight:600; }
|
| 1715 |
+
button:disabled { filter:grayscale(.5); opacity:.7; cursor:not-allowed; }
|
| 1716 |
+
.muted { color:var(--muted); }
|
| 1717 |
+
footer { max-width:980px; margin:0 auto 32px; padding:0 20px; color:var(--muted); }
|
| 1718 |
+
a { color:#9ec1ff; text-decoration:none; }
|
| 1719 |
+
.ok { color:var(--ok); }
|
| 1720 |
</style>
|
| 1721 |
</head>
|
| 1722 |
<body>
|
| 1723 |
<header>
|
| 1724 |
<span class="badge">Axis Β· Llama3 Agent API</span>
|
| 1725 |
<h1>Welcome π</h1>
|
| 1726 |
+
<p class="sub">This Space exposes a tiny agent server powered by <b>$MODEL</b>.
|
| 1727 |
Use it with our CLI client, or hit the HTTP endpoints directly.</p>
|
| 1728 |
<div class="row muted">
|
| 1729 |
<div>Live status: <span class="ok">Running</span></div>
|
|
|
|
| 1744 |
<pre>curl -X POST "$LLAMA_SERVER/infer" \
|
| 1745 |
-H "content-type: application/json" \
|
| 1746 |
-H "authorization: Bearer <your-key>" \
|
| 1747 |
+
-d '{"prompt":"List three things this API can do"}'</pre>
|
| 1748 |
|
| 1749 |
<pre>curl -X POST "$LLAMA_SERVER/execute" \
|
| 1750 |
-H "content-type: application/json" \
|
| 1751 |
-H "authorization: Bearer <your-key>" \
|
| 1752 |
+
-d '{"plan":{"steps":[{"type":"respond","text":"Hello from Axis"}]}}'</pre>
|
| 1753 |
|
| 1754 |
<pre>curl -X POST "$LLAMA_SERVER/gen" \
|
| 1755 |
-H "content-type: application/json" \
|
| 1756 |
-H "authorization: Bearer <your-key>" \
|
| 1757 |
+
-d '{"format":"text","instruction":"one-line haiku about security"}'</pre>
|
| 1758 |
</div>
|
| 1759 |
|
| 1760 |
<div class="card">
|
|
|
|
| 1776 |
<div class="card">
|
| 1777 |
<h3>Endpoint contract</h3>
|
| 1778 |
<ul class="muted">
|
| 1779 |
+
<li><code>POST /infer</code> β <code>{"plan":{"steps":[...]}}</code> (first call may be slow while the Space warms up)</li>
|
| 1780 |
+
<li><code>POST /execute</code> with <code>{"plan": ...}</code> β <code>{"results":[...]}</code></li>
|
| 1781 |
+
<li><code>POST /gen</code> with <code>{"format","instruction","length"}</code> β <code>{"content":"..."}</code></li>
|
| 1782 |
<li><code>GET /status</code> β JSON status</li>
|
| 1783 |
<li><span class="muted">Send <code>Authorization: Bearer <token></code> if your server enforces API keys.</span></li>
|
| 1784 |
</ul>
|
|
|
|
| 1786 |
</section>
|
| 1787 |
|
| 1788 |
<footer>
|
| 1789 |
+
<p>Built by TanDev Β· Axis server Β· Model: <b>$MODEL</b>. For programmatic checks, hit <a href="/status">/status</a> or request <code>Accept: application/json</code> on <code>/</code>.</p>
|
| 1790 |
</footer>
|
| 1791 |
|
| 1792 |
<script>
|
| 1793 |
const $ = (id)=>document.getElementById(id);
|
| 1794 |
+
$("run").addEventListener("click", async () => {
|
| 1795 |
$("run").disabled = true; $("status").textContent = "Calling /inferβ¦";
|
| 1796 |
$("out").textContent = "";
|
| 1797 |
+
try {
|
| 1798 |
+
const headers = { "content-type": "application/json" };
|
| 1799 |
const key = $("key").value.trim();
|
| 1800 |
if (key) headers["authorization"] = key.startsWith("Bearer ") ? key : ("Bearer " + key);
|
| 1801 |
+
const r = await fetch("/infer", {
|
| 1802 |
+
method:"POST", headers, body: JSON.stringify({ prompt: $("prompt").value })
|
| 1803 |
+
});
|
| 1804 |
const txt = await r.text();
|
| 1805 |
$("out").textContent = txt;
|
| 1806 |
$("status").textContent = r.ok ? "OK" : ("HTTP " + r.status);
|
| 1807 |
+
} catch (e) {
|
| 1808 |
$("status").textContent = "Error";
|
| 1809 |
$("out").textContent = String(e);
|
| 1810 |
+
} finally {
|
| 1811 |
$("run").disabled = false;
|
| 1812 |
+
}
|
| 1813 |
+
});
|
| 1814 |
</script>
|
| 1815 |
</body>
|
| 1816 |
+
</html>""")
|
| 1817 |
+
|
| 1818 |
+
@app.get("/")
|
| 1819 |
+
def home():
|
| 1820 |
+
# Keep JSON for probes/clients
|
| 1821 |
+
accept = (request.headers.get("accept") or "").lower()
|
| 1822 |
+
if "application/json" in accept or request.args.get("format") == "json":
|
| 1823 |
+
return jsonify(ok=True, model=MODEL_NAME, endpoints=["/infer", "/execute", "/gen", "/status"])
|
| 1824 |
+
return Response(HOME_HTML.substitute(MODEL=MODEL_NAME), mimetype="text/html")
|
| 1825 |
|
|
|
|
| 1826 |
@app.get("/status")
|
| 1827 |
def status():
|
| 1828 |
return jsonify(ok=True, model=MODEL_NAME)
|