mirror of
https://github.com/serge-chat/serge.git
synced 2024-01-15 09:32:12 +03:00
Proper dev & deployment images. Converts front-end to SPA. (#84)
* begin work on dev environment * more work on dev image * working dev + prod images with SPA front-end * reworked dockerfile * make CI point to the right action * Improvements to github actions (#79) * Improvements to github actions * Change username to repo owner username * Add fix for login into ghcr (#81) * Update bug_report.yml * added dev instructions to readme * reduced number of steps in dockerfile --------- Co-authored-by: Juan Calderon-Perez <835733+gaby@users.noreply.github.com>
This commit is contained in:
1
.github/workflows/docker-image.yml
vendored
1
.github/workflows/docker-image.yml
vendored
@@ -49,6 +49,7 @@ jobs:
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
target: release
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
86
Dockerfile
86
Dockerfile
@@ -1,4 +1,5 @@
|
||||
FROM gcc:11 as llama_builder
|
||||
# Compile llama
|
||||
FROM gcc:11 as llama_builder
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
@@ -8,54 +9,73 @@ RUN cd llama.cpp && \
|
||||
make && \
|
||||
mv main llama
|
||||
|
||||
# Copy over rest of the project files
|
||||
# Base image for node
|
||||
FROM node:19 as node_base
|
||||
|
||||
FROM ubuntu:22.04 as deployment
|
||||
WORKDIR /usr/src/app
|
||||
# Install pip and requirements
|
||||
|
||||
# Base image for runtime
|
||||
FROM ubuntu:22.04 as base
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Europe/Amsterdam
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# install pip
|
||||
RUN apt update
|
||||
RUN apt-get install -y python3-pip curl wget
|
||||
RUN pip install --upgrade pip
|
||||
# Install MongoDB and necessary tools
|
||||
RUN apt update && \
|
||||
apt install -y curl wget gnupg python3-pip && \
|
||||
wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | apt-key add - && \
|
||||
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-6.0.list && \
|
||||
apt-get update && \
|
||||
apt-get install -y mongodb-org
|
||||
|
||||
# install nodejs
|
||||
RUN curl -sL https://deb.nodesource.com/setup_19.x | bash
|
||||
RUN apt-get install nodejs
|
||||
|
||||
|
||||
# MongoDB
|
||||
RUN wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | apt-key add -
|
||||
RUN echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-6.0.list
|
||||
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y mongodb-org
|
||||
|
||||
|
||||
# install requirements
|
||||
# copy & install python reqs
|
||||
COPY ./api/requirements.txt api/requirements.txt
|
||||
RUN pip install -r ./api/requirements.txt
|
||||
RUN pip install --upgrade pip && \
|
||||
pip install --no-cache-dir -r ./api/requirements.txt
|
||||
|
||||
# copy llama binary from llama_builder
|
||||
# Copy files
|
||||
COPY --from=llama_builder /tmp/llama.cpp/llama /usr/bin/llama
|
||||
|
||||
# copy built webserver from web_builder
|
||||
COPY ./web/package.json web/
|
||||
COPY ./web/package-lock.json web/
|
||||
# Install Node modules
|
||||
RUN cd web && npm install
|
||||
# Dev environment
|
||||
FROM base as dev
|
||||
ENV NODE_ENV='development'
|
||||
|
||||
COPY ./web /usr/src/app/web/
|
||||
# Install Node.js and npm packages
|
||||
COPY --from=node_base /usr/local /usr/local
|
||||
COPY ./web/package*.json ./
|
||||
RUN npm ci
|
||||
|
||||
#copy api folder
|
||||
# Copy the rest of the project files
|
||||
COPY web /usr/src/app/web
|
||||
COPY ./api /usr/src/app/api
|
||||
|
||||
COPY dev.sh /usr/src/app/dev.sh
|
||||
RUN chmod +x /usr/src/app/dev.sh
|
||||
CMD ./dev.sh
|
||||
|
||||
# Build frontend
|
||||
FROM node_base as frontend_builder
|
||||
|
||||
COPY ./web/package*.json ./
|
||||
RUN npm ci
|
||||
|
||||
COPY ./web /usr/src/app/web/
|
||||
WORKDIR /usr/src/app/web/
|
||||
RUN npm run build
|
||||
|
||||
# Runtime environment
|
||||
FROM base as release
|
||||
|
||||
ENV NODE_ENV='production'
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY --from=frontend_builder /usr/src/app/web/build /usr/src/app/api/static/
|
||||
COPY ./api /usr/src/app/api
|
||||
|
||||
# get the deploy script with the right permissions
|
||||
COPY deploy.sh /usr/src/app/deploy.sh
|
||||
RUN chmod +x /usr/src/app/deploy.sh
|
||||
|
||||
CMD /usr/src/app/deploy.sh
|
||||
CMD ./deploy.sh
|
||||
|
||||
16
README.md
16
README.md
@@ -14,21 +14,21 @@ A chat interface based on `llama.cpp` for running Alpaca models. Entirely self-h
|
||||
## Getting started
|
||||
|
||||
Setting up Serge is very easy. TLDR for running it with Alpaca 7B:
|
||||
|
||||
```
|
||||
git clone https://github.com/nsarrazin/serge.git
|
||||
cd serge
|
||||
|
||||
docker compose up -d
|
||||
docker compose up --build -d
|
||||
docker compose exec serge python3 /usr/src/app/api/utils/download.py tokenizer 7B
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
:warning: For cloning on windows, use `git clone https://github.com/nsarrazin/serge.git --config core.autocrlf=input`.
|
||||
:warning: For cloning on windows, use `git clone https://github.com/nsarrazin/serge.git --config core.autocrlf=input`.
|
||||
|
||||
Make sure you have docker desktop installed, WSL2 configured and enough free RAM to run models. (see below)
|
||||
|
||||
|
||||
#### Kubernetes
|
||||
|
||||
Setting up Serge on Kubernetes can be found in the wiki: https://github.com/nsarrazin/serge/wiki/Integrating-Serge-in-your-orchestration#kubernetes-example
|
||||
@@ -59,6 +59,16 @@ llama will just crash if you don't have enough available memory for your model.
|
||||
|
||||
Feel free to join the discord if you need help with the setup: https://discord.gg/62Hc6FEYQH
|
||||
|
||||
## Contributing
|
||||
|
||||
Serge is always open for contributions! If you catch a bug or have a feature idea, feel free to open an issue or a PR.
|
||||
|
||||
If you want to run Serge in development mode (with hot-module reloading for svelte & autoreload for FastAPI) you can do so like this:
|
||||
|
||||
```
|
||||
docker compose -f docker-compose.dev.yml up -d --build
|
||||
```
|
||||
|
||||
## What's next
|
||||
|
||||
- [x] Front-end to interface with the API
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
FROM gcc:10.2 as builder
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
RUN git clone https://github.com/ggerganov/llama.cpp.git --branch master-d5850c5
|
||||
|
||||
RUN cd llama.cpp && \
|
||||
make && \
|
||||
mv main llama
|
||||
|
||||
FROM ubuntu:latest
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
RUN apt update
|
||||
RUN apt-get install -y python3-pip
|
||||
RUN pip install --upgrade pip
|
||||
|
||||
COPY ./requirements.txt requirements.txt
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
COPY --from=builder /tmp/llama.cpp/llama /usr/bin/llama
|
||||
48
api/main.py
48
api/main.py
@@ -9,10 +9,12 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||
from beanie.odm.enums import SortDirection
|
||||
|
||||
from sse_starlette.sse import EventSourceResponse
|
||||
from utils.initiate_database import initiate_database
|
||||
from utils.initiate_database import initiate_database, Settings
|
||||
from utils.generate import generate, get_full_prompt_from_chat
|
||||
from utils.convert import convert_all
|
||||
from models import Question, Chat, ChatParameters
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from starlette.responses import FileResponse
|
||||
|
||||
|
||||
# Configure logging settings
|
||||
@@ -27,6 +29,8 @@ logging.basicConfig(
|
||||
# Define a logger for the current module
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
settings = Settings()
|
||||
|
||||
tags_metadata = [
|
||||
{
|
||||
"name": "misc.",
|
||||
@@ -46,6 +50,32 @@ app = FastAPI(
|
||||
title="Serge", version="0.0.1", description=description, tags_metadata=tags_metadata
|
||||
)
|
||||
|
||||
api_app = FastAPI(title="Serge API")
|
||||
app.mount('/api', api_app)
|
||||
|
||||
if settings.NODE_ENV == "production":
|
||||
@app.middleware("http")
|
||||
async def add_custom_header(request, call_next):
|
||||
response = await call_next(request)
|
||||
if response.status_code == 404:
|
||||
return FileResponse('static/200.html')
|
||||
return response
|
||||
|
||||
@app.exception_handler(404)
|
||||
def not_found(request, exc):
|
||||
return FileResponse('static/200.html')
|
||||
|
||||
async def homepage(request):
|
||||
return FileResponse('static/200.html')
|
||||
|
||||
app.route('/', homepage)
|
||||
app.mount('/', StaticFiles(directory='static'))
|
||||
|
||||
if settings.NODE_ENV == "development":
|
||||
start_app = api_app
|
||||
else:
|
||||
start_app = app
|
||||
|
||||
origins = [
|
||||
"http://localhost",
|
||||
"http://api:9124",
|
||||
@@ -90,7 +120,7 @@ async def convert_model_files():
|
||||
logger.info("models are ready")
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
@start_app.on_event("startup")
|
||||
async def start_database():
|
||||
logger.info("initializing database connection")
|
||||
await initiate_database()
|
||||
@@ -99,14 +129,14 @@ async def start_database():
|
||||
asyncio.create_task(convert_model_files())
|
||||
|
||||
|
||||
@app.get("/models", tags=["misc."])
|
||||
@api_app.get("/models", tags=["misc."])
|
||||
def list_of_installed_models(
|
||||
models: Annotated[list[str], Depends(dep_models_ready)]
|
||||
):
|
||||
return models
|
||||
|
||||
|
||||
@app.post("/chat", tags=["chats"])
|
||||
@api_app.post("/chat", tags=["chats"])
|
||||
async def create_new_chat(
|
||||
model: str = "ggml-alpaca-7B-q4_0.bin",
|
||||
temperature: float = 0.1,
|
||||
@@ -136,14 +166,14 @@ async def create_new_chat(
|
||||
return chat.id
|
||||
|
||||
|
||||
@app.get("/chat/{chat_id}", tags=["chats"])
|
||||
@api_app.get("/chat/{chat_id}", tags=["chats"])
|
||||
async def get_specific_chat(chat_id: str):
|
||||
chat = await Chat.get(chat_id)
|
||||
await chat.fetch_all_links()
|
||||
|
||||
return chat
|
||||
|
||||
@app.delete("/chat/{chat_id}", tags=["chats"])
|
||||
@api_app.delete("/chat/{chat_id}", tags=["chats"])
|
||||
async def delete_chat(chat_id: str):
|
||||
chat = await Chat.get(chat_id)
|
||||
deleted_chat = await chat.delete()
|
||||
@@ -175,7 +205,7 @@ def remove_matching_end(a, b):
|
||||
|
||||
return b
|
||||
|
||||
@app.get("/chat/{chat_id}/question", dependencies=[Depends(dep_models_ready)])
|
||||
@api_app.get("/chat/{chat_id}/question", dependencies=[Depends(dep_models_ready)])
|
||||
async def stream_ask_a_question(chat_id: str, prompt: str):
|
||||
|
||||
chat = await Chat.get(chat_id)
|
||||
@@ -216,7 +246,7 @@ async def stream_ask_a_question(chat_id: str, prompt: str):
|
||||
|
||||
return EventSourceResponse(event_generator())
|
||||
|
||||
@app.post("/chat/{chat_id}/question", dependencies=[Depends(dep_models_ready)])
|
||||
@api_app.post("/chat/{chat_id}/question", dependencies=[Depends(dep_models_ready)])
|
||||
async def ask_a_question(chat_id: str, prompt: str):
|
||||
chat = await Chat.get(chat_id)
|
||||
await chat.fetch_link(Chat.parameters)
|
||||
@@ -240,7 +270,7 @@ async def ask_a_question(chat_id: str, prompt: str):
|
||||
|
||||
return {"question" : prompt, "answer" : answer[len(full_prompt)+1:]}
|
||||
|
||||
@app.get("/chats", tags=["chats"])
|
||||
@api_app.get("/chats", tags=["chats"])
|
||||
async def get_all_chats():
|
||||
res = []
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ async def generate(
|
||||
if return_code != 0:
|
||||
error_output = await procLlama.stderr.read()
|
||||
logger.error(error_output.decode("utf-8"))
|
||||
raise ValueError(error_output.decode("utf-8"))
|
||||
raise ValueError(f"RETURN CODE {return_code}\n\n"+error_output.decode("utf-8"))
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ from models import Question, Chat, ChatParameters
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
NODE_ENV: str = "development"
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
||||
@@ -2,14 +2,11 @@
|
||||
|
||||
mongod &
|
||||
|
||||
# Start the web server
|
||||
cd web && npm run dev -- --host 0.0.0.0 --port 8008 &
|
||||
|
||||
# Start the API
|
||||
cd api && uvicorn main:app --host 0.0.0.0 --port 9124 --root-path /api/ &
|
||||
cd api && uvicorn main:app --host 0.0.0.0 --port 8008 &
|
||||
|
||||
# Wait for any process to exit
|
||||
wait -n
|
||||
|
||||
# Exit with status of process that exited first
|
||||
exit $?
|
||||
exit $?
|
||||
14
dev.sh
Normal file
14
dev.sh
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
mongod &
|
||||
|
||||
# Start the web server
|
||||
cd web && npm run dev -- --host 0.0.0.0 --port 8008 &
|
||||
|
||||
# Start the API
|
||||
cd api && uvicorn main:api_app --reload --host 0.0.0.0 --port 9124 --root-path /api/ &
|
||||
|
||||
# Wait for any process to exit
|
||||
wait -n
|
||||
# Exit with status of process that exited first
|
||||
exit $?
|
||||
20
docker-compose.dev.yml
Normal file
20
docker-compose.dev.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
version: "3.9"
|
||||
services:
|
||||
serge:
|
||||
restart: on-failure
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
target: dev
|
||||
volumes:
|
||||
- ./web:/usr/src/app/web/
|
||||
- ./api:/usr/src/app/api/
|
||||
- datadb:/data/db
|
||||
- weights:/usr/src/app/weights/
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "8008:8008"
|
||||
|
||||
volumes:
|
||||
datadb:
|
||||
weights:
|
||||
@@ -5,6 +5,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
target: release
|
||||
volumes:
|
||||
- datadb:/data/db
|
||||
- weights:/usr/src/app/weights/
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
FROM node:19.8.1
|
||||
|
||||
# Set the Node environment to development to ensure all packages are installed
|
||||
ENV NODE_ENV development
|
||||
|
||||
# Change our current working directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Copy over `package.json` and lock files to optimize the build process
|
||||
COPY package.json .
|
||||
COPY package-lock.json .
|
||||
# Install Node modules
|
||||
RUN npm install
|
||||
|
||||
# Copy over rest of the project files
|
||||
COPY . .
|
||||
|
||||
# Expose port 24678 for Vite's HMR
|
||||
EXPOSE 24678
|
||||
|
||||
236
web/package-lock.json
generated
236
web/package-lock.json
generated
@@ -15,6 +15,8 @@
|
||||
"devDependencies": {
|
||||
"@feltjs/eslint-config": "^0.2.1",
|
||||
"@sveltejs/adapter-auto": "^2.0.0",
|
||||
"@sveltejs/adapter-node": "^1.2.3",
|
||||
"@sveltejs/adapter-static": "^2.0.1",
|
||||
"@sveltejs/kit": "^1.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
||||
"@typescript-eslint/parser": "^5.56.0",
|
||||
@@ -569,6 +571,150 @@
|
||||
"integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs": {
|
||||
"version": "24.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.1.tgz",
|
||||
"integrity": "sha512-15LsiWRZk4eOGqvrJyu3z3DaBu5BhXIMeWnijSRvd8irrrg9SHpQ1pH+BUK4H6Z9wL9yOxZJMTLU+Au86XHxow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1",
|
||||
"commondir": "^1.0.1",
|
||||
"estree-walker": "^2.0.2",
|
||||
"glob": "^8.0.3",
|
||||
"is-reference": "1.2.1",
|
||||
"magic-string": "^0.27.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^2.68.0||^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs/node_modules/glob": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
||||
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^5.0.1",
|
||||
"once": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs/node_modules/magic-string": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz",
|
||||
"integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.13"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs/node_modules/minimatch": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
|
||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-json": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.0.0.tgz",
|
||||
"integrity": "sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^1.20.0||^2.0.0||^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-node-resolve": {
|
||||
"version": "15.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.1.tgz",
|
||||
"integrity": "sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1",
|
||||
"@types/resolve": "1.20.2",
|
||||
"deepmerge": "^4.2.2",
|
||||
"is-builtin-module": "^3.2.0",
|
||||
"is-module": "^1.0.0",
|
||||
"resolve": "^1.22.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^2.78.0||^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
|
||||
"integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^1.20.0||^2.0.0||^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/adapter-auto": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-2.0.0.tgz",
|
||||
@@ -581,6 +727,30 @@
|
||||
"@sveltejs/kit": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/adapter-node": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.2.3.tgz",
|
||||
"integrity": "sha512-Fv6NyVpVWYA63KRaV6dDjcU8ytcWFiUr0siJOoHl+oWy5WHNEuRiJOUdiZzYbZo8MmvFaCoxHkTgPrVQhpqaRA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/plugin-commonjs": "^24.0.0",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"rollup": "^3.7.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@sveltejs/kit": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/adapter-static": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-2.0.1.tgz",
|
||||
"integrity": "sha512-o5/q3YwD/ErxYCFlK1v3ydvldyNKk1lh3oeyxn4mhz+Pkbx/uuxhzmbOpytTlp5aVqNHDVsb04xadUzOFCDDzw==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@sveltejs/kit": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/kit": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.12.0.tgz",
|
||||
@@ -665,6 +835,12 @@
|
||||
"integrity": "sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
|
||||
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||
@@ -677,6 +853,12 @@
|
||||
"integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
|
||||
@@ -1084,6 +1266,18 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/builtin-modules": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
|
||||
"integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/busboy": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||
@@ -1207,6 +1401,12 @@
|
||||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/commondir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@@ -1657,6 +1857,12 @@
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/esutils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
@@ -2007,6 +2213,21 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-builtin-module": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
|
||||
"integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"builtin-modules": "^3.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
|
||||
@@ -2037,6 +2258,12 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
@@ -2054,6 +2281,15 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-reference": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
|
||||
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
"devDependencies": {
|
||||
"@feltjs/eslint-config": "^0.2.1",
|
||||
"@sveltejs/adapter-auto": "^2.0.0",
|
||||
"@sveltejs/adapter-node": "^1.2.3",
|
||||
"@sveltejs/adapter-static": "^2.0.1",
|
||||
"@sveltejs/kit": "^1.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
||||
"@typescript-eslint/parser": "^5.56.0",
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
$: deleteConfirm = false;
|
||||
|
||||
async function deleteChat(chatID: string) {
|
||||
var response = await fetch("/api/chat/" + chatID, { method: "DELETE" });
|
||||
const response = await fetch("/api/chat/" + chatID, { method: "DELETE" });
|
||||
if (response.status == 200) {
|
||||
toggleDeleteConfirm();
|
||||
await goto("/");
|
||||
await invalidate("/api/chats");
|
||||
} else {
|
||||
alert("Error " + response.status + ": " + response.statusText);
|
||||
console.error("Error " + response.status + ": " + response.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +24,9 @@
|
||||
|
||||
function timeSince(datestring: string) {
|
||||
const date = new Date(datestring);
|
||||
var seconds = Math.floor((Date.now() - date.getTime()) / 1000);
|
||||
const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
|
||||
|
||||
var interval = seconds / 31536000;
|
||||
let interval = seconds / 31536000;
|
||||
|
||||
if (interval > 1) {
|
||||
return Math.floor(interval) + " years";
|
||||
@@ -74,7 +75,7 @@
|
||||
<div>
|
||||
<span class="font-semibold">{chat.model}</span>
|
||||
<span class="ml-3">{timeSince(chat.created) + " ago"}</span>
|
||||
{#if $page.params.id == chat.id}
|
||||
{#if $page.params.id === chat.id}
|
||||
{#if deleteConfirm}
|
||||
<button
|
||||
name="confirm-delete"
|
||||
|
||||
@@ -11,6 +11,6 @@ export const load: LayoutLoad = async ({ fetch }) => {
|
||||
const r = await fetch("/api/chats");
|
||||
const chats = (await r.json()) as t[];
|
||||
return {
|
||||
chats: chats,
|
||||
chats,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { redirect } from "@sveltejs/kit";
|
||||
import type { Actions } from "./$types";
|
||||
|
||||
export const actions = {
|
||||
default: async ({ fetch, request }) => {
|
||||
const formData = await request.formData();
|
||||
|
||||
const convertedFormEntries = Array.from(formData, ([key, value]) => [
|
||||
key,
|
||||
typeof value === "string" ? value : value.name,
|
||||
]);
|
||||
const searchParams = new URLSearchParams(convertedFormEntries);
|
||||
|
||||
const r = await fetch("/api/chat?" + searchParams.toString(), {
|
||||
method: "POST",
|
||||
});
|
||||
if (r.ok) {
|
||||
const data = await r.json();
|
||||
throw redirect(303, "/chat/" + data);
|
||||
} else {
|
||||
console.log(r.statusText);
|
||||
}
|
||||
},
|
||||
} satisfies Actions;
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from "./$types";
|
||||
|
||||
import { goto, invalidate } from "$app/navigation";
|
||||
export let data: PageData;
|
||||
|
||||
const modelAvailable = data.models.length > 0;
|
||||
@@ -18,14 +18,39 @@
|
||||
|
||||
let n_threads = 4;
|
||||
let ctx_length = 512;
|
||||
|
||||
async function onCreateChat(event: Event) {
|
||||
const form = document.getElementById("form-create-chat") as HTMLFormElement;
|
||||
|
||||
const formData = new FormData(form);
|
||||
|
||||
const convertedFormEntries = Array.from(formData, ([key, value]) => [
|
||||
key,
|
||||
typeof value === "string" ? value : value.name,
|
||||
]);
|
||||
const searchParams = new URLSearchParams(convertedFormEntries);
|
||||
|
||||
const r = await fetch("/api/chat?" + searchParams.toString(), {
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
console.log(r);
|
||||
if (r.ok) {
|
||||
const data = await r.json();
|
||||
await goto("/chat/" + data);
|
||||
await invalidate("/api/chats");
|
||||
} else {
|
||||
console.log(r.statusText);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<h1 class="text-3xl font-bold text-center pt-5">Say Hi to Serge!</h1>
|
||||
<h1 class="text-xl text-center pt-2 pb-5">
|
||||
<h1 class="text-xl font-light text-center pt-2 pb-5">
|
||||
An easy way to chat with Alpaca & other LLaMa based models.
|
||||
</h1>
|
||||
|
||||
<form method="POST" class="p-5">
|
||||
<form on:submit|preventDefault={onCreateChat} id="form-create-chat" class="p-5">
|
||||
<div class="w-full pb-20">
|
||||
<div class="mx-auto w-fit pt-5">
|
||||
<button class=" mx-auto btn btn-primary ml-5" disabled={!modelAvailable}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import adapter from '@sveltejs/adapter-auto';
|
||||
import adapter from '@sveltejs/adapter-static';
|
||||
import { vitePreprocess } from '@sveltejs/kit/vite';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
@@ -11,7 +11,10 @@ const config = {
|
||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
||||
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||
adapter: adapter(),
|
||||
adapter: adapter({
|
||||
fallback: '200.html' // may differ from host to host
|
||||
}
|
||||
),
|
||||
csrf: {
|
||||
checkOrigin: false,
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ import { defineConfig } from "vite";
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()],
|
||||
server: {
|
||||
fs: {
|
||||
// Allow serving files from one level up to the project root
|
||||
allow: [".."],
|
||||
},
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: "http://serge:9124/",
|
||||
|
||||
Reference in New Issue
Block a user