refactor: switch to /v1/events endpoint (#42)
* refactor: Add EventType enum for validation * refactor: use /v1/events in monaco components * refactor: use /v1/events in vscode client * refactor: remove unused api endpoint * refactor: improve api endpoint type checkadd-more-languages
parent
51e3b54016
commit
6da7c17f67
|
|
@ -110,9 +110,11 @@ export class TabbyClient extends EventEmitter {
|
||||||
this.ping();
|
this.ping();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(
|
const response = await axios.post(`${this.tabbyServerUrl}/v1/events`, {
|
||||||
`${this.tabbyServerUrl}/v1/completions/${event.id}/choices/${event.index}/${event.type}`
|
type: event.type,
|
||||||
);
|
completion_id: event.id,
|
||||||
|
choice_index: event.index
|
||||||
|
});
|
||||||
assert(response.status == 200);
|
assert(response.status == 200);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.ping();
|
this.ping();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"files": {
|
"files": {
|
||||||
"main.js": "./static/js/main.c14dfe27.js",
|
"main.js": "./static/js/main.ab7e9a50.js",
|
||||||
"index.html": "./index.html"
|
"index.html": "./index.html"
|
||||||
},
|
},
|
||||||
"entrypoints": [
|
"entrypoints": [
|
||||||
"static/js/main.c14dfe27.js"
|
"static/js/main.ab7e9a50.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
<!doctype html><html lang="en"><head><title>Streamlit Component</title><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Streamlit Component"/><link rel="stylesheet" href="bootstrap.min.css"/><script defer="defer" src="./static/js/main.c14dfe27.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
<!doctype html><html lang="en"><head><title>Streamlit Component</title><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Streamlit Component"/><link rel="stylesheet" href="bootstrap.min.css"/><script defer="defer" src="./static/js/main.ab7e9a50.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,7 @@
|
||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
import { useRenderData } from "streamlit-component-lib-react-hooks"
|
import { useRenderData } from "streamlit-component-lib-react-hooks"
|
||||||
|
|
||||||
import React, { useRef, useEffect} from "react"
|
import React, { useRef, useEffect } from "react"
|
||||||
import Editor, { useMonaco } from "@monaco-editor/react"
|
import Editor, { useMonaco } from "@monaco-editor/react"
|
||||||
|
|
||||||
let TabbyServerURL = "http://localhost:5000"
|
let TabbyServerURL = "http://localhost:5000"
|
||||||
|
|
@ -162,6 +162,10 @@ class CompletionProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function logAction(id, index, event) {
|
function logAction(completion_id, choice_index, type) {
|
||||||
axios.post(`${TabbyServerURL}/v1/completions/${id}/choices/${index}/${event}`)
|
axios.post(`${TabbyServerURL}/v1/events`, {
|
||||||
|
type,
|
||||||
|
completion_id,
|
||||||
|
choice_index,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,15 @@ from fastapi import FastAPI, Response
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
from . import events
|
from . import events as events_lib
|
||||||
from .backend import PythonModelService, TritonService
|
from .backend import PythonModelService, TritonService
|
||||||
from .models import CompletionRequest, CompletionResponse
|
from .models import (
|
||||||
|
ChoiceEvent,
|
||||||
|
CompletionEvent,
|
||||||
|
CompletionRequest,
|
||||||
|
CompletionResponse,
|
||||||
|
EventTypeMapping,
|
||||||
|
)
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title="TabbyServer",
|
title="TabbyServer",
|
||||||
|
|
@ -37,23 +43,21 @@ else:
|
||||||
|
|
||||||
LOGS_DIR = os.environ.get("LOGS_DIR", None)
|
LOGS_DIR = os.environ.get("LOGS_DIR", None)
|
||||||
if LOGS_DIR is not None:
|
if LOGS_DIR is not None:
|
||||||
events.setup_logging(os.path.join(LOGS_DIR, "tabby-server"))
|
events_lib.setup_logging(os.path.join(LOGS_DIR, "tabby-server"))
|
||||||
|
|
||||||
|
|
||||||
@app.post("/v1/completions")
|
@app.post("/v1/completions")
|
||||||
async def completions(request: CompletionRequest) -> CompletionResponse:
|
async def completions(request: CompletionRequest) -> CompletionResponse:
|
||||||
response = model_backend(request)
|
response = model_backend(request)
|
||||||
events.log_completions(request, response)
|
events_lib.log_completion(request, response)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@app.post("/v1/completions/{id}/choices/{index}/view")
|
@app.post("/v1/events")
|
||||||
async def view(id: str, index: int) -> JSONResponse:
|
async def events(e: ChoiceEvent | CompletionEvent) -> JSONResponse:
|
||||||
events.log_view(id, index)
|
if isinstance(e, EventTypeMapping[e.type]):
|
||||||
return JSONResponse(content="ok")
|
events_lib.log_event(e)
|
||||||
|
return JSONResponse(content="ok")
|
||||||
|
else:
|
||||||
@app.post("/v1/completions/{id}/choices/{index}/select")
|
print(type(e))
|
||||||
async def select(id: str, index: int) -> JSONResponse:
|
return JSONResponse(content="invalid event", status_code=422)
|
||||||
events.log_select(id, index)
|
|
||||||
return JSONResponse(content="ok")
|
|
||||||
|
|
|
||||||
|
|
@ -27,18 +27,12 @@ def setup_logging(logdir):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def log_completions(
|
def log_completion(
|
||||||
request: models.CompletionRequest, response: models.CompletionResponse
|
request: models.CompletionRequest, response: models.CompletionResponse
|
||||||
) -> None:
|
) -> None:
|
||||||
event = models.CompletionEvent.build(request, response)
|
event = models.CompletionEvent.build(request, response)
|
||||||
logger.info(event.json())
|
logger.info(event.json())
|
||||||
|
|
||||||
|
|
||||||
def log_view(id: str, index: int) -> None:
|
def log_event(event: models.Event):
|
||||||
event = models.ChoiceEvent.build_view(id, index)
|
|
||||||
logger.info(event.json())
|
|
||||||
|
|
||||||
|
|
||||||
def log_select(id: str, index: int) -> None:
|
|
||||||
event = models.ChoiceEvent.build_select(id, index)
|
|
||||||
logger.info(event.json())
|
logger.info(event.json())
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
from enum import Enum
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
@ -21,8 +22,14 @@ class CompletionResponse(BaseModel):
|
||||||
choices: List[Choice]
|
choices: List[Choice]
|
||||||
|
|
||||||
|
|
||||||
|
class EventType(str, Enum):
|
||||||
|
COMPLETION = "completion"
|
||||||
|
VIEW = "view"
|
||||||
|
SELECT = "select"
|
||||||
|
|
||||||
|
|
||||||
class Event(BaseModel):
|
class Event(BaseModel):
|
||||||
type: str
|
type: EventType
|
||||||
|
|
||||||
|
|
||||||
class CompletionEvent(Event):
|
class CompletionEvent(Event):
|
||||||
|
|
@ -34,7 +41,7 @@ class CompletionEvent(Event):
|
||||||
@classmethod
|
@classmethod
|
||||||
def build(cls, request: CompletionRequest, response: CompletionResponse):
|
def build(cls, request: CompletionRequest, response: CompletionResponse):
|
||||||
return cls(
|
return cls(
|
||||||
type="completion",
|
type=EventType.COMPLETION,
|
||||||
id=response.id,
|
id=response.id,
|
||||||
prompt=request.prompt,
|
prompt=request.prompt,
|
||||||
created=response.created,
|
created=response.created,
|
||||||
|
|
@ -46,10 +53,9 @@ class ChoiceEvent(Event):
|
||||||
completion_id: str
|
completion_id: str
|
||||||
choice_index: int
|
choice_index: int
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def build_view(cls, id, index):
|
|
||||||
return cls(type="view", completion_id=id, choice_index=index)
|
|
||||||
|
|
||||||
@classmethod
|
EventTypeMapping = {
|
||||||
def build_select(cls, id, index):
|
EventType.COMPLETION: CompletionEvent,
|
||||||
return cls(type="select", completion_id=id, choice_index=index)
|
EventType.VIEW: ChoiceEvent,
|
||||||
|
EventType.SELECT: ChoiceEvent,
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue