Skip to content

Commit 2f0a9ac

Browse files
committed
Merge branch 'development'
2 parents a5064b3 + 3622202 commit 2f0a9ac

21 files changed

+118
-65
lines changed

Makefile

-3
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,6 @@ run-pgadmin:
133133
echo "$$SERVERS_JSON" > ./pgadmin/servers.json && \
134134
docker volume create pgadmin_data && \
135135
docker compose -f pgadmin.yml up --force-recreate
136-
137-
load-server-pgadmin:
138-
docker exec -it pgadmin python /pgadmin4/setup.py --load-servers servers.json
139136

140137
clean-pgadmin:
141138
docker volume rm pgadmin_data

README.md

+69-9
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Developing web applications can be a challenging process, especially when dealin
1414
- Development Best Practices: We apply code formatting, type checking, and static analysis tools to ensure that the code is readable, robust, and reliable.
1515

1616
## Table of Contents
17-
1. [Set environment variables](#set-environment-variables)
17+
1. [Prerequisites](#prerequisites)
1818
2. [Run the project using Docker containers and forcing build containers](#run-the-project-using-docker-containers-and-forcing-build-containers)
1919
3. [Run project using Docker containers](#run-project-using-docker-containers)
2020
4. [Setup database with initial data](#setup-database-with-initial-data)
@@ -36,10 +36,72 @@ Developing web applications can be a challenging process, especially when dealin
3636
20. [TODO List](#todo-list)
3737
21. [License](#license)
3838

39+
# Prerequisites
40+
3941
## Set environment variables
4042

4143
Create an **.env** file on root folder and copy the content from **.env.example**. Feel free to change it according to your own configuration.
4244

45+
## Docker engine
46+
This project utilizes Docker and Docker Compose, so please ensure that you have installed the latest version compatible with your operating system. If you haven't already installed Docker, you can find detailed instructions on how to do so [here](https://docs.docker.com/engine/install/). Docker desktop can be good for a dev computer.
47+
48+
You can check if it is installed with this command
49+
```
50+
docker --version
51+
```
52+
53+
## Make
54+
"Make" is a build automation tool that is primarily used to manage the compilation and building of software projects. It reads a file called a "Makefile" which specifies a set of rules and dependencies for building a project, and then executes the necessary commands to build the project according to those rules. Depending of your OS you will requiere to install it in different ways.
55+
56+
Mac
57+
```
58+
xcode-select --install
59+
```
60+
61+
Ubuntu
62+
```
63+
sudo apt-get install build-essential
64+
sudo apt-get -y install make
65+
```
66+
67+
You can check if it is installed with this command
68+
```
69+
make --version
70+
```
71+
72+
## Python ">3.9,<3.12"
73+
If you haven't already installed Python. You can download and install python from [here](https://www.python.org/downloads/).
74+
75+
You can check yu python version:
76+
```
77+
python --version
78+
```
79+
80+
## Poetry
81+
82+
Python Poetry is a tool for dependency management and packaging in Python. It provides a modern and efficient approach to managing Python projects' dependencies, virtual environments, and packaging. You can find detailed instructions on how install it [here](https://python-poetry.org/docs/#installing-with-the-official-installer). Poetry manages packages in **pyproject.toml** file; In this project you can find it in the folder backend/app.
83+
84+
You can check if it is installed with this command
85+
```
86+
poetry --version
87+
```
88+
89+
### Dev tip to activate virtual environment
90+
When you are opening python files do this cna help you to vscode detect installed packages.
91+
92+
```
93+
cd backend/app/
94+
poetry shell
95+
```
96+
97+
After that you can show the interpreted path. You can copy that path and set as the default for the project in vscode. Press on **Enter interpreter path ..** and past path.
98+
99+
<p align="center">
100+
<img src="static/python_int.png" align="center"/>
101+
</p>
102+
103+
104+
43105
## Run the project using Docker containers and forcing build containers
44106

45107
*Using docker compose command*
@@ -92,12 +154,7 @@ You can connect to the Database using pgAdmin4 and use the credentials from .env
92154
make run-pgadmin
93155
```
94156

95-
*Load server configuration (It is required just the first time)*
96-
```sh
97-
make load-server-pgadmin
98-
```
99-
100-
This starts pgamin in [http://localhost:15432](http://localhost:15432).
157+
This starts pgamin in [http://localhost:15432](http://localhost:15432). When connecting to db server introduce the password by default it is **postgres** if you didn't change it in .env file.
101158

102159
<p align="center">
103160
<img src="static/tables.png" align="center"/>
@@ -298,13 +355,13 @@ make mypy
298355
```
299356

300357
## Basic chatbot example with Langchain and OpenAI
301-
In addition to its core features, this project template demonstrates how to integrate an basic chatbot powered by Langchain and OpenAI through websockets.
358+
In addition to its core features, this project template demonstrates how to integrate an basic chatbot powered by Langchain and OpenAI through websockets. You can use [PieSocket Websocket Tester](https://chromewebstore.google.com/detail/oilioclnckkoijghdniegedkbocfpnip) to test websockets.
302359

303360
To begin experimenting with the basic chatbot, follow these steps:
304361

305362
1. **Obtain an OpenAI API Key**: You'll need to set the `OPENAI_API_KEY` environment variable, which you can obtain from [OpenAI's platform](https://platform.openai.com/).
306363

307-
2. **Test Websocket Connection**: You can test the websocket connection by using the following URL: [ws://fastapi.localhost/chat/\<USER_ID\>](ws://fastapi.localhost/chat/<USER_ID>). Replace `<USER_ID>` with a user identifier of your choice.
364+
2. **Test Websocket Connection**: You can test the websocket connection by using the following URL: [ws://fastapi.localhost/chat/\<USER_ID\>](ws://fastapi.localhost/chat/<USER_ID>). Replace `<USER_ID>` with a user identifier of your choice. It should be the ID of your user.
308365

309366
3. **Sending and Receiving Messages**: You should be able to send messages to the chatbot using the provided websocket connection. To do this, use the following message structure:
310367

@@ -313,6 +370,9 @@ To begin experimenting with the basic chatbot, follow these steps:
313370
```
314371
Once you send a message, the chatbot will respond with generated responses based on the content of your input.
315372

373+
<p align="center">
374+
<img src="static/ws.png" align="center"/>
375+
</p>
316376

317377
## Inspiration and References
318378

backend/app/app/api/v1/endpoints/login.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ async def get_new_access_token(
158158
status_code=status.HTTP_403_FORBIDDEN,
159159
detail="Error when decoding the token. Please check your request.",
160160
)
161-
except MissingRequiredClaimError as e:
161+
except MissingRequiredClaimError:
162162
raise HTTPException(
163163
status_code=status.HTTP_403_FORBIDDEN,
164164
detail="There is no required field in your token. Please contact the administrator.",

backend/app/app/crud/base_crud.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ async def get_multi_paginated(
8585
db_session = db_session or self.db.session
8686
if query is None:
8787
query = select(self.model)
88-
88+
8989
output = await paginate(db_session, query, params)
9090
return output
9191

backend/app/app/db/session.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
str(settings.ASYNC_CELERY_BEAT_DATABASE_URI),
3535
# echo=True,
3636
future=True,
37-
#pool_size=POOL_SIZE,
38-
#max_overflow=64,
37+
# pool_size=POOL_SIZE,
38+
# max_overflow=64,
3939
)
4040

4141
SessionLocalCelery = sessionmaker(

backend/app/app/main.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from fastapi_cache.backends.redis import RedisBackend
1818
from fastapi_limiter import FastAPILimiter
1919
from fastapi_limiter.depends import WebSocketRateLimiter
20-
from fastapi_pagination import add_pagination
2120
from jwt import DecodeError, ExpiredSignatureError, MissingRequiredClaimError
2221
from langchain.chat_models import ChatOpenAI
2322
from langchain.schema import HumanMessage
@@ -189,7 +188,7 @@ async def websocket_endpoint(websocket: WebSocket, user_id: UUID):
189188
# Receive and send back the client message
190189
data = await websocket.receive_json()
191190
await ws_ratelimit(websocket)
192-
user_message = IUserMessage.parse_obj(data)
191+
user_message = IUserMessage.model_validate(data)
193192
user_message.user_id = user_id
194193

195194
resp = IChatResponse(
@@ -227,7 +226,7 @@ async def websocket_endpoint(websocket: WebSocket, user_id: UUID):
227226
message_id="",
228227
id="",
229228
sender="bot",
230-
message="Sorry, something went wrong. Your user limit of api usages has been reached.",
229+
message="Sorry, something went wrong. Your user limit of api usages has been reached or check your API key.",
231230
type="error",
232231
)
233232
await websocket.send_json(resp.dict())
@@ -237,4 +236,4 @@ async def websocket_endpoint(websocket: WebSocket, user_id: UUID):
237236

238237

239238
# Add Routers
240-
app.include_router(api_router_v1, prefix=settings.API_V1_STR)
239+
app.include_router(api_router_v1, prefix=settings.API_V1_STR)

backend/app/app/models/base_uuid_model.py

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from sqlalchemy.orm import declared_attr
55
from datetime import datetime
66

7+
78
# id: implements proposal uuid7 draft4
89
class SQLModel(_SQLModel):
910
@declared_attr # type: ignore

backend/app/app/models/team_model.py

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from uuid import UUID
55

66

7-
87
class TeamBase(SQLModel):
98
name: str = Field(index=True)
109
headquarters: str

backend/app/app/models/user_follow_model.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ class UserFollowBase(SQLModel):
1010

1111

1212
class UserFollow(BaseUUIDModel, UserFollowBase, table=True):
13-
is_mutual: bool | None = Field(default=None, sa_column=Column(Boolean(), server_default="0"))
13+
is_mutual: bool | None = Field(
14+
default=None, sa_column=Column(Boolean(), server_default="0")
15+
)

backend/app/app/schemas/common_schema.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class TokenType(str, Enum):
2828
class IUserMessage(BaseModel):
2929
"""User message schema."""
3030

31-
user_id: UUID | None
31+
user_id: UUID | None = None
3232
message: str
3333

3434

backend/app/app/schemas/hero_schema.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77

88
class IHeroCreate(HeroBase):
9-
@field_validator('age')
9+
@field_validator("age")
1010
def check_age(cls, value):
1111
if value < 0:
1212
raise ValueError("Invalid age")

backend/app/app/schemas/image_media_schema.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from app.models.image_media_model import ImageMedia, ImageMediaBase
22
from app.models.media_model import Media
3-
from pydantic import model_validator, root_validator
3+
from pydantic import model_validator
44
from .media_schema import IMediaRead
55
from app.utils.partial import optional
66

@@ -20,11 +20,11 @@ class IImageMediaRead(ImageMediaBase):
2020
media: IMediaRead | None
2121

2222

23-
#Todo make it compatible with pydantic v2
23+
# Todo make it compatible with pydantic v2
2424
class IImageMediaReadCombined(ImageMediaBase):
2525
link: str | None
2626

27-
@model_validator(mode='before')
27+
@model_validator(mode="before")
2828
def combine_attributes(cls, values):
2929
link_fields = {"link": values.get("link", None)}
3030
if "media" in values:

backend/app/app/schemas/team_schema.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from typing import Any
21
from app.models.hero_model import HeroBase
32
from app.models.team_model import TeamBase
43
from .user_schema import IUserBasicInfo

backend/app/app/schemas/user_schema.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from pydantic import BaseModel
55
from uuid import UUID
66
from enum import Enum
7-
from .image_media_schema import IImageMediaReadCombined, IImageMediaRead
7+
from .image_media_schema import IImageMediaRead
88
from .role_schema import IRoleRead
99

1010

backend/app/app/utils/partial.py

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# https://github.com/pydantic/pydantic/pull/3179
33
# https://github.com/pydantic/pydantic/issues/1673
44

5-
from pydantic import BaseModel
65
from copy import deepcopy
76
from typing import Any, Callable, Optional, Type, TypeVar
87
from pydantic import BaseModel, create_model

docker-compose-dev.yml

+6-6
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,22 @@ services:
1818
- caddy_reverse_proxy:storage.localhost
1919

2020
database:
21-
image: bitnami/postgresql:13.3.0
21+
image: bitnami/postgresql
2222
restart: always
2323
container_name: database
2424
env_file: ".env"
2525
user: root
2626
volumes:
27-
- ./db_docker:/bitnami/postgresql
27+
- db_docker:/bitnami/postgresql
2828
- ./create-dbs.sql:/docker-entrypoint-initdb.d/create-dbs.sql
2929
ports:
3030
- 5454:5432 # Remove this on production
3131
expose:
3232
- 5432
3333
environment:
34-
- POSTGRES_USERNAME=${DATABASE_USER}
35-
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
36-
- POSTGRES_DATABASE=${DATABASE_NAME}
37-
- POSTGRES_HOST_AUTH_METHOD= "trust"
34+
- POSTGRESQL_USERNAME=${DATABASE_USER}
35+
- POSTGRESQL_PASSWORD=${DATABASE_PASSWORD}
36+
- POSTGRESQL_DATABASE=${DATABASE_NAME}
3837

3938
redis_server:
4039
image: redis:alpine
@@ -108,5 +107,6 @@ services:
108107
- caddy_config:/config
109108

110109
volumes:
110+
db_docker:
111111
caddy_data:
112112
caddy_config:

docker-compose-sonarqube.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version: "3.9"
33
services:
44
sonarqube:
55
container_name: "sonarqube"
6-
image: "sonarqube:9.9.1-community"
6+
image: "sonarqube:9.9.2-community"
77
volumes:
88
- ./sonarqube/extensions:/opt/sonarqube/extensions
99
- ./sonarqube/logs:/opt/sonarqube/logs

docker-compose-test.yml

+7-10
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,22 @@ services:
2222
- caddy_reverse_proxy:storage.localhost
2323

2424
database:
25-
image: bitnami/postgresql:13.3.0
25+
image: bitnami/postgresql
2626
restart: always
2727
container_name: database
2828
env_file: ".env"
2929
user: root
3030
volumes:
31-
- ./db_docker:/bitnami/postgresql
31+
- db_docker:/bitnami/postgresql
3232
- ./create-dbs.sql:/docker-entrypoint-initdb.d/create-dbs.sql
3333
ports:
3434
- 5454:5432 # Remove this on production
3535
expose:
3636
- 5432
3737
environment:
38-
- POSTGRES_USERNAME=${DATABASE_USER}
39-
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
40-
- POSTGRES_DATABASE=${DATABASE_NAME}
41-
- POSTGRES_HOST_AUTH_METHOD= "trust"
38+
- POSTGRESQL_USERNAME=${DATABASE_USER}
39+
- POSTGRESQL_PASSWORD=${DATABASE_PASSWORD}
40+
- POSTGRESQL_DATABASE=${DATABASE_NAME}
4241

4342
redis_server:
4443
image: redis:alpine
@@ -52,10 +51,7 @@ services:
5251
container_name: celery_worker
5352
restart: always
5453
# platform: linux/arm64/v8
55-
build:
56-
context: ./backend
57-
args:
58-
INSTALL_DEV: "true"
54+
build: ./backend
5955
command: "watchfiles 'celery -A app.core.celery worker -l info' "
6056
volumes:
6157
- ./backend/app:/code
@@ -115,5 +111,6 @@ services:
115111
- caddy_config:/config
116112

117113
volumes:
114+
db_docker:
118115
caddy_data:
119116
caddy_config:

0 commit comments

Comments
 (0)