Skip to content

Commit 240c8ee

Browse files
authored
Merge branch 'main' into edr/getting_started_doc
2 parents 5d44e63 + ca6df6a commit 240c8ee

File tree

141 files changed

+13199
-1184
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+13199
-1184
lines changed

.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CUDA_VISIBLE_DEVICES=""
2+
USE_DEPLOYMENT_CACHE = True
3+
SAVE_DEPLOYMENT_CACHE = True

.github/workflows/python-package.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ jobs:
3838
sudo apt-get update
3939
sudo apt-get install ffmpeg
4040
- name: Test with pytest
41-
run: poetry run pytest
41+
run: poetry run pytest -vv

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ celerybeat.pid
120120
*.sage.py
121121

122122
# Environments
123-
.env
124123
.venv
125124
env/
126125
venv/

README.md

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,52 @@ that Ruff problems appear while you edit, and formatting is applied
135135
automatically on save.
136136

137137

138+
## Testing
139+
140+
The project uses pytest for testing. To run the tests, use the following command:
141+
142+
```bash
143+
poetry run pytest
144+
```
145+
146+
If you are using VS Code, you can run the tests using the Test Explorer that is installed with the [Python extension](https://code.visualstudio.com/docs/python/testing).
147+
148+
There are a few environment variables that can be set to control the behavior of the tests:
149+
- `USE_DEPLOYMENT_CACHE`: If set to `true`, the tests will use the deployment cache to avoid downloading the models and running the deployments. This is useful for running integration tests faster and in the environment where GPU is not available.
150+
- `SAVE_DEPLOYMENT_CACHE`: If set to `true`, the tests will save the deployment cache after running the deployments. This is useful for updating the deployment cache if new deployments or tests are added.
151+
152+
### How to use the deployment cache environment variables
153+
154+
Here are some examples of how to use the deployment cache environment variables.
155+
156+
#### Do you want to run the tests normally using GPU?
157+
158+
```bash
159+
USE_DEPLOYMENT_CACHE=false
160+
SAVE_DEPLOYMENT_CACHE=false
161+
```
162+
163+
This is the default behavior. The tests will run normally using GPU and the deployment cache will be completely ignored.
164+
165+
#### Do you want to run the tests faster without GPU?
166+
167+
```bash
168+
USE_DEPLOYMENT_CACHE=true
169+
SAVE_DEPLOYMENT_CACHE=false
170+
```
171+
172+
This will run the tests using the deployment cache to avoid downloading the models and running the deployments. The deployment cache will not be updated after running the deployments. Only use it if you are sure that the deployment cache is up to date.
173+
174+
#### Do you want to update the deployment cache?
175+
176+
```bash
177+
USE_DEPLOYMENT_CACHE=false
178+
SAVE_DEPLOYMENT_CACHE=true
179+
```
180+
181+
This will run the tests normally using GPU and save the deployment cache after running the deployments. Use it if you have added new deployments or tests and want to update the deployment cache.
182+
183+
138184
## Databases
139185
The project uses two databases: a vector database as well as a tradtional SQL database,
140186
referred to internally as vectorstore and datastore, respectively.
@@ -156,4 +202,13 @@ ORM models referenced in the rest of the code should be imported from `aana.mode
156202
not from that model's file for reasons explained in `aana/models/db/__init__.py`. This also means that
157203
if you add a new model class, it should be imported by `__init__.py` in addition to creating a migration.
158204

159-
Higher level code for interacting with the ORM is available in `aana.repository.data`.
205+
Higher level code for interacting with the ORM is available in `aana.repository.data`.
206+
207+
## Settings
208+
209+
Here are the environment variables that can be used to configure the Aaana SDK:
210+
- TMP_DATA_DIR: The directory to store temporary data. Default: `/tmp/aana`.
211+
- NUM_WORKERS: The number of request workers. Default: `2`.
212+
- DB_CONFIG: The database configuration in the format `{"datastore_type": "sqlite", "datastore_config": {"path": "/path/to/sqlite.db"}}`. Currently only SQLite and PostgreSQL are supported. Default: `{"datastore_type": "sqlite", "datastore_config": {"path": "/var/lib/aana_data"}}`.
213+
- USE_DEPLOYMENT_CACHE (testing only): If set to `true`, the tests will use the deployment cache to avoid downloading the models and running the deployments. Default: `false`.
214+
- SAVE_DEPLOYMENT_CACHE (testing only): If set to `true`, the tests will save the deployment cache after running the deployments. Default: `false`.

aana/api/app.py

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -81,40 +81,15 @@ def custom_exception_handler(request: Request | None, exc_raw: Exception):
8181
)
8282

8383

84-
@app.exception_handler(BaseException)
85-
async def pipeline_exception_handler(request: Request, exc: BaseException):
84+
@app.exception_handler(Exception)
85+
async def pipeline_exception_handler(request: Request, exc: Exception):
8686
"""This handler is used to handle exceptions raised by the Mobius Pipeline and Aana application.
8787
8888
Args:
8989
request (Request): The request object
90-
exc (BaseException): The exception raised
90+
exc (Exception): The exception raised
9191
9292
Returns:
9393
JSONResponse: JSON response with the error details
9494
"""
9595
return custom_exception_handler(request, exc)
96-
97-
98-
@app.exception_handler(RayTaskError)
99-
async def ray_task_error_handler(request: Request, exc: RayTaskError):
100-
"""This handler is used to handle RayTaskError exceptions.
101-
102-
Args:
103-
request (Request): The request object
104-
exc (RayTaskError): The exception raised
105-
106-
Returns:
107-
JSONResponse: JSON response with the error details. The response contains the following fields:
108-
error: The name of the exception class.
109-
message: The message of the exception.
110-
stacktrace: The stacktrace of the exception.
111-
"""
112-
error = exc.__class__.__name__
113-
stacktrace = traceback.format_exc()
114-
115-
return AanaJSONResponse(
116-
status_code=400,
117-
content=ExceptionResponseModel(
118-
error=error, message=str(exc), stacktrace=stacktrace
119-
).dict(),
120-
)

aana/api/responses.py

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,9 @@
1-
from pathlib import Path
21
from typing import Any
32

43
import orjson
54
from fastapi.responses import JSONResponse
6-
from pydantic import BaseModel
75

8-
9-
def json_serializer_default(obj: Any) -> Any:
10-
"""Default function for json serializer to handle pydantic models.
11-
12-
If json serializer does not know how to serialize an object, it calls the default function.
13-
14-
If we see that the object is a pydantic model,
15-
we call the dict method to get the dictionary representation of the model
16-
that json serializer can deal with.
17-
18-
If the object is not a pydantic model, we raise a TypeError.
19-
20-
Args:
21-
obj (Any): The object to serialize.
22-
23-
Returns:
24-
Any: The serializable object.
25-
26-
Raises:
27-
TypeError: If the object is not a pydantic model.
28-
"""
29-
if isinstance(obj, BaseModel):
30-
return obj.dict()
31-
if isinstance(obj, Path):
32-
return str(obj)
33-
raise TypeError
6+
from aana.utils.json import json_serializer_default
347

358

369
class AanaJSONResponse(JSONResponse):

aana/configs/db.py

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,32 @@
55

66
from alembic import command
77
from alembic.config import Config
8-
from sqlalchemy import String, create_engine
8+
from sqlalchemy import String, TypeDecorator, create_engine
99

10-
# These are here so we can change types in a single place.
10+
from aana.models.pydantic.media_id import MediaId
1111

12-
media_id_type: TypeAlias = str
13-
MediaIdSqlType: TypeAlias = String
12+
13+
class MediaIdType(TypeDecorator):
14+
"""Custom type for handling MediaId objects with SQLAlchemy."""
15+
16+
impl = String
17+
18+
cache_ok = True
19+
20+
def process_bind_param(self, value, dialect):
21+
"""Convert a MediaId instance to a string value for storage."""
22+
if value is None:
23+
return value
24+
return str(value)
25+
26+
def process_result_value(self, value, dialect):
27+
"""Convert a string value from the database back into a MediaId instance."""
28+
if value is None:
29+
return value
30+
return MediaId(value)
31+
32+
33+
MediaIdSqlType: TypeAlias = MediaIdType
1434

1535

1636
class SQLiteConfig(TypedDict):
@@ -112,3 +132,17 @@ def run_alembic_migrations(settings):
112132

113133
alembic_config = get_alembic_config(settings, ini_file_path, alembic_data_path)
114134
command.upgrade(alembic_config, "head")
135+
136+
137+
def drop_all_tables(settings):
138+
"""Drops all tables in the database."""
139+
# TODO: only allow this in testing mode
140+
current_path = Path(__file__)
141+
aana_root = current_path.parent.parent # go up two directories
142+
if aana_root.name != "aana": # we are not in the right place
143+
raise RuntimeError("Not in right directory, exiting.") # noqa: TRY003
144+
ini_file_path = aana_root / "alembic.ini"
145+
alembic_data_path = aana_root / "alembic"
146+
147+
alembic_config = get_alembic_config(settings, ini_file_path, alembic_data_path)
148+
command.downgrade(alembic_config, "base")

aana/configs/endpoints.py

Lines changed: 8 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,6 @@
6969
],
7070
),
7171
],
72-
"video": [
73-
Endpoint(
74-
name="video_extract_frames",
75-
path="/video/extract_frames",
76-
summary="Extract frames from a video",
77-
outputs=[
78-
EndpointOutput(name="timestamps", output="timestamps"),
79-
EndpointOutput(name="duration", output="duration"),
80-
],
81-
)
82-
],
8372
"whisper": [
8473
Endpoint(
8574
name="whisper_transcribe",
@@ -124,8 +113,6 @@
124113
),
125114
],
126115
),
127-
],
128-
"chat_with_video_test": [
129116
Endpoint(
130117
name="delete_media_id",
131118
path="/video/delete",
@@ -136,54 +123,6 @@
136123
),
137124
],
138125
"chat_with_video": [
139-
Endpoint(
140-
name="delete_media_id",
141-
path="/video/delete",
142-
summary="Delete a video",
143-
outputs=[
144-
EndpointOutput(name="deleted_media_id", output="deleted_media_id")
145-
],
146-
),
147-
Endpoint(
148-
name="blip2_video_generate",
149-
path="/video/generate_captions",
150-
summary="Generate captions for videos using BLIP2 OPT-2.7B",
151-
outputs=[
152-
EndpointOutput(
153-
name="captions",
154-
output="video_captions_hf_blip2_opt_2_7b",
155-
streaming=True,
156-
),
157-
EndpointOutput(
158-
name="timestamps", output="video_timestamps", streaming=True
159-
),
160-
],
161-
streaming=True,
162-
),
163-
Endpoint(
164-
name="whisper_transcribe",
165-
path="/video/transcribe",
166-
summary="Transcribe a video using Whisper Medium",
167-
outputs=[
168-
EndpointOutput(
169-
name="transcription",
170-
output="video_transcriptions_whisper_medium",
171-
streaming=True,
172-
),
173-
EndpointOutput(
174-
name="segments",
175-
output="video_transcriptions_segments_whisper_medium",
176-
streaming=True,
177-
),
178-
EndpointOutput(
179-
name="info",
180-
output="video_transcriptions_info_whisper_medium",
181-
streaming=True,
182-
),
183-
EndpointOutput(name="transcription_id", output="transcription_id"),
184-
],
185-
streaming=True,
186-
),
187126
Endpoint(
188127
name="index_video_stream",
189128
path="/video/index_stream",
@@ -217,27 +156,6 @@
217156
],
218157
streaming=True,
219158
),
220-
Endpoint(
221-
name="llm_generate",
222-
path="/llm/generate",
223-
summary="Generate text using LLaMa2 7B Chat",
224-
outputs=[
225-
EndpointOutput(name="completion", output="vllm_llama2_7b_chat_output")
226-
],
227-
),
228-
Endpoint(
229-
name="llm_generate_stream",
230-
path="/llm/generate_stream",
231-
summary="Generate text using LLaMa2 7B Chat (streaming)",
232-
outputs=[
233-
EndpointOutput(
234-
name="completion",
235-
output="vllm_llama2_7b_chat_output_stream",
236-
streaming=True,
237-
)
238-
],
239-
streaming=True,
240-
),
241159
Endpoint(
242160
name="video_chat_stream",
243161
path="/video/chat_stream",
@@ -259,6 +177,14 @@
259177
EndpointOutput(name="metadata", output="video_metadata"),
260178
],
261179
),
180+
Endpoint(
181+
name="delete_media_id",
182+
path="/video/delete",
183+
summary="Delete a video",
184+
outputs=[
185+
EndpointOutput(name="deleted_media_id", output="deleted_media_id")
186+
],
187+
),
262188
],
263189
"stablediffusion2": [
264190
Endpoint(

aana/configs/pipeline.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
from aana.models.pydantic.captions import CaptionsList, VideoCaptionsList
1616
from aana.models.pydantic.chat_message import ChatDialog
1717
from aana.models.pydantic.image_input import ImageInputList
18+
from aana.models.pydantic.media_id import MediaId
1819
from aana.models.pydantic.prompt import Prompt
20+
from aana.models.pydantic.question import Question
1921
from aana.models.pydantic.sampling_params import SamplingParams
2022
from aana.models.pydantic.video_input import VideoInput, VideoInputList
2123
from aana.models.pydantic.video_metadata import VideoMetadata
@@ -526,6 +528,7 @@
526528
"name": "media_id",
527529
"key": "media_id",
528530
"path": "media_id",
531+
"data_model": MediaId,
529532
}
530533
],
531534
},
@@ -538,6 +541,7 @@
538541
"name": "question",
539542
"key": "question",
540543
"path": "question",
544+
"data_model": Question,
541545
}
542546
],
543547
},

0 commit comments

Comments
 (0)