initial commit
This commit is contained in:
commit
75c5c2db63
6 changed files with 58 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/.venv
|
||||
__pycache__
|
7
README.md
Normal file
7
README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# llm-ui
|
||||
|
||||
```shell
|
||||
$ uv venv
|
||||
$ uv pip install -r requirements.txt
|
||||
$ uv run uvicorn server:app
|
||||
```
|
BIN
requirements.txt
Normal file
BIN
requirements.txt
Normal file
Binary file not shown.
11
server/__init__.py
Normal file
11
server/__init__.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from server.http import Starlette, Route, Request, Response, JSONResponse, WebSocketRoute
|
||||
from server.inference import list_conversations, connect_to_conversation
|
||||
|
||||
async def status(request: Request) -> Response:
|
||||
return JSONResponse({"status": "ok"})
|
||||
|
||||
app = Starlette(debug=True, routes=[
|
||||
Route("/api/", status),
|
||||
Route("/api/conversation", list_conversations, methods=["GET"]),
|
||||
WebSocketRoute("/api/conversation/:conversation/connect", connect_to_conversation)
|
||||
])
|
5
server/http.py
Normal file
5
server/http.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
from starlette.applications import Starlette
|
||||
from starlette.routing import Route, WebSocketRoute
|
||||
from starlette.responses import *
|
||||
from starlette.requests import *
|
||||
from starlette.websockets import WebSocket
|
33
server/inference.py
Normal file
33
server/inference.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
import llm, llm.cli, sqlite_utils
|
||||
from .http import Request, JSONResponse, WebSocket, RedirectResponse
|
||||
import json
|
||||
|
||||
db = sqlite_utils.Database(llm.cli.logs_db_path())
|
||||
|
||||
async def list_conversations(request: Request):
|
||||
conversations = []
|
||||
for row in db["conversations"].rows:
|
||||
conversations.append({ "id": row["id"], "name": row["name"] })
|
||||
return JSONResponse(conversations)
|
||||
|
||||
girlypop_prompt = llm.cli.load_template("girlypop").system
|
||||
|
||||
async def connect_to_conversation(ws: WebSocket):
|
||||
conversation_id = ws.path_params["conversation"]
|
||||
if conversation_id == "new":
|
||||
conversation = llm.AsyncConversation(llm.get_async_model())
|
||||
else:
|
||||
try:
|
||||
conversation: llm.AsyncConversation = llm.cli.load_conversation(conversation_id, async_=True)
|
||||
except:
|
||||
await ws.send_denial_response(JSONResponse({
|
||||
"error": "unable to load conversation {}".format(conversation_id)
|
||||
}))
|
||||
return
|
||||
|
||||
await ws.accept()
|
||||
async for message in ws.iter_text():
|
||||
response = conversation.prompt(message, system=girlypop_prompt)
|
||||
async for chunk in response:
|
||||
ws.send_text(json.dumps({"c": chunk}))
|
||||
ws.send_text(json.dumps({"d": True})) # done
|
Loading…
Reference in a new issue