1
1
import uvicorn
2
- import asyncio
3
- from contextlib import asynccontextmanager
4
- from scalar_fastapi import get_scalar_api_reference
5
2
6
- from fastapi import FastAPI
7
- from fastapi .routing import APIRoute
8
- from fastapi .responses import JSONResponse
9
- from fastapi .exceptions import RequestValidationError
10
- from fastapi .middleware .cors import CORSMiddleware
11
-
12
- from cat .log import log
13
3
from cat .env import get_env , fix_legacy_env_variables
14
- from cat .routes import (
15
- base ,
16
- auth ,
17
- users ,
18
- settings ,
19
- llm ,
20
- embedder ,
21
- auth_handler ,
22
- plugins ,
23
- upload ,
24
- websocket ,
25
- )
26
- from cat .routes .memory .memory_router import memory_router
27
- from cat .routes .static import admin , static
28
- from cat .routes .openapi import get_openapi_configuration_function
29
- from cat .looking_glass .cheshire_cat import CheshireCat
30
-
31
-
32
- # TODO: take away in v2
33
- fix_legacy_env_variables ()
34
-
35
-
36
- @asynccontextmanager
37
- async def lifespan (app : FastAPI ):
38
- # ^._.^
39
- #
40
- # loads Cat and plugins
41
- # Every endpoint can access the cat instance via request.app.state.ccat
42
- # - Not using midlleware because I can't make it work with both http and websocket;
43
- # - Not using Depends because it only supports callables (not instances)
44
- # - Starlette allows this: https://www.starlette.io/applications/#storing-state-on-the-app-instance
45
- app .state .ccat = CheshireCat ()
46
-
47
- # Dict of pseudo-sessions (key is the user_id)
48
- app .state .strays = {}
49
-
50
- # set a reference to asyncio event loop
51
- app .state .event_loop = asyncio .get_running_loop ()
52
-
53
- # startup message with admin, public and swagger addresses
54
- log .welcome ()
55
-
56
- yield
57
-
58
-
59
- def custom_generate_unique_id (route : APIRoute ):
60
- return f"{ route .name } "
61
-
62
-
63
- # REST API
64
- cheshire_cat_api = FastAPI (
65
- lifespan = lifespan , generate_unique_id_function = custom_generate_unique_id ,
66
- docs_url = None , redoc_url = None , title = "Cheshire-Cat API" ,
67
- license_info = {"name" : "GPL-3" , "url" : "https://www.gnu.org/licenses/gpl-3.0.en.html" },
68
- )
69
-
70
- # Configures the CORS middleware for the FastAPI app
71
- cors_allowed_origins_str = get_env ("CCAT_CORS_ALLOWED_ORIGINS" )
72
- origins = cors_allowed_origins_str .split ("," ) if cors_allowed_origins_str else ["*" ]
73
- cheshire_cat_api .add_middleware (
74
- CORSMiddleware ,
75
- allow_origins = origins ,
76
- allow_credentials = True ,
77
- allow_methods = ["*" ],
78
- allow_headers = ["*" ],
79
- )
80
-
81
- # Add routers to the middleware stack.
82
- cheshire_cat_api .include_router (base .router , tags = ["Home" ])
83
- cheshire_cat_api .include_router (auth .router , tags = ["User Auth" ], prefix = "/auth" )
84
- cheshire_cat_api .include_router (users .router , tags = ["Users" ], prefix = "/users" )
85
- cheshire_cat_api .include_router (settings .router , tags = ["Settings" ], prefix = "/settings" )
86
- cheshire_cat_api .include_router (
87
- llm .router , tags = ["Large Language Model" ], prefix = "/llm"
88
- )
89
- cheshire_cat_api .include_router (embedder .router , tags = ["Embedder" ], prefix = "/embedder" )
90
- cheshire_cat_api .include_router (plugins .router , tags = ["Plugins" ], prefix = "/plugins" )
91
- cheshire_cat_api .include_router (memory_router , prefix = "/memory" )
92
- cheshire_cat_api .include_router (
93
- upload .router , tags = ["Rabbit Hole" ], prefix = "/rabbithole"
94
- )
95
- cheshire_cat_api .include_router (
96
- auth_handler .router , tags = ["AuthHandler" ], prefix = "/auth_handler"
97
- )
98
- cheshire_cat_api .include_router (websocket .router , tags = ["Websocket" ])
99
-
100
- # mount static files
101
- # this cannot be done via fastapi.APIrouter:
102
- # https://github.com/tiangolo/fastapi/discussions/9070
103
-
104
- # admin single page app (static build)
105
- admin .mount (cheshire_cat_api )
106
- # static files (for plugins and other purposes)
107
- static .mount (cheshire_cat_api )
108
-
109
-
110
- # error handling
111
- @cheshire_cat_api .exception_handler (RequestValidationError )
112
- async def validation_exception_handler (request , exc ):
113
- return JSONResponse (
114
- status_code = 400 ,
115
- content = {"error" : exc .errors ()},
116
- )
117
-
118
-
119
- # openapi customization
120
- cheshire_cat_api .openapi = get_openapi_configuration_function (cheshire_cat_api )
121
-
122
- @cheshire_cat_api .get ("/docs" , include_in_schema = False )
123
- async def scalar_docs ():
124
- return get_scalar_api_reference (
125
- openapi_url = cheshire_cat_api .openapi_url ,
126
- title = cheshire_cat_api .title ,
127
- scalar_favicon_url = "https://cheshirecat.ai/wp-content/uploads/2023/10/Logo-Cheshire-Cat.svg" ,
128
- )
129
4
130
5
# RUN!
131
6
if __name__ == "__main__" :
7
+
8
+ # TODO: take away in v2
9
+ fix_legacy_env_variables ()
10
+
132
11
# debugging utilities, to deactivate put `DEBUG=false` in .env
133
12
debug_config = {}
134
13
if get_env ("CCAT_DEBUG" ) == "true" :
@@ -146,7 +25,7 @@ async def scalar_docs():
146
25
}
147
26
148
27
uvicorn .run (
149
- "cat.main :cheshire_cat_api" ,
28
+ "cat.startup :cheshire_cat_api" ,
150
29
host = "0.0.0.0" ,
151
30
port = 80 ,
152
31
use_colors = True ,
0 commit comments