server: refactor to reflector module

- replaced loguru to structlog, to get ability of having open tracing later
- moved configuration to pydantic-settings
- merged both secrets.ini and config.ini to .env (check reflector/settings.py)
This commit is contained in:
Mathieu Virbel
2023-07-27 15:29:41 +02:00
parent 094ed696c4
commit 69ba871481
24 changed files with 385 additions and 283 deletions

1
.env Normal file
View File

@@ -0,0 +1 @@
LLM_URL=http://216.153.52.83:7860/api/v1/generate

View File

@@ -24,7 +24,6 @@ RUN . /venv/bin/activate && poetry install --only main --no-root --no-interactio
FROM base AS final FROM base AS final
COPY --from=builder /venv /venv COPY --from=builder /venv /venv
RUN mkdir -p /app RUN mkdir -p /app
COPY server.py reflector_dataclasses.py /app/ COPY reflector /app/reflector
COPY utils /app/utils
WORKDIR /app WORKDIR /app
CMD ["/venv/bin/python", "server.py"] CMD ["/venv/bin/python", "-m", "reflector.server"]

View File

@@ -33,12 +33,12 @@ Then run the server:
``` ```
# With a config.ini # With a config.ini
$ poetry run python server.py $ poetry run python -m reflector.server
# Within a poetry env # Within a poetry env
$ poetry shell $ poetry shell
$ LLM_URL=http://.../api/v1/generate python server.py $ LLM_URL=http://.../api/v1/generate python -m reflector.server
``` ```

View File

@@ -1,61 +0,0 @@
pyaudio==0.2.13
keyboard==0.13.5
pynput==1.7.6
wave==0.0.2
async-timeout==4.0.2
attrs==23.1.0
certifi==2023.5.7
charset-normalizer==3.1.0
decorator==4.4.2
filelock==3.12.0
frozenlist==1.3.3
idna==3.4
imageio==2.29.0
imageio-ffmpeg==0.4.8
Jinja2==3.1.2
llvmlite==0.40.0
loguru==0.7.0
MarkupSafe==2.1.2
more-itertools==9.1.0
moviepy==1.0.3
mpmath==1.3.0
multidict==6.0.4
networkx==3.1
numba==0.57.0
numpy==1.24.3
openai==0.27.7
openai-whisper@ git+https://github.com/openai/whisper.git@248b6cb124225dd263bb9bd32d060b6517e067f8
Pillow==9.5.0
proglog==0.1.10
pytube==15.0.0
regex==2023.5.5
six==1.16.0
sympy==1.12
tiktoken==0.3.3
torch==2.0.1
tqdm==4.65.0
typing_extensions==4.6.2
urllib3
yarl==1.9.2
boto3==1.26.151
nltk==3.8.1
wordcloud==1.9.2
spacy==3.5.4
scattertext==0.1.19
pandas==2.0.3
jupyter==1.0.0
seaborn==0.12.2
matplotlib==3.7.2
matplotlib-inline==0.1.6
termcolor==2.3.0
ffmpeg==1.4
cached_property==1.5.2
stamina==23.1.0
httpx==0.24.1
https://github.com/yt-dlp/yt-dlp/archive/master.tar.gz
gpt4all==1.0.5
aiohttp==3.8.5
aiohttp-cors==0.7.0
aioice==0.9.0
aiortc==1.5.0
aiosignal==1.3.1

271
server/poetry.lock generated
View File

@@ -223,6 +223,17 @@ files = [
[package.dependencies] [package.dependencies]
frozenlist = ">=1.1.0" frozenlist = ">=1.1.0"
[[package]]
name = "annotated-types"
version = "0.5.0"
description = "Reusable constraint types to use with typing.Annotated"
optional = false
python-versions = ">=3.7"
files = [
{file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"},
{file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"},
]
[[package]] [[package]]
name = "anyio" name = "anyio"
version = "3.7.1" version = "3.7.1"
@@ -952,6 +963,29 @@ sniffio = "==1.*"
http2 = ["h2 (>=3,<5)"] http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"] socks = ["socksio (==1.*)"]
[[package]]
name = "httpx"
version = "0.24.1"
description = "The next generation HTTP client."
optional = false
python-versions = ">=3.7"
files = [
{file = "httpx-0.24.1-py3-none-any.whl", hash = "sha256:06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd"},
{file = "httpx-0.24.1.tar.gz", hash = "sha256:5853a43053df830c20f8110c5e69fe44d035d850b2dfe795e196f00fdb774bdd"},
]
[package.dependencies]
certifi = "*"
httpcore = ">=0.15.0,<0.18.0"
idna = "*"
sniffio = "*"
[package.extras]
brotli = ["brotli", "brotlicffi"]
cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"]
[[package]] [[package]]
name = "huggingface-hub" name = "huggingface-hub"
version = "0.16.4" version = "0.16.4"
@@ -1283,6 +1317,29 @@ files = [
{file = "protobuf-4.23.4.tar.gz", hash = "sha256:ccd9430c0719dce806b93f89c91de7977304729e55377f872a92465d548329a9"}, {file = "protobuf-4.23.4.tar.gz", hash = "sha256:ccd9430c0719dce806b93f89c91de7977304729e55377f872a92465d548329a9"},
] ]
[[package]]
name = "pyaudio"
version = "0.2.13"
description = "Cross-platform audio I/O with PortAudio"
optional = false
python-versions = "*"
files = [
{file = "PyAudio-0.2.13-cp310-cp310-win32.whl", hash = "sha256:48e29537ea22ae2ae323eebe297bfb2683831cee4f20d96964e131f65ab2161d"},
{file = "PyAudio-0.2.13-cp310-cp310-win_amd64.whl", hash = "sha256:87137cfd0ef8608a2a383be3f6996f59505e322dab9d16531f14cf542fa294f1"},
{file = "PyAudio-0.2.13-cp311-cp311-win32.whl", hash = "sha256:13915faaa780e6bbbb6d745ef0e761674fd461b1b1b3f9c1f57042a534bfc0c3"},
{file = "PyAudio-0.2.13-cp311-cp311-win_amd64.whl", hash = "sha256:59cc3cc5211b729c7854e3989058a145872cc58b1a7b46c6d4d88448a343d890"},
{file = "PyAudio-0.2.13-cp37-cp37m-win32.whl", hash = "sha256:d294e3f85b2238649b1ff49ce3412459a8a312569975a89d14646536362d7576"},
{file = "PyAudio-0.2.13-cp37-cp37m-win_amd64.whl", hash = "sha256:ff7f5e44ef51fe61da1e09c6f632f0b5808198edd61b363855cc7dd03bf4a8ac"},
{file = "PyAudio-0.2.13-cp38-cp38-win32.whl", hash = "sha256:c6b302b048c054b7463936d8ba884b73877dc47012f3c94665dba92dd658ae04"},
{file = "PyAudio-0.2.13-cp38-cp38-win_amd64.whl", hash = "sha256:1505d766ee718df6f5a18b73ac42307ba1cb4d2c0397873159254a34f67515d6"},
{file = "PyAudio-0.2.13-cp39-cp39-win32.whl", hash = "sha256:eb128e4a6ea9b98d9a31f33c44978885af27dbe8ae53d665f8790cbfe045517e"},
{file = "PyAudio-0.2.13-cp39-cp39-win_amd64.whl", hash = "sha256:910ef09225cce227adbba92622d4a3e3c8375117f7dd64039f287d9ffc0e02a1"},
{file = "PyAudio-0.2.13.tar.gz", hash = "sha256:26bccc81e4243d1c0ff5487e6b481de6329fcd65c79365c267cef38f363a2b56"},
]
[package.extras]
test = ["numpy"]
[[package]] [[package]]
name = "pycparser" name = "pycparser"
version = "2.21" version = "2.21"
@@ -1294,6 +1351,153 @@ files = [
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
] ]
[[package]]
name = "pydantic"
version = "2.1.1"
description = "Data validation using Python type hints"
optional = false
python-versions = ">=3.7"
files = [
{file = "pydantic-2.1.1-py3-none-any.whl", hash = "sha256:43bdbf359d6304c57afda15c2b95797295b702948082d4c23851ce752f21da70"},
{file = "pydantic-2.1.1.tar.gz", hash = "sha256:22d63db5ce4831afd16e7c58b3192d3faf8f79154980d9397d9867254310ba4b"},
]
[package.dependencies]
annotated-types = ">=0.4.0"
pydantic-core = "2.4.0"
typing-extensions = ">=4.6.1"
[package.extras]
email = ["email-validator (>=2.0.0)"]
[[package]]
name = "pydantic-core"
version = "2.4.0"
description = ""
optional = false
python-versions = ">=3.7"
files = [
{file = "pydantic_core-2.4.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:2ca4687dd996bde7f3c420def450797feeb20dcee2b9687023e3323c73fc14a2"},
{file = "pydantic_core-2.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:782fced7d61469fd1231b184a80e4f2fa7ad54cd7173834651a453f96f29d673"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6213b471b68146af97b8551294e59e7392c2117e28ffad9c557c65087f4baee3"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63797499a219d8e81eb4e0c42222d0a4c8ec896f5c76751d4258af95de41fdf1"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_24_armv7l.whl", hash = "sha256:0455876d575a35defc4da7e0a199596d6c773e20d3d42fa1fc29f6aa640369ed"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:8c938c96294d983dcf419b54dba2d21056959c22911d41788efbf949a29ae30d"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_24_s390x.whl", hash = "sha256:878a5017d93e776c379af4e7b20f173c82594d94fa073059bcc546789ad50bf8"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:69159afc2f2dc43285725f16143bc5df3c853bc1cb7df6021fce7ef1c69e8171"},
{file = "pydantic_core-2.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54df7df399b777c1fd144f541c95d351b3aa110535a6810a6a569905d106b6f3"},
{file = "pydantic_core-2.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e412607ca89a0ced10758dfb8f9adcc365ce4c1c377e637c01989a75e9a9ec8a"},
{file = "pydantic_core-2.4.0-cp310-none-win32.whl", hash = "sha256:853f103e2b9a58832fdd08a587a51de8b552ae90e1a5d167f316b7eabf8d7dde"},
{file = "pydantic_core-2.4.0-cp310-none-win_amd64.whl", hash = "sha256:3ba2c9c94a9176f6321a879c8b864d7c5b12d34f549a4c216c72ce213d7d953c"},
{file = "pydantic_core-2.4.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:a8b7acd04896e8f161e1500dc5f218017db05c1d322f054e89cbd089ce5d0071"},
{file = "pydantic_core-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:16468bd074fa4567592d3255bf25528ed41e6b616d69bf07096bdb5b66f947d1"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cba5ad5eef02c86a1f3da00544cbc59a510d596b27566479a7cd4d91c6187a11"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7206e41e04b443016e930e01685bab7a308113c0b251b3f906942c8d4b48fcb"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_24_armv7l.whl", hash = "sha256:c1375025f0bfc9155286ebae8eecc65e33e494c90025cda69e247c3ccd2bab00"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_24_ppc64le.whl", hash = "sha256:3534118289e33130ed3f1cc487002e8d09b9f359be48b02e9cd3de58ce58fba9"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_24_s390x.whl", hash = "sha256:94d2b36a74623caab262bf95f0e365c2c058396082bd9d6a9e825657d0c1e7fa"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:af24ad4fbaa5e4a2000beae0c3b7fd1c78d7819ab90f9370a1cfd8998e3f8a3c"},
{file = "pydantic_core-2.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bf10963d8aed8bbe0165b41797c9463d4c5c8788ae6a77c68427569be6bead41"},
{file = "pydantic_core-2.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68199ada7c310ddb8c76efbb606a0de656b40899388a7498954f423e03fc38be"},
{file = "pydantic_core-2.4.0-cp311-none-win32.whl", hash = "sha256:6f855bcc96ed3dd56da7373cfcc9dcbabbc2073cac7f65c185772d08884790ce"},
{file = "pydantic_core-2.4.0-cp311-none-win_amd64.whl", hash = "sha256:de39eb3bab93a99ddda1ac1b9aa331b944d8bcc4aa9141148f7fd8ee0299dafc"},
{file = "pydantic_core-2.4.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:f773b39780323a0499b53ebd91a28ad11cde6705605d98d999dfa08624caf064"},
{file = "pydantic_core-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a297c0d6c61963c5c3726840677b798ca5b7dfc71bc9c02b9a4af11d23236008"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:546064c55264156b973b5e65e5fafbe5e62390902ce3cf6b4005765505e8ff56"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36ba9e728588588f0196deaf6751b9222492331b5552f865a8ff120869d372e0"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_24_armv7l.whl", hash = "sha256:57a53a75010c635b3ad6499e7721eaa3b450e03f6862afe2dbef9c8f66e46ec8"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_24_ppc64le.whl", hash = "sha256:4b262bbc13022f2097c48a21adcc360a81d83dc1d854c11b94953cd46d7d3c07"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_24_s390x.whl", hash = "sha256:01947ad728f426fa07fcb26457ebf90ce29320259938414bc0edd1476e75addb"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b2799c2eaf182769889761d4fb4d78b82bc47dae833799fedbf69fc7de306faa"},
{file = "pydantic_core-2.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a08fd490ba36d1fbb2cd5dcdcfb9f3892deb93bd53456724389135712b5fc735"},
{file = "pydantic_core-2.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1e8a7c62d15a5c4b307271e4252d76ebb981d6251c6ecea4daf203ef0179ea4f"},
{file = "pydantic_core-2.4.0-cp312-none-win32.whl", hash = "sha256:9206c14a67c38de7b916e486ae280017cf394fa4b1aa95cfe88621a4e1d79725"},
{file = "pydantic_core-2.4.0-cp312-none-win_amd64.whl", hash = "sha256:884235507549a6b2d3c4113fb1877ae263109e787d9e0eb25c35982ab28d0399"},
{file = "pydantic_core-2.4.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:4cbe929efa77a806e8f1a97793f2dc3ea3475ae21a9ed0f37c21320fe93f6f50"},
{file = "pydantic_core-2.4.0-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:9137289de8fe845c246a8c3482dd0cb40338846ba683756d8f489a4bd8fddcae"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5d8e764b5646623e57575f624f8ebb8f7a9f7fd1fae682ef87869ca5fec8dcf"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fba0aff4c407d0274e43697e785bcac155ad962be57518d1c711f45e72da70f"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_24_armv7l.whl", hash = "sha256:30527d173e826f2f7651f91c821e337073df1555e3b5a0b7b1e2c39e26e50678"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:bd7d1dde70ff3e09e4bc7a1cbb91a7a538add291bfd5b3e70ef1e7b45192440f"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_24_s390x.whl", hash = "sha256:72f1216ca8cef7b8adacd4c4c6b89c3b0c4f97503197f5284c80f36d6e4edd30"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b013c7861a7c7bfcec48fd709513fea6f9f31727e7a0a93ca0dd12e056740717"},
{file = "pydantic_core-2.4.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:478f5f6d7e32bd4a04d102160efb2d389432ecf095fe87c555c0a6fc4adfc1a4"},
{file = "pydantic_core-2.4.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d9610b47b5fe4aacbbba6a9cb5f12cbe864eec99dbfed5710bd32ef5dd8a5d5b"},
{file = "pydantic_core-2.4.0-cp37-none-win32.whl", hash = "sha256:ff246c0111076c8022f9ba325c294f2cb5983403506989253e04dbae565e019b"},
{file = "pydantic_core-2.4.0-cp37-none-win_amd64.whl", hash = "sha256:d0c2b713464a8e263a243ae7980d81ce2de5ac59a9f798a282e44350b42dc516"},
{file = "pydantic_core-2.4.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:12ef6838245569fd60a179fade81ca4b90ae2fa0ef355d616f519f7bb27582db"},
{file = "pydantic_core-2.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49db206eb8fdc4b4f30e6e3e410584146d813c151928f94ec0db06c4f2595538"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a507d7fa44688bbac76af6521e488b3da93de155b9cba6f2c9b7833ce243d59"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffe18407a4d000c568182ce5388bbbedeb099896904e43fc14eee76cfae6dec5"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_24_armv7l.whl", hash = "sha256:fa8e48001b39d54d97d7b380a0669fa99fc0feeb972e35a2d677ba59164a9a22"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:394f12a2671ff8c4dfa2e85be6c08be0651ad85bc1e6aa9c77c21671baaf28cd"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_24_s390x.whl", hash = "sha256:2f9ea0355f90db2a76af530245fa42f04d98f752a1236ed7c6809ec484560d5b"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:61d4e713f467abcdd59b47665d488bb898ad3dd47ce7446522a50e0cbd8e8279"},
{file = "pydantic_core-2.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:453862ab268f6326b01f067ed89cb3a527d34dc46f6f4eeec46a15bbc706d0da"},
{file = "pydantic_core-2.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:56a85fa0dab1567bd0cac10f0c3837b03e8a0d939e6a8061a3a420acd97e9421"},
{file = "pydantic_core-2.4.0-cp38-none-win32.whl", hash = "sha256:0d726108c1c0380b88b6dd4db559f0280e0ceda9e077f46ff90bc85cd4d03e77"},
{file = "pydantic_core-2.4.0-cp38-none-win_amd64.whl", hash = "sha256:047580388644c473b934d27849f8ed8dbe45df0adb72104e78b543e13bf69762"},
{file = "pydantic_core-2.4.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:867d3eea954bea807cabba83cfc939c889a18576d66d197c60025b15269d7cc0"},
{file = "pydantic_core-2.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:664402ef0c238a7f8a46efb101789d5f2275600fb18114446efec83cfadb5b66"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64e8012ad60a5f0da09ed48725e6e923d1be25f2f091a640af6079f874663813"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac2b680de398f293b68183317432b3d67ab3faeba216aec18de0c395cb5e3060"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_24_armv7l.whl", hash = "sha256:8efc1be43b036c2b6bcfb1451df24ee0ddcf69c31351003daf2699ed93f5687b"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:d93aedbc4614cc21b9ab0d0c4ccd7143354c1f7cffbbe96ae5216ad21d1b21b5"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_24_s390x.whl", hash = "sha256:af788b64e13d52fc3600a68b16d31fa8d8573e3ff2fc9a38f8a60b8d94d1f012"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97c6349c81cee2e69ef59eba6e6c08c5936e6b01c2d50b9e4ac152217845ae09"},
{file = "pydantic_core-2.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cc086ddb6dc654a15deeed1d1f2bcb1cb924ebd70df9dca738af19f64229b06c"},
{file = "pydantic_core-2.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e953353180bec330c3b830891d260b6f8e576e2d18db3c78d314e56bb2276066"},
{file = "pydantic_core-2.4.0-cp39-none-win32.whl", hash = "sha256:6feb4b64d11d5420e517910d60a907d08d846cacaf4e029668725cd21d16743c"},
{file = "pydantic_core-2.4.0-cp39-none-win_amd64.whl", hash = "sha256:153a61ac4030fa019b70b31fb7986461119230d3ba0ab661c757cfea652f4332"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3fcf529382b282a30b466bd7af05be28e22aa620e016135ac414f14e1ee6b9e1"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2edef05b63d82568b877002dc4cb5cc18f8929b59077120192df1e03e0c633f8"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da055a1b0bfa8041bb2ff586b2cb0353ed03944a3472186a02cc44a557a0e661"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:77dadc764cf7c5405e04866181c5bd94a447372a9763e473abb63d1dfe9b7387"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a4ea23b07f29487a7bef2a869f68c7ee0e05424d81375ce3d3de829314c6b5ec"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:382f0baa044d674ad59455a5eff83d7965572b745cc72df35c52c2ce8c731d37"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:08f89697625e453421401c7f661b9d1eb4c9e4c0a12fd256eeb55b06994ac6af"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:43a405ce520b45941df9ff55d0cd09762017756a7b413bbad3a6e8178e64a2c2"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:584a7a818c84767af16ce8bda5d4f7fedb37d3d231fc89928a192f567e4ef685"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04922fea7b13cd480586fa106345fe06e43220b8327358873c22d8dfa7a711c7"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17156abac20a9feed10feec867fddd91a80819a485b0107fe61f09f2117fe5f3"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4e562cc63b04636cde361fd47569162f1daa94c759220ff202a8129902229114"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:90f3785146f701e053bb6b9e8f53acce2c919aca91df88bd4975be0cb926eb41"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:e40b1e97edd3dc127aa53d8a5e539a3d0c227d71574d3f9ac1af02d58218a122"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:b27f3e67f6e031f6620655741b7d0d6bebea8b25d415924b3e8bfef2dd7bd841"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be86c2eb12fb0f846262ace9d8f032dc6978b8cb26a058920ecb723dbcb87d05"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4665f7ed345012a8d2eddf4203ef145f5f56a291d010382d235b94e91813f88a"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:79262be5a292d1df060f29b9a7cdd66934801f987a817632d7552534a172709a"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5fd905a69ac74eaba5041e21a1e8b1a479dab2b41c93bdcc4c1cede3c12a8d86"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:2ad538b7e07343001934417cdc8584623b4d8823c5b8b258e75ec8d327cec969"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:dd2429f7635ad4857b5881503f9c310be7761dc681c467a9d27787b674d1250a"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:efff8b6761a1f6e45cebd1b7a6406eb2723d2d5710ff0d1b624fe11313693989"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32a1e0352558cd7ccc014ffe818c7d87b15ec6145875e2cc5fa4bb7351a1033d"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a027f41c5008571314861744d83aff75a34cf3a07022e0be32b214a5bc93f7f1"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1927f0e15d190f11f0b8344373731e28fd774c6d676d8a6cfadc95c77214a48b"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7aa82d483d5fb867d4fb10a138ffd57b0f1644e99f2f4f336e48790ada9ada5e"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b85778308bf945e9b33ac604e6793df9b07933108d20bdf53811bc7c2798a4af"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3ded19dcaefe2f6706d81e0db787b59095f4ad0fbadce1edffdf092294c8a23f"},
{file = "pydantic_core-2.4.0.tar.gz", hash = "sha256:ec3473c9789cc00c7260d840c3db2c16dbfc816ca70ec87a00cddfa3e1a1cdd5"},
]
[package.dependencies]
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
[[package]]
name = "pydantic-settings"
version = "2.0.2"
description = "Settings management using Pydantic"
optional = false
python-versions = ">=3.7"
files = [
{file = "pydantic_settings-2.0.2-py3-none-any.whl", hash = "sha256:6183a2abeab465d5a3ab69758e9a22d38b0cc2ba193f0b85f6971a252ea630f6"},
{file = "pydantic_settings-2.0.2.tar.gz", hash = "sha256:342337fff50b23585e807a86dec85037900972364435c55c2fc00d16ff080539"},
]
[package.dependencies]
pydantic = ">=2.0.1"
python-dotenv = ">=0.21.0"
[[package]] [[package]]
name = "pyee" name = "pyee"
version = "11.0.0" version = "11.0.0"
@@ -1402,6 +1606,20 @@ files = [
{file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"},
] ]
[[package]]
name = "python-dotenv"
version = "1.0.0"
description = "Read key-value pairs from a .env file and set them as environment variables"
optional = false
python-versions = ">=3.8"
files = [
{file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"},
{file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"},
]
[package.extras]
cli = ["click (>=5.0)"]
[[package]] [[package]]
name = "pyyaml" name = "pyyaml"
version = "6.0.1" version = "6.0.1"
@@ -1494,6 +1712,43 @@ files = [
{file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"},
] ]
[[package]]
name = "stamina"
version = "23.1.0"
description = "Production-grade retries made easy."
optional = false
python-versions = ">=3.8"
files = [
{file = "stamina-23.1.0-py3-none-any.whl", hash = "sha256:850de8c2c2469aabf42a4c02e7372eaa12c2eced78f2bfa34162b8676c2846e5"},
{file = "stamina-23.1.0.tar.gz", hash = "sha256:b16ce3d52d658aa75db813fc6a6661b770abfea915f72cda48e325f2a7854786"},
]
[package.dependencies]
tenacity = "*"
[package.extras]
dev = ["nox", "prometheus-client", "stamina[tests,typing]", "structlog", "tomli"]
docs = ["furo", "myst-parser", "prometheus-client", "sphinx", "sphinx-notfound-page", "structlog"]
tests = ["pytest", "pytest-asyncio"]
typing = ["mypy (>=1.4)"]
[[package]]
name = "structlog"
version = "23.1.0"
description = "Structured Logging for Python"
optional = false
python-versions = ">=3.7"
files = [
{file = "structlog-23.1.0-py3-none-any.whl", hash = "sha256:79b9e68e48b54e373441e130fa447944e6f87a05b35de23138e475c05d0f7e0e"},
{file = "structlog-23.1.0.tar.gz", hash = "sha256:270d681dd7d163c11ba500bc914b2472d2b50a8ef00faa999ded5ff83a2f906b"},
]
[package.extras]
dev = ["structlog[docs,tests,typing]"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "twisted"]
tests = ["coverage[toml]", "freezegun (>=0.2.8)", "pretend", "pytest (>=6.0)", "pytest-asyncio (>=0.17)", "simplejson"]
typing = ["mypy", "rich", "twisted"]
[[package]] [[package]]
name = "sympy" name = "sympy"
version = "1.12" version = "1.12"
@@ -1508,6 +1763,20 @@ files = [
[package.dependencies] [package.dependencies]
mpmath = ">=0.19" mpmath = ">=0.19"
[[package]]
name = "tenacity"
version = "8.2.2"
description = "Retry code until it succeeds"
optional = false
python-versions = ">=3.6"
files = [
{file = "tenacity-8.2.2-py3-none-any.whl", hash = "sha256:2f277afb21b851637e8f52e6a613ff08734c347dc19ade928e519d7d2d8569b0"},
{file = "tenacity-8.2.2.tar.gz", hash = "sha256:43af037822bd0029025877f3b2d97cc4d7bb0c2991000a3d59d71517c5c969e0"},
]
[package.extras]
doc = ["reno", "sphinx", "tornado (>=4.5)"]
[[package]] [[package]]
name = "tokenizers" name = "tokenizers"
version = "0.13.3" version = "0.13.3"
@@ -1714,4 +1983,4 @@ multidict = ">=4.0"
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.11" python-versions = "^3.11"
content-hash = "e8eb6b4f81c090adb882a1b293d81f32167ea89f4636222d43fe0e9131cb97d6" content-hash = "32981f838c232fdf2274aadbc933ef107c820d053bc9c2ceec563b2a22c1ea4c"

View File

@@ -16,11 +16,19 @@ aiortc = "^1.5.0"
faster-whisper = "^0.7.1" faster-whisper = "^0.7.1"
sortedcontainers = "^2.4.0" sortedcontainers = "^2.4.0"
loguru = "^0.7.0" loguru = "^0.7.0"
pydantic-settings = "^2.0.2"
structlog = "^23.1.0"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
black = "^23.7.0" black = "^23.7.0"
[tool.poetry.group.client.dependencies]
httpx = "^0.24.1"
pyaudio = "^0.2.13"
stamina = "^23.1.0"
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api" build-backend = "poetry.core.masonry.api"

View File

@@ -4,8 +4,8 @@ import signal
from aiortc.contrib.signaling import add_signaling_arguments, create_signaling from aiortc.contrib.signaling import add_signaling_arguments, create_signaling
from utils.log_utils import LOGGER from reflector.logger import logger
from stream_client import StreamClient from reflector.stream_client import StreamClient
from typing import NoReturn from typing import NoReturn
@@ -42,16 +42,16 @@ async def main() -> NoReturn:
async def shutdown(signal, loop): async def shutdown(signal, loop):
"""Cleanup tasks tied to the service's shutdown.""" """Cleanup tasks tied to the service's shutdown."""
LOGGER.info(f"Received exit signal {signal.name}...") logger.info(f"Received exit signal {signal.name}...")
LOGGER.info("Closing database connections") logger.info("Closing database connections")
LOGGER.info("Nacking outstanding messages") logger.info("Nacking outstanding messages")
tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()] tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
[task.cancel() for task in tasks] [task.cancel() for task in tasks]
LOGGER.info(f"Cancelling {len(tasks)} outstanding tasks") logger.info(f"Cancelling {len(tasks)} outstanding tasks")
await asyncio.gather(*tasks, return_exceptions=True) await asyncio.gather(*tasks, return_exceptions=True)
LOGGER.info(f'{"Flushing metrics"}') logger.info(f'{"Flushing metrics"}')
loop.stop() loop.stop()
signals = (signal.SIGHUP, signal.SIGTERM, signal.SIGINT) signals = (signal.SIGHUP, signal.SIGTERM, signal.SIGINT)

View File

@@ -0,0 +1,3 @@
import structlog
logger = structlog.get_logger()

View File

@@ -198,10 +198,12 @@ class TranscriptionContext:
incremental_responses: List[IncrementalResult] incremental_responses: List[IncrementalResult]
sorted_transcripts: dict sorted_transcripts: dict
data_channel: None # FIXME data_channel: None # FIXME
logger: None
def __init__(self): def __init__(self, logger):
self.transcription_text = "" self.transcription_text = ""
self.last_transcribed_time = 0.0 self.last_transcribed_time = 0.0
self.incremental_responses = [] self.incremental_responses = []
self.data_channel = None self.data_channel = None
self.sorted_transcripts = SortedDict() self.sorted_transcripts = SortedDict()
self.logger = logger

View File

@@ -3,8 +3,8 @@ import asyncio
import datetime import datetime
import json import json
import os import os
import uuid
import wave import wave
import uuid
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from typing import NoReturn, Union from typing import NoReturn, Union
@@ -16,7 +16,7 @@ from aiortc import MediaStreamTrack, RTCPeerConnection, RTCSessionDescription
from aiortc.contrib.media import MediaRelay from aiortc.contrib.media import MediaRelay
from faster_whisper import WhisperModel from faster_whisper import WhisperModel
from reflector_dataclasses import ( from reflector.models import (
BlackListedMessages, BlackListedMessages,
FinalSummaryResult, FinalSummaryResult,
ParseLLMResult, ParseLLMResult,
@@ -26,8 +26,9 @@ from reflector_dataclasses import (
TranscriptionOutput, TranscriptionOutput,
TranscriptionContext, TranscriptionContext,
) )
from utils.log_utils import LOGGER from reflector.logger import logger
from utils.run_utils import CONFIG, run_in_executor, SECRETS from reflector.utils.run_utils import run_in_executor
from reflector.settings import settings
# WebRTC components # WebRTC components
pcs = set() pcs = set()
@@ -37,19 +38,12 @@ executor = ThreadPoolExecutor()
# Transcription model # Transcription model
model = WhisperModel("tiny", device="cpu", compute_type="float32", num_workers=12) model = WhisperModel("tiny", device="cpu", compute_type="float32", num_workers=12)
# Audio configurations
CHANNELS = int(CONFIG["AUDIO"]["CHANNELS"])
RATE = int(CONFIG["AUDIO"]["SAMPLING_RATE"])
AUDIO_BUFFER_SIZE = 256 * 960
# LLM # LLM
LLM_URL = os.environ.get("LLM_URL") LLM_URL = settings.LLM_URL
if LLM_URL: if not LLM_URL:
LOGGER.info(f"Using LLM from environment: {LLM_URL}") assert settings.LLM_BACKEND == "oobagooda"
else: LLM_URL = f"http://{settings.LLM_HOST}:{settings.LLM_PORT}/api/v1/generate"
LLM_MACHINE_IP = CONFIG["LLM"]["LLM_MACHINE_IP"] logger.info(f"Using LLM [{settings.LLM_BACKEND}]: {LLM_URL}")
LLM_MACHINE_PORT = CONFIG["LLM"]["LLM_MACHINE_PORT"]
LLM_URL = f"http://{LLM_MACHINE_IP}:{LLM_MACHINE_PORT}/api/v1/generate"
def parse_llm_output( def parse_llm_output(
@@ -64,8 +58,8 @@ def parse_llm_output(
try: try:
output = json.loads(response.json()["results"][0]["text"]) output = json.loads(response.json()["results"][0]["text"])
return ParseLLMResult(param, output) return ParseLLMResult(param, output)
except Exception as e: except Exception:
LOGGER.info("Exception" + str(e)) logger.exception("Exception while parsing LLM output")
return None return None
@@ -78,7 +72,7 @@ def get_title_and_summary(
:param param: :param param:
:return: :return:
""" """
LOGGER.info("Generating title and summary") logger.info("Generating title and summary")
# TODO : Handle unexpected output formats from the model # TODO : Handle unexpected output formats from the model
try: try:
@@ -89,21 +83,10 @@ def get_title_and_summary(
ctx.incremental_responses.append(result) ctx.incremental_responses.append(result)
return TitleSummaryOutput(ctx.incremental_responses) return TitleSummaryOutput(ctx.incremental_responses)
except Exception: except Exception:
LOGGER.exception("Exception while generating title and summary") logger.exception("Exception while generating title and summary")
return None return None
def channel_log(channel, t: str, message: str) -> NoReturn:
"""
Add logs
:param channel:
:param t:
:param message:
:return:
"""
LOGGER.info("channel(%s) %s %s" % (channel.label, t, message))
def channel_send(channel, message: str) -> NoReturn: def channel_send(channel, message: str) -> NoReturn:
""" """
Send text messages via the data channel Send text messages via the data channel
@@ -135,7 +118,6 @@ def channel_send_transcript(ctx: TranscriptionContext) -> NoReturn:
:param channel: :param channel:
:return: :return:
""" """
# channel_log(channel, ">", message)
if not ctx.data_channel: if not ctx.data_channel:
return return
try: try:
@@ -151,8 +133,8 @@ def channel_send_transcript(ctx: TranscriptionContext) -> NoReturn:
else: else:
if len(ctx.sorted_transcripts) >= 3: if len(ctx.sorted_transcripts) >= 3:
del ctx.sorted_transcripts[least_time] del ctx.sorted_transcripts[least_time]
except Exception as exception: except Exception:
LOGGER.info("Exception", str(exception)) logger.exception("Exception while sending transcript")
def get_transcription( def get_transcription(
@@ -164,7 +146,7 @@ def get_transcription(
:param input_frames: :param input_frames:
:return: :return:
""" """
LOGGER.info("Transcribing..") ctx.logger.info("Transcribing..")
ctx.sorted_transcripts[input_frames.frames[0].time] = None ctx.sorted_transcripts[input_frames.frames[0].time] = None
# TODO: Find cleaner way, watch "no transcription" issue below # TODO: Find cleaner way, watch "no transcription" issue below
@@ -174,9 +156,9 @@ def get_transcription(
# https://github.com/guillaumekln/faster-whisper/issues/369 # https://github.com/guillaumekln/faster-whisper/issues/369
audio_file = "test" + str(datetime.datetime.now()) audio_file = "test" + str(datetime.datetime.now())
wf = wave.open(audio_file, "wb") wf = wave.open(audio_file, "wb")
wf.setnchannels(CHANNELS) wf.setnchannels(settings.AUDIO_CHANNELS)
wf.setframerate(RATE) wf.setframerate(settings.AUDIO_SAMPLING_RATE)
wf.setsampwidth(2) wf.setsampwidth(settings.AUDIO_SAMPLING_WIDTH)
for frame in input_frames.frames: for frame in input_frames.frames:
wf.writeframes(b"".join(frame.to_ndarray())) wf.writeframes(b"".join(frame.to_ndarray()))
@@ -209,8 +191,8 @@ def get_transcription(
ctx.last_transcribed_time += duration ctx.last_transcribed_time += duration
ctx.transcription_text += result_text ctx.transcription_text += result_text
except Exception as exception: except Exception:
LOGGER.info("Exception" + str(exception)) logger.exception("Exception while transcribing")
result = TranscriptionOutput(result_text) result = TranscriptionOutput(result_text)
ctx.sorted_transcripts[input_frames.frames[0].time] = result ctx.sorted_transcripts[input_frames.frames[0].time] = result
@@ -258,7 +240,7 @@ class AudioStreamTrack(MediaStreamTrack):
self.audio_buffer.write(frame) self.audio_buffer.write(frame)
if local_frames := self.audio_buffer.read_many( if local_frames := self.audio_buffer.read_many(
AUDIO_BUFFER_SIZE, partial=False settings.AUDIO_BUFFER_SIZE, partial=False
): ):
whisper_result = run_in_executor( whisper_result = run_in_executor(
get_transcription, get_transcription,
@@ -296,24 +278,30 @@ async def offer(request: requests.Request) -> web.Response:
params = await request.json() params = await request.json()
offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"]) offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])
ctx = TranscriptionContext() # client identification
peername = request.transport.get_extra_info("peername")
if peername is not None:
clientid = f"{peername[0]}:{peername[1]}"
else:
clientid = uuid.uuid4()
# create a context for the whole rtc transaction
# add a customised logger to the context
ctx = TranscriptionContext(logger=logger.bind(client=clientid))
# handle RTC peer connection
pc = RTCPeerConnection() pc = RTCPeerConnection()
pc_id = "PeerConnection(%s)" % uuid.uuid4()
pcs.add(pc) pcs.add(pc)
def log_info(msg, *args) -> NoReturn:
LOGGER.info(pc_id + " " + msg, *args)
log_info("Created for " + request.remote)
@pc.on("datachannel") @pc.on("datachannel")
def on_datachannel(channel) -> NoReturn: def on_datachannel(channel) -> NoReturn:
ctx.data_channel = channel ctx.data_channel = channel
channel_log(channel, "-", "created by remote party") ctx.logger = ctx.logger.bind(channel=channel.label)
ctx.logger.info("Channel created by remote party")
@channel.on("message") @channel.on("message")
def on_message(message: str) -> NoReturn: def on_message(message: str) -> NoReturn:
channel_log(channel, "<", message) ctx.logger.info(f"Message: {message}")
if json.loads(message)["cmd"] == "STOP": if json.loads(message)["cmd"] == "STOP":
# Placeholder final summary # Placeholder final summary
response = get_final_summary_response() response = get_final_summary_response()
@@ -326,14 +314,14 @@ async def offer(request: requests.Request) -> web.Response:
@pc.on("connectionstatechange") @pc.on("connectionstatechange")
async def on_connectionstatechange() -> NoReturn: async def on_connectionstatechange() -> NoReturn:
log_info("Connection state is " + pc.connectionState) ctx.logger.info(f"Connection state changed: {pc.connectionState}")
if pc.connectionState == "failed": if pc.connectionState == "failed":
await pc.close() await pc.close()
pcs.discard(pc) pcs.discard(pc)
@pc.on("track") @pc.on("track")
def on_track(track) -> NoReturn: def on_track(track) -> NoReturn:
log_info("Track " + track.kind + " received") ctx.logger.info(f"Track {track.kind} received")
pc.addTrack(AudioStreamTrack(ctx, relay.subscribe(track))) pc.addTrack(AudioStreamTrack(ctx, relay.subscribe(track)))
await pc.setRemoteDescription(offer) await pc.setRemoteDescription(offer)

View File

@@ -0,0 +1,45 @@
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
OPENMP_KMP_DUPLICATE_LIB_OK: bool = False
# Whisper
WHISPER_MODEL_SIZE: str = "tiny"
whisper_real_time_model_size: str = "tiny"
# Summarizer
SUMMARIZER_MODEL: str = "facebook/bart-large-cnn"
SUMMARIZER_INPUT_ENCODING_MAX_LENGTH: int = 1024
SUMMARIZER_MAX_LENGTH: int = 2048
SUMMARIZER_BEAM_SIZE: int = 6
SUMMARIZER_MAX_CHUNK_LENGTH: int = 1024
SUMMARIZER_USING_CHUNKS: bool = True
# Audio
AUDIO_BLACKHOLE_INPUT_AGGREGATOR_DEVICE_NAME: str = "aggregator"
AUDIO_AV_FOUNDATION_DEVICE_ID: int = 1
AUDIO_CHANNELS: int = 2
AUDIO_SAMPLING_RATE: int = 48000
AUDIO_SAMPLING_WIDTH: int = 2
AUDIO_BUFFER_SIZE: int = 256 * 960
# LLM
LLM_BACKEND: str = "oobagooda"
LLM_URL: str | None = None
LLM_HOST: str = "localhost"
LLM_PORT: int = 7860
# Storage
STORAGE_BACKEND: str = "aws"
STORAGE_AWS_ACCESS_KEY: str = ""
STORAGE_AWS_SECRET_KEY: str = ""
STORAGE_AWS_BUCKET: str = ""
# OpenAI
OPENAI_API_KEY: str = ""
settings = Settings()

View File

@@ -9,8 +9,8 @@ import stamina
from aiortc import RTCPeerConnection, RTCSessionDescription from aiortc import RTCPeerConnection, RTCSessionDescription
from aiortc.contrib.media import MediaPlayer, MediaRelay from aiortc.contrib.media import MediaPlayer, MediaRelay
from utils.log_utils import LOGGER from reflector.logger import logger
from utils.run_utils import CONFIG from reflector.settings import settings
class StreamClient: class StreamClient:
@@ -31,7 +31,7 @@ class StreamClient:
self.time_start = None self.time_start = None
self.queue = asyncio.Queue() self.queue = asyncio.Queue()
self.player = MediaPlayer( self.player = MediaPlayer(
":" + str(CONFIG["AUDIO"]["AV_FOUNDATION_DEVICE_ID"]), f":{settings.AUDIO_AV_FOUNDATION_DEVICE_ID}",
format="avfoundation", format="avfoundation",
options={"channels": "2"}, options={"channels": "2"},
) )
@@ -71,7 +71,7 @@ class StreamClient:
self.pcs.add(pc) self.pcs.add(pc)
def log_info(msg, *args): def log_info(msg, *args):
LOGGER.info(pc_id + " " + msg, *args) logger.info(pc_id + " " + msg, *args)
@pc.on("connectionstatechange") @pc.on("connectionstatechange")
async def on_connectionstatechange(): async def on_connectionstatechange():

View File

@@ -3,48 +3,12 @@ Utility file for server side asynchronous task running and config objects
""" """
import asyncio import asyncio
import configparser
import contextlib import contextlib
from functools import partial from functools import partial
from threading import Lock from threading import Lock
from typing import ContextManager, Generic, TypeVar from typing import ContextManager, Generic, TypeVar
class ReflectorConfig:
"""
Create a single config object to share across the project
"""
__config = None
__secrets = None
@staticmethod
def get_config():
"""
Load the configurations from the local config.ini file
:return:
"""
if ReflectorConfig.__config is None:
ReflectorConfig.__config = configparser.ConfigParser()
ReflectorConfig.__config.read("utils/config.ini")
return ReflectorConfig.__config
@staticmethod
def get_secrets():
"""
Load the configurations from the local config.ini file
:return:
"""
if ReflectorConfig.__secrets is None:
ReflectorConfig.__secrets = configparser.ConfigParser()
ReflectorConfig.__secrets.read("utils/secrets.ini")
return ReflectorConfig.__secrets
CONFIG = ReflectorConfig.get_config()
SECRETS = ReflectorConfig.get_secrets()
def run_in_executor(func, *args, executor=None, **kwargs): def run_in_executor(func, *args, executor=None, **kwargs):
""" """
Run the function in an executor, unblocking the main loop Run the function in an executor, unblocking the main loop

View File

@@ -1,50 +0,0 @@
aiohttp==3.8.5
aiohttp-cors==0.7.0
aioice==0.9.0
aiortc==1.5.0
aiosignal==1.3.1
anyio==3.7.1
async-timeout==4.0.2
attrs==23.1.0
av==10.0.0
certifi==2023.7.22
cffi==1.15.1
charset-normalizer==3.2.0
coloredlogs==15.0.1
cryptography==41.0.2
ctranslate2==3.17.1
dnspython==2.4.0
faster-whisper==0.7.1
filelock==3.12.2
flatbuffers==23.5.26
frozenlist==1.4.0
fsspec==2023.6.0
google-crc32c==1.5.0
h11==0.14.0
httpcore==0.17.3
huggingface-hub==0.16.4
humanfriendly==10.0
idna==3.4
ifaddr==0.2.0
loguru==0.7.0
mpmath==1.3.0
multidict==6.0.4
numpy==1.25.1
onnxruntime==1.15.1
packaging==23.1
protobuf==4.23.4
pycparser==2.21
pyee==11.0.0
pylibsrtp==0.8.0
pyOpenSSL==23.2.0
PyYAML==6.0.1
requests==2.31.0
sniffio==1.3.0
sortedcontainers==2.4.0
sympy==1.12
tokenizers==0.13.3
tqdm==4.65.0
typing_extensions==4.7.1
urllib3==2.0.4
yarl==1.9.2
wave==0.0.2

View File

@@ -1,25 +0,0 @@
[DEFAULT]
#Set exception rule for OpenMP error
#to allow duplicate lib initialization
KMP_DUPLICATE_LIB_OK = TRUE
[WHISPER]
#ExportWhisperModelSize
WHISPER_MODEL_SIZE = tiny
WHISPER_REAL_TIME_MODEL_SIZE = tiny
[SUMMARIZER]
#Summarizerconfig
SUMMARY_MODEL = facebook/bart-large-cnn
INPUT_ENCODING_MAX_LENGTH = 1024
MAX_LENGTH = 2048
BEAM_SIZE = 6
MAX_CHUNK_LENGTH = 1024
SUMMARIZE_USING_CHUNKS = YES
[AUDIO]
# Audiodevice
BLACKHOLE_INPUT_AGGREGATOR_DEVICE_NAME = aggregator
AV_FOUNDATION_DEVICE_ID = 1
CHANNELS = 2
SAMPLING_RATE = 48000

View File

@@ -1,27 +0,0 @@
"""
Utility file for logging
"""
import loguru
class SingletonLogger:
"""
Use Singleton design pattern to create a logger object and share it
across the entire project
"""
__instance = None
@staticmethod
def get_logger():
"""
Create or return the singleton instance for the SingletonLogger class
:return: SingletonLogger instance
"""
if not SingletonLogger.__instance:
SingletonLogger.__instance = loguru.logger
return SingletonLogger.__instance
LOGGER = SingletonLogger.get_logger()

View File

@@ -1,14 +0,0 @@
[LLM]
# LLM configs
LLM_MACHINE_IP=
LLM_MACHINE_PORT=
[AWS-S3]
#AWSconfig
AWS_ACCESS_KEY=
AWS_SECRET_KEY=
BUCKET_NAME=
[OPENAI]
#ExportOpenAIAPIKey
OPENAI_APIKEY=