feat: mongita first implementation
Browse files- .env.sample +6 -3
- app/api/chat_api.py +8 -0
- app/config/db.py +9 -2
- app/db/client.py +3 -3
- main.py +3 -3
- pyproject.toml +2 -1
- resources/mock/chat_api_list_messages.json +1 -1
- uv.lock +21 -0
.env.sample
CHANGED
|
@@ -7,7 +7,10 @@ SECRET_KEY="1234"
|
|
| 7 |
API_KEY="sk-lokumai=="
|
| 8 |
BASE_URL="http://0.0.0.0:7860"
|
| 9 |
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
DB_MONGO_URI=mongodb://localhost:27017
|
| 13 |
-
DB_MONGO_DATABASE_NAME=lokumai
|
|
|
|
| 7 |
API_KEY="sk-lokumai=="
|
| 8 |
BASE_URL="http://0.0.0.0:7860"
|
| 9 |
|
| 10 |
+
# mongodb, mongita_memory, mongita_disk
|
| 11 |
+
DB_DATABASE_TYPE=mongita_memory
|
| 12 |
+
# when type is disk
|
| 13 |
+
DB_MONGITA_DB_PATH="./local_dev.db"
|
| 14 |
+
|
| 15 |
+
DB_DATABASE_NAME=lokumai
|
| 16 |
DB_MONGO_URI=mongodb://localhost:27017
|
|
|
app/api/chat_api.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
| 2 |
|
| 3 |
from typing import List
|
| 4 |
from fastapi import APIRouter, HTTPException, Depends, Request
|
|
|
|
| 5 |
from app.schema.chat_schema import (
|
| 6 |
ChatCompletionRequest,
|
| 7 |
ChatCompletionResponse,
|
|
@@ -21,6 +22,13 @@ router = APIRouter(prefix="/v1", tags=["chat"])
|
|
| 21 |
service = ChatService()
|
| 22 |
auth_service = AuthService()
|
| 23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
################
|
| 26 |
# chat completion api list
|
|
|
|
| 2 |
|
| 3 |
from typing import List
|
| 4 |
from fastapi import APIRouter, HTTPException, Depends, Request
|
| 5 |
+
from pydantic import BaseModel
|
| 6 |
from app.schema.chat_schema import (
|
| 7 |
ChatCompletionRequest,
|
| 8 |
ChatCompletionResponse,
|
|
|
|
| 22 |
service = ChatService()
|
| 23 |
auth_service = AuthService()
|
| 24 |
|
| 25 |
+
class VersionResponse(BaseModel):
|
| 26 |
+
version: str = "0.0.1"
|
| 27 |
+
|
| 28 |
+
# version api from pyproject.toml
|
| 29 |
+
@router.get("/version", response_model=VersionResponse)
|
| 30 |
+
async def get_version():
|
| 31 |
+
return VersionResponse()
|
| 32 |
|
| 33 |
################
|
| 34 |
# chat completion api list
|
app/config/db.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
from pydantic_settings import BaseSettings, SettingsConfigDict
|
| 2 |
|
| 3 |
|
|
@@ -9,12 +10,18 @@ class DBConfig(BaseSettings):
|
|
| 9 |
extra="ignore",
|
| 10 |
)
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
MONGO_USER: str = "root"
|
| 13 |
MONGO_PASSWORD: str = "rootPass"
|
| 14 |
MONGO_HOST: str = "localhost"
|
| 15 |
MONGO_PORT: int = 27017
|
| 16 |
-
|
| 17 |
-
|
|
|
|
| 18 |
|
| 19 |
def get_mongo_uri(self) -> str:
|
| 20 |
return self.MONGO_URI
|
|
|
|
| 1 |
+
from typing import Literal, Optional
|
| 2 |
from pydantic_settings import BaseSettings, SettingsConfigDict
|
| 3 |
|
| 4 |
|
|
|
|
| 10 |
extra="ignore",
|
| 11 |
)
|
| 12 |
|
| 13 |
+
|
| 14 |
+
DATABASE_TYPE: Literal["mongodb", "mongita_disk", "mongita_memory"] = "mongodb"
|
| 15 |
+
DATABASE_NAME: str = "openai_chatbot_api"
|
| 16 |
+
MONGITA_DB_PATH: Optional[str] = None
|
| 17 |
+
|
| 18 |
MONGO_USER: str = "root"
|
| 19 |
MONGO_PASSWORD: str = "rootPass"
|
| 20 |
MONGO_HOST: str = "localhost"
|
| 21 |
MONGO_PORT: int = 27017
|
| 22 |
+
MONGO_URI: str = f"mongodb://{MONGO_USER}:{MONGO_PASSWORD}@{MONGO_HOST}:{MONGO_PORT}/{DATABASE_NAME}"
|
| 23 |
+
|
| 24 |
+
|
| 25 |
|
| 26 |
def get_mongo_uri(self) -> str:
|
| 27 |
return self.MONGO_URI
|
app/db/client.py
CHANGED
|
@@ -9,7 +9,7 @@ from environs import Env
|
|
| 9 |
env = Env()
|
| 10 |
env.read_env()
|
| 11 |
|
| 12 |
-
|
| 13 |
|
| 14 |
|
| 15 |
class MongoDBClient:
|
|
@@ -26,7 +26,7 @@ class MongoDBClient:
|
|
| 26 |
def __init__(self):
|
| 27 |
if self._client is None:
|
| 28 |
self._client = AsyncIOMotorClient(db_config.get_mongo_uri())
|
| 29 |
-
self._db = self._client[db_config.
|
| 30 |
|
| 31 |
@property
|
| 32 |
def client(self) -> AsyncIOMotorClient:
|
|
@@ -41,7 +41,7 @@ class MongoDBClient:
|
|
| 41 |
if not self._is_connected:
|
| 42 |
if self._client is None:
|
| 43 |
self._client = AsyncIOMotorClient(db_config.get_mongo_uri())
|
| 44 |
-
self._db = self._client[db_config.
|
| 45 |
await self._client.server_info()
|
| 46 |
self._is_connected = True
|
| 47 |
logger.info("Connected to MongoDB")
|
|
|
|
| 9 |
env = Env()
|
| 10 |
env.read_env()
|
| 11 |
|
| 12 |
+
DB_DATABASE_TYPE = env.str("DB_DATABASE_TYPE", "mongodb")
|
| 13 |
|
| 14 |
|
| 15 |
class MongoDBClient:
|
|
|
|
| 26 |
def __init__(self):
|
| 27 |
if self._client is None:
|
| 28 |
self._client = AsyncIOMotorClient(db_config.get_mongo_uri())
|
| 29 |
+
self._db = self._client[db_config.DATABASE_NAME]
|
| 30 |
|
| 31 |
@property
|
| 32 |
def client(self) -> AsyncIOMotorClient:
|
|
|
|
| 41 |
if not self._is_connected:
|
| 42 |
if self._client is None:
|
| 43 |
self._client = AsyncIOMotorClient(db_config.get_mongo_uri())
|
| 44 |
+
self._db = self._client[db_config.DATABASE_NAME]
|
| 45 |
await self._client.server_info()
|
| 46 |
self._is_connected = True
|
| 47 |
logger.info("Connected to MongoDB")
|
main.py
CHANGED
|
@@ -18,7 +18,7 @@ print(log_config.get_log_level())
|
|
| 18 |
env = Env()
|
| 19 |
env.read_env()
|
| 20 |
|
| 21 |
-
|
| 22 |
|
| 23 |
# Hugging Face Spaces için özel yapılandırma
|
| 24 |
IS_HF_SPACE = os.environ.get("SPACE_ID") is not None
|
|
@@ -33,13 +33,13 @@ async def lifespan(app: FastAPI):
|
|
| 33 |
"""
|
| 34 |
# Startup
|
| 35 |
logger.info("Starting up application...")
|
| 36 |
-
if
|
| 37 |
await mongodb.connect()
|
| 38 |
yield
|
| 39 |
|
| 40 |
# Shutdown
|
| 41 |
logger.info("Shutting down application...")
|
| 42 |
-
if
|
| 43 |
await mongodb.close()
|
| 44 |
|
| 45 |
|
|
|
|
| 18 |
env = Env()
|
| 19 |
env.read_env()
|
| 20 |
|
| 21 |
+
DB_DATABASE_TYPE = env.str("DB_DATABASE_TYPE", "mongodb")
|
| 22 |
|
| 23 |
# Hugging Face Spaces için özel yapılandırma
|
| 24 |
IS_HF_SPACE = os.environ.get("SPACE_ID") is not None
|
|
|
|
| 33 |
"""
|
| 34 |
# Startup
|
| 35 |
logger.info("Starting up application...")
|
| 36 |
+
if DB_DATABASE_TYPE == "mongodb":
|
| 37 |
await mongodb.connect()
|
| 38 |
yield
|
| 39 |
|
| 40 |
# Shutdown
|
| 41 |
logger.info("Shutting down application...")
|
| 42 |
+
if DB_DATABASE_TYPE == "mongodb":
|
| 43 |
await mongodb.close()
|
| 44 |
|
| 45 |
|
pyproject.toml
CHANGED
|
@@ -10,6 +10,7 @@ dependencies = [
|
|
| 10 |
"gradio>=5.30.0",
|
| 11 |
"httpx>=0.28.1",
|
| 12 |
"loguru>=0.7.3",
|
|
|
|
| 13 |
"motor>=3.7.1",
|
| 14 |
"plotly>=6.1.1",
|
| 15 |
"pydantic>=2.11.4",
|
|
@@ -21,4 +22,4 @@ dependencies = [
|
|
| 21 |
|
| 22 |
# ruff line length
|
| 23 |
[tool.ruff]
|
| 24 |
-
line-length = 145
|
|
|
|
| 10 |
"gradio>=5.30.0",
|
| 11 |
"httpx>=0.28.1",
|
| 12 |
"loguru>=0.7.3",
|
| 13 |
+
"mongita>=1.2.0",
|
| 14 |
"motor>=3.7.1",
|
| 15 |
"plotly>=6.1.1",
|
| 16 |
"pydantic>=2.11.4",
|
|
|
|
| 22 |
|
| 23 |
# ruff line length
|
| 24 |
[tool.ruff]
|
| 25 |
+
line-length = 145
|
resources/mock/chat_api_list_messages.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
[
|
| 2 |
{
|
| 3 |
-
"message_id": "msg_mock-
|
| 4 |
"role": "assistant",
|
| 5 |
"content": "## Result\n|status|count|\n|---|---|\n|active|100|\n|cancelled|30|\n|pending|40|\n|passive|150|\n\n## Explanation\nThis result represents the number of active, cancelled, pending and passive customers in the year 2025. This is a mock result for the question \"How many customers are active, cancelled, pending and passive in the year 2025?\"\n\n## Query\n```sql\nSELECT status, COUNT(*) FROM customers WHERE year = 2025 GROUP BY status;\n```",
|
| 6 |
"figure": {"data":[{"alignmentgroup":"True","customdata":[["North"],["North"],["South"]],"hovertemplate":"category=Category A\u003cbr\u003estatus=%{x}\u003cbr\u003ecount=%{y}\u003cbr\u003eregion=%{customdata[0]}\u003cextra\u003e\u003c\u002fextra\u003e","legendgroup":"Category A","marker":{"color":"#636efa","pattern":{"shape":""}},"name":"Category A","offsetgroup":"Category A","orientation":"v","showlegend":true,"textposition":"auto","texttemplate":"%{y}","x":["active","in_review","pending_deletion"],"xaxis":"x","y":{"dtype":"i1","bdata":"Mh4P"},"yaxis":"y","type":"bar"},{"alignmentgroup":"True","customdata":[["South"],["West"]],"hovertemplate":"category=Category B\u003cbr\u003estatus=%{x}\u003cbr\u003ecount=%{y}\u003cbr\u003eregion=%{customdata[0]}\u003cextra\u003e\u003c\u002fextra\u003e","legendgroup":"Category B","marker":{"color":"#EF553B","pattern":{"shape":""}},"name":"Category B","offsetgroup":"Category B","orientation":"v","showlegend":true,"textposition":"auto","texttemplate":"%{y}","x":["passive","newly_added"],"xaxis":"x","y":{"dtype":"i1","bdata":"Rhk="},"yaxis":"y","type":"bar"},{"alignmentgroup":"True","customdata":[["East"]],"hovertemplate":"category=Category C\u003cbr\u003estatus=%{x}\u003cbr\u003ecount=%{y}\u003cbr\u003eregion=%{customdata[0]}\u003cextra\u003e\u003c\u002fextra\u003e","legendgroup":"Category C","marker":{"color":"#00cc96","pattern":{"shape":""}},"name":"Category C","offsetgroup":"Category C","orientation":"v","showlegend":true,"textposition":"auto","texttemplate":"%{y}","x":["archived"],"xaxis":"x","y":{"dtype":"i1","bdata":"Wg=="},"yaxis":"y","type":"bar"}],"layout":{"template":{"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"type":"scattergl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermap":[{"type":"scattermap","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermapbox":[{"type":"scattermapbox","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]},"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"mapbox":{"style":"light"}}},"xaxis":{"anchor":"y","domain":[0.0,1.0],"title":{"text":"Status"}},"yaxis":{"anchor":"x","domain":[0.0,1.0],"title":{"text":"Count"}},"legend":{"title":{"text":"Category"},"tracegroupgap":0},"title":{"text":"Bar Chart: Count by Status and Category","x":0.5},"barmode":"group"}}
|
|
|
|
| 1 |
[
|
| 2 |
{
|
| 3 |
+
"message_id": "msg_mock-1234",
|
| 4 |
"role": "assistant",
|
| 5 |
"content": "## Result\n|status|count|\n|---|---|\n|active|100|\n|cancelled|30|\n|pending|40|\n|passive|150|\n\n## Explanation\nThis result represents the number of active, cancelled, pending and passive customers in the year 2025. This is a mock result for the question \"How many customers are active, cancelled, pending and passive in the year 2025?\"\n\n## Query\n```sql\nSELECT status, COUNT(*) FROM customers WHERE year = 2025 GROUP BY status;\n```",
|
| 6 |
"figure": {"data":[{"alignmentgroup":"True","customdata":[["North"],["North"],["South"]],"hovertemplate":"category=Category A\u003cbr\u003estatus=%{x}\u003cbr\u003ecount=%{y}\u003cbr\u003eregion=%{customdata[0]}\u003cextra\u003e\u003c\u002fextra\u003e","legendgroup":"Category A","marker":{"color":"#636efa","pattern":{"shape":""}},"name":"Category A","offsetgroup":"Category A","orientation":"v","showlegend":true,"textposition":"auto","texttemplate":"%{y}","x":["active","in_review","pending_deletion"],"xaxis":"x","y":{"dtype":"i1","bdata":"Mh4P"},"yaxis":"y","type":"bar"},{"alignmentgroup":"True","customdata":[["South"],["West"]],"hovertemplate":"category=Category B\u003cbr\u003estatus=%{x}\u003cbr\u003ecount=%{y}\u003cbr\u003eregion=%{customdata[0]}\u003cextra\u003e\u003c\u002fextra\u003e","legendgroup":"Category B","marker":{"color":"#EF553B","pattern":{"shape":""}},"name":"Category B","offsetgroup":"Category B","orientation":"v","showlegend":true,"textposition":"auto","texttemplate":"%{y}","x":["passive","newly_added"],"xaxis":"x","y":{"dtype":"i1","bdata":"Rhk="},"yaxis":"y","type":"bar"},{"alignmentgroup":"True","customdata":[["East"]],"hovertemplate":"category=Category C\u003cbr\u003estatus=%{x}\u003cbr\u003ecount=%{y}\u003cbr\u003eregion=%{customdata[0]}\u003cextra\u003e\u003c\u002fextra\u003e","legendgroup":"Category C","marker":{"color":"#00cc96","pattern":{"shape":""}},"name":"Category C","offsetgroup":"Category C","orientation":"v","showlegend":true,"textposition":"auto","texttemplate":"%{y}","x":["archived"],"xaxis":"x","y":{"dtype":"i1","bdata":"Wg=="},"yaxis":"y","type":"bar"}],"layout":{"template":{"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"type":"scattergl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermap":[{"type":"scattermap","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermapbox":[{"type":"scattermapbox","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]},"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"mapbox":{"style":"light"}}},"xaxis":{"anchor":"y","domain":[0.0,1.0],"title":{"text":"Status"}},"yaxis":{"anchor":"x","domain":[0.0,1.0],"title":{"text":"Count"}},"legend":{"title":{"text":"Category"},"tracegroupgap":0},"title":{"text":"Bar Chart: Count by Status and Category","x":0.5},"barmode":"group"}}
|
uv.lock
CHANGED
|
@@ -429,6 +429,16 @@ wheels = [
|
|
| 429 |
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
|
| 430 |
]
|
| 431 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 432 |
[[package]]
|
| 433 |
name = "motor"
|
| 434 |
version = "3.7.1"
|
|
@@ -498,6 +508,7 @@ dependencies = [
|
|
| 498 |
{ name = "gradio" },
|
| 499 |
{ name = "httpx" },
|
| 500 |
{ name = "loguru" },
|
|
|
|
| 501 |
{ name = "motor" },
|
| 502 |
{ name = "plotly" },
|
| 503 |
{ name = "pydantic" },
|
|
@@ -514,6 +525,7 @@ requires-dist = [
|
|
| 514 |
{ name = "gradio", specifier = ">=5.30.0" },
|
| 515 |
{ name = "httpx", specifier = ">=0.28.1" },
|
| 516 |
{ name = "loguru", specifier = ">=0.7.3" },
|
|
|
|
| 517 |
{ name = "motor", specifier = ">=3.7.1" },
|
| 518 |
{ name = "plotly", specifier = ">=6.1.1" },
|
| 519 |
{ name = "pydantic", specifier = ">=2.11.4" },
|
|
@@ -951,6 +963,15 @@ wheels = [
|
|
| 951 |
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
| 952 |
]
|
| 953 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 954 |
[[package]]
|
| 955 |
name = "starlette"
|
| 956 |
version = "0.46.2"
|
|
|
|
| 429 |
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
|
| 430 |
]
|
| 431 |
|
| 432 |
+
[[package]]
|
| 433 |
+
name = "mongita"
|
| 434 |
+
version = "1.2.0"
|
| 435 |
+
source = { registry = "https://pypi.org/simple" }
|
| 436 |
+
dependencies = [
|
| 437 |
+
{ name = "pymongo" },
|
| 438 |
+
{ name = "sortedcontainers" },
|
| 439 |
+
]
|
| 440 |
+
sdist = { url = "https://files.pythonhosted.org/packages/a4/b6/9159dca5e74e497b19ab8e68c369f789dc2167d2c8cccb5fbd21377ba040/mongita-1.2.0.tar.gz", hash = "sha256:27487d1deb40d83e4ecb107c3d9d732d369a83cc5f10599ba86fc024e2ce9cda", size = 54582 }
|
| 441 |
+
|
| 442 |
[[package]]
|
| 443 |
name = "motor"
|
| 444 |
version = "3.7.1"
|
|
|
|
| 508 |
{ name = "gradio" },
|
| 509 |
{ name = "httpx" },
|
| 510 |
{ name = "loguru" },
|
| 511 |
+
{ name = "mongita" },
|
| 512 |
{ name = "motor" },
|
| 513 |
{ name = "plotly" },
|
| 514 |
{ name = "pydantic" },
|
|
|
|
| 525 |
{ name = "gradio", specifier = ">=5.30.0" },
|
| 526 |
{ name = "httpx", specifier = ">=0.28.1" },
|
| 527 |
{ name = "loguru", specifier = ">=0.7.3" },
|
| 528 |
+
{ name = "mongita", specifier = ">=1.2.0" },
|
| 529 |
{ name = "motor", specifier = ">=3.7.1" },
|
| 530 |
{ name = "plotly", specifier = ">=6.1.1" },
|
| 531 |
{ name = "pydantic", specifier = ">=2.11.4" },
|
|
|
|
| 963 |
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
| 964 |
]
|
| 965 |
|
| 966 |
+
[[package]]
|
| 967 |
+
name = "sortedcontainers"
|
| 968 |
+
version = "2.4.0"
|
| 969 |
+
source = { registry = "https://pypi.org/simple" }
|
| 970 |
+
sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 }
|
| 971 |
+
wheels = [
|
| 972 |
+
{ url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 },
|
| 973 |
+
]
|
| 974 |
+
|
| 975 |
[[package]]
|
| 976 |
name = "starlette"
|
| 977 |
version = "0.46.2"
|