From b5dc1669e36b158cb931f433f6290e4685338453 Mon Sep 17 00:00:00 2001 From: "P. Taylor Goetz" Date: Sat, 27 Apr 2024 19:17:17 -0400 Subject: [PATCH] Etablish versioned API path --- API.md | 22 +++++++++++----------- backend/app/api/__init__.py | 6 +++--- backend/app/server.py | 4 ++-- frontend/src/api/assistants.ts | 2 +- frontend/src/api/threads.ts | 2 +- frontend/src/hooks/useChatList.ts | 6 +++--- frontend/src/hooks/useChatMessages.ts | 2 +- frontend/src/hooks/useConfigList.ts | 6 +++--- frontend/src/hooks/useMessageEditing.ts | 2 +- frontend/src/hooks/useSchemas.ts | 2 +- frontend/src/hooks/useStreamState.tsx | 2 +- frontend/vite.config.ts | 2 +- 12 files changed, 29 insertions(+), 29 deletions(-) diff --git a/API.md b/API.md index 6b2a3745..17320cae 100644 --- a/API.md +++ b/API.md @@ -3,7 +3,7 @@ This documentation covers how to get started with the API that backs OpenGPTs. This allows you to easily integrate it with a different frontend of your choice. -For full API documentation, see [localhost:8100/docs](localhost:8100/docs) after deployment. +For full API documentation, see [localhost:8100/api/v1/docs](localhost:8100/api/v1/docs) after deployment. If you want to see the API docs before deployment, check out the [hosted docs here](https://opengpts-example-vz4y4ooboq-uc.a.run.app/docs). @@ -17,7 +17,7 @@ This should look something like: ```python import requests -requests.post('http://127.0.0.1:8100/assistants', json={ +requests.post('http://127.0.0.1:8100/api/v1/assistants', json={ "name": "bar", "config": {"configurable": {}}, "public": True @@ -61,7 +61,7 @@ Notably different from OpenAI's assistant API, we require starting the thread wi ```python import requests -requests.post('http://127.0.0.1:8100/threads', cookies= {"opengpts_user_id": "foo"}, json={ +requests.post('http://127.0.0.1:8100/api/v1/threads', cookies= {"opengpts_user_id": "foo"}, json={ "name": "hi", "assistant_id": "9c7d7e6e-654b-4eaa-b160-f19f922fc63b" }).content @@ -82,7 +82,7 @@ We can check the thread, and see that it is currently empty: ```python import requests requests.get( - 'http://127.0.0.1:8100/threads/231dc7f3-33ee-4040-98fe-27f6e2aa8b2b/state', + 'http://127.0.0.1:8100/api/v1/threads/231dc7f3-33ee-4040-98fe-27f6e2aa8b2b/state', cookies= {"opengpts_user_id": "foo"} ).content ``` @@ -99,7 +99,7 @@ Let's add a message to the thread! ```python import requests requests.post( - 'http://127.0.0.1:8100/threads/231dc7f3-33ee-4040-98fe-27f6e2aa8b2b/state', + 'http://127.0.0.1:8100/api/v1/threads/231dc7f3-33ee-4040-98fe-27f6e2aa8b2b/state', cookies= {"opengpts_user_id": "foo"}, json={ "values": [{ "content": "hi! my name is bob", @@ -125,7 +125,7 @@ If we now run the command to see the thread, we can see that there is now a mess ```python import requests requests.get( - 'http://127.0.0.1:8100/threads/231dc7f3-33ee-4040-98fe-27f6e2aa8b2b/state', + 'http://127.0.0.1:8100/api/v1/threads/231dc7f3-33ee-4040-98fe-27f6e2aa8b2b/state', cookies= {"opengpts_user_id": "foo"} ).content ``` @@ -143,7 +143,7 @@ We can now run the assistant on that thread. ```python import requests -requests.post('http://127.0.0.1:8100/runs', cookies= {"opengpts_user_id": "foo"}, json={ +requests.post('http://127.0.0.1:8100/api/v1/runs', cookies= {"opengpts_user_id": "foo"}, json={ "assistant_id": "9c7d7e6e-654b-4eaa-b160-f19f922fc63b", "thread_id": "231dc7f3-33ee-4040-98fe-27f6e2aa8b2b", "input": { @@ -157,7 +157,7 @@ If we now check the thread, we can see (after a bit) that there is a message fro ```python import requests -requests.get('http://127.0.0.1:8100/threads/231dc7f3-33ee-4040-98fe-27f6e2aa8b2b/state', cookies= {"opengpts_user_id": "foo"}).content +requests.get('http://127.0.0.1:8100/api/v1/threads/231dc7f3-33ee-4040-98fe-27f6e2aa8b2b/state', cookies= {"opengpts_user_id": "foo"}).content ``` ```shell b'{"values":[{"content":"hi! my name is bob","additional_kwargs":{},"type":"human","example":false},{"content":"Hello, Bob! How can I assist you today?","additional_kwargs":{"agent":{"return_values":{"output":"Hello, Bob! How can I assist you today?"},"log":"Hello, Bob! How can I assist you today?","type":"AgentFinish"}},"type":"ai","example":false}],"next":[]}' @@ -174,7 +174,7 @@ Continuing the example above, we can run: ```python import requests -requests.post('http://127.0.0.1:8100/runs', cookies= {"opengpts_user_id": "foo"}, json={ +requests.post('http://127.0.0.1:8100/api/v1/runs', cookies= {"opengpts_user_id": "foo"}, json={ "assistant_id": "9c7d7e6e-654b-4eaa-b160-f19f922fc63b", "thread_id": "231dc7f3-33ee-4040-98fe-27f6e2aa8b2b", "input": { @@ -190,7 +190,7 @@ Then, if we call the threads endpoint after a bit we can see the human message - ```python import requests -requests.get('http://127.0.0.1:8100/threads/231dc7f3-33ee-4040-98fe-27f6e2aa8b2b/state', cookies= {"opengpts_user_id": "foo"}).content +requests.get('http://127.0.0.1:8100/api/v1/threads/231dc7f3-33ee-4040-98fe-27f6e2aa8b2b/state', cookies= {"opengpts_user_id": "foo"}).content ``` ```shell @@ -210,7 +210,7 @@ Below is an example of streaming back tokens for a response. import requests import json response = requests.post( - 'http://127.0.0.1:8100/runs/stream', + 'http://127.0.0.1:8100/api/v1/runs/stream', cookies= {"opengpts_user_id": "foo"}, json={ "assistant_id": "9c7d7e6e-654b-4eaa-b160-f19f922fc63b", "thread_id": "231dc7f3-33ee-4040-98fe-27f6e2aa8b2b", diff --git a/backend/app/api/__init__.py b/backend/app/api/__init__.py index 47d463e5..db2db034 100644 --- a/backend/app/api/__init__.py +++ b/backend/app/api/__init__.py @@ -14,16 +14,16 @@ async def ok(): router.include_router( assistants_router, - prefix="/assistants", + prefix="/api/v1/assistants", tags=["assistants"], ) router.include_router( runs_router, - prefix="/runs", + prefix="/api/v1/runs", tags=["runs"], ) router.include_router( threads_router, - prefix="/threads", + prefix="/api/v1/threads", tags=["threads"], ) diff --git a/backend/app/server.py b/backend/app/server.py index a8978da4..678b9339 100644 --- a/backend/app/server.py +++ b/backend/app/server.py @@ -25,7 +25,7 @@ app.include_router(api_router) -@app.post("/ingest", description="Upload files to the given assistant.") +@app.post("/api/v1/ingest", description="Upload files to the given assistant.") async def ingest_files( files: list[UploadFile], user: AuthedUser, config: str = Form(...) ) -> None: @@ -47,7 +47,7 @@ async def ingest_files( return ingest_runnable.batch([file.file for file in files], config) -@app.get("/health") +@app.get("/api/v1/health") async def health() -> dict: return {"status": "ok"} diff --git a/frontend/src/api/assistants.ts b/frontend/src/api/assistants.ts index 74402629..d83d3ac1 100644 --- a/frontend/src/api/assistants.ts +++ b/frontend/src/api/assistants.ts @@ -4,7 +4,7 @@ export async function getAssistant( assistantId: string, ): Promise { try { - const response = await fetch(`/assistants/${assistantId}`); + const response = await fetch(`/api/v1/assistants/${assistantId}`); if (!response.ok) { return null; } diff --git a/frontend/src/api/threads.ts b/frontend/src/api/threads.ts index ffa1b879..626f21d6 100644 --- a/frontend/src/api/threads.ts +++ b/frontend/src/api/threads.ts @@ -2,7 +2,7 @@ import { Chat } from "../types"; export async function getThread(threadId: string): Promise { try { - const response = await fetch(`/threads/${threadId}`); + const response = await fetch(`/api/v1/threads/${threadId}`); if (!response.ok) { return null; } diff --git a/frontend/src/hooks/useChatList.ts b/frontend/src/hooks/useChatList.ts index b5a51bb6..e0e85f06 100644 --- a/frontend/src/hooks/useChatList.ts +++ b/frontend/src/hooks/useChatList.ts @@ -32,7 +32,7 @@ export function useChatList(): ChatListProps { useEffect(() => { async function fetchChats() { - const chats = await fetch("/threads/", { + const chats = await fetch("/api/v1/threads/", { headers: { Accept: "application/json", }, @@ -44,7 +44,7 @@ export function useChatList(): ChatListProps { }, []); const createChat = useCallback(async (name: string, assistant_id: string) => { - const response = await fetch(`/threads`, { + const response = await fetch(`/api/v1/threads`, { method: "POST", body: JSON.stringify({ assistant_id, name }), headers: { @@ -59,7 +59,7 @@ export function useChatList(): ChatListProps { const deleteChat = useCallback( async (thread_id: string) => { - await fetch(`/threads/${thread_id}`, { + await fetch(`/api/v1/threads/${thread_id}`, { method: "DELETE", headers: { Accept: "application/json", diff --git a/frontend/src/hooks/useChatMessages.ts b/frontend/src/hooks/useChatMessages.ts index b830cfa7..89279f83 100644 --- a/frontend/src/hooks/useChatMessages.ts +++ b/frontend/src/hooks/useChatMessages.ts @@ -3,7 +3,7 @@ import { Message } from "../types"; import { StreamState, mergeMessagesById } from "./useStreamState"; async function getState(threadId: string) { - const { values, next } = await fetch(`/threads/${threadId}/state`, { + const { values, next } = await fetch(`/api/v1/threads/${threadId}/state`, { headers: { Accept: "application/json", }, diff --git a/frontend/src/hooks/useConfigList.ts b/frontend/src/hooks/useConfigList.ts index bd50ddf9..e5b21dcc 100644 --- a/frontend/src/hooks/useConfigList.ts +++ b/frontend/src/hooks/useConfigList.ts @@ -51,7 +51,7 @@ export function useConfigList(): ConfigListProps { useEffect(() => { async function fetchConfigs() { - const myConfigs = await fetch("/assistants/", { + const myConfigs = await fetch("/api/v1/assistants/", { headers: { Accept: "application/json", }, @@ -73,7 +73,7 @@ export function useConfigList(): ConfigListProps { assistantId?: string, ): Promise => { const confResponse = await fetch( - assistantId ? `/assistants/${assistantId}` : "/assistants", + assistantId ? `/api/v1/assistants/${assistantId}` : "/api/v1/assistants", { method: assistantId ? "PUT" : "POST", body: JSON.stringify({ name, config, public: isPublic }), @@ -94,7 +94,7 @@ export function useConfigList(): ConfigListProps { "config", JSON.stringify({ configurable: { assistant_id } }), ); - await fetch(`/ingest`, { + await fetch(`/api/v1/ingest`, { method: "POST", body: formData, }); diff --git a/frontend/src/hooks/useMessageEditing.ts b/frontend/src/hooks/useMessageEditing.ts index 91ba3ba9..ad31ab94 100644 --- a/frontend/src/hooks/useMessageEditing.ts +++ b/frontend/src/hooks/useMessageEditing.ts @@ -13,7 +13,7 @@ export function useMessageEditing( }, []); const commitEdits = useCallback(async () => { if (!threadId) return; - fetch(`/threads/${threadId}/state`, { + fetch(`/api/v1/threads/${threadId}/state`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ values: Object.values(editing) }), diff --git a/frontend/src/hooks/useSchemas.ts b/frontend/src/hooks/useSchemas.ts index a6d54ba8..29e0339f 100644 --- a/frontend/src/hooks/useSchemas.ts +++ b/frontend/src/hooks/useSchemas.ts @@ -36,7 +36,7 @@ export function useSchemas() { useEffect(() => { async function save() { - const configSchema = await fetch("/runs/config_schema") + const configSchema = await fetch("/api/v1/runs/config_schema") .then((r) => r.json()) .then(simplifySchema); setSchemas({ diff --git a/frontend/src/hooks/useStreamState.tsx b/frontend/src/hooks/useStreamState.tsx index 36596284..3f9c871d 100644 --- a/frontend/src/hooks/useStreamState.tsx +++ b/frontend/src/hooks/useStreamState.tsx @@ -33,7 +33,7 @@ export function useStreamState(): StreamStateProps { setController(controller); setCurrent({ status: "inflight", messages: input || [] }); - await fetchEventSource("/runs/stream", { + await fetchEventSource("/api/v1/runs/stream", { signal: controller.signal, method: "POST", headers: { "Content-Type": "application/json" }, diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index a8a086ee..7c4da034 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -9,7 +9,7 @@ export default defineConfig({ usePolling: true }, proxy: { - "^/(assistants|threads|ingest|runs)": { + "^/api/v1/(assistants|threads|ingest|runs)": { target: process.env.VITE_BACKEND_URL || "http://127.0.0.1:8100", changeOrigin: true, rewrite: (path) => path.replace("/____LANGSERVE_BASE_URL", ""),