alessandro trinca tornidor commited on
Commit
b7ddaea
·
2 Parent(s): 7e0c650 55d7511

merge master into main

Browse files
.gitignore ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ venv
2
+ __pycache__
3
+ *.pyc
4
+ flagged/*
5
+
6
+ # Created by https://www.toptal.com/developers/gitignore/api/pycharm+all
7
+ # Edit at https://www.toptal.com/developers/gitignore?templates=pycharm+all
8
+
9
+ ### PyCharm+all ###
10
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
11
+ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
12
+
13
+ # User-specific stuff
14
+ .idea/**/workspace.xml
15
+ .idea/**/tasks.xml
16
+ .idea/**/usage.statistics.xml
17
+ .idea/**/dictionaries
18
+ .idea/**/shelf
19
+
20
+ # AWS User-specific
21
+ .idea/**/aws.xml
22
+
23
+ # Generated files
24
+ .idea/**/contentModel.xml
25
+
26
+ # Sensitive or high-churn files
27
+ .idea/**/dataSources/
28
+ .idea/**/dataSources.ids
29
+ .idea/**/dataSources.local.xml
30
+ .idea/**/sqlDataSources.xml
31
+ .idea/**/dynamic.xml
32
+ .idea/**/uiDesigner.xml
33
+ .idea/**/dbnavigator.xml
34
+
35
+ # Gradle
36
+ .idea/**/gradle.xml
37
+ .idea/**/libraries
38
+
39
+ # Gradle and Maven with auto-import
40
+ # When using Gradle or Maven with auto-import, you should exclude module files,
41
+ # since they will be recreated, and may cause churn. Uncomment if using
42
+ # auto-import.
43
+ # .idea/artifacts
44
+ # .idea/compiler.xml
45
+ # .idea/jarRepositories.xml
46
+ # .idea/modules.xml
47
+ # .idea/*.iml
48
+ # .idea/modules
49
+ # *.iml
50
+ # *.ipr
51
+
52
+ # CMake
53
+ cmake-build-*/
54
+
55
+ # Mongo Explorer plugin
56
+ .idea/**/mongoSettings.xml
57
+
58
+ # File-based project format
59
+ *.iws
60
+
61
+ # IntelliJ
62
+ out/
63
+
64
+ # mpeltonen/sbt-idea plugin
65
+ .idea_modules/
66
+
67
+ # JIRA plugin
68
+ atlassian-ide-plugin.xml
69
+
70
+ # Cursive Clojure plugin
71
+ .idea/replstate.xml
72
+
73
+ # SonarLint plugin
74
+ .idea/sonarlint/
75
+
76
+ # Crashlytics plugin (for Android Studio and IntelliJ)
77
+ com_crashlytics_export_strings.xml
78
+ crashlytics.properties
79
+ crashlytics-build.properties
80
+ fabric.properties
81
+
82
+ # Editor-based Rest Client
83
+ .idea/httpRequests
84
+
85
+ # Android studio 3.1+ serialized cache file
86
+ .idea/caches/build_file_checksums.ser
87
+
88
+ ### PyCharm+all Patch ###
89
+ # Ignore everything but code style settings and run configurations
90
+ # that are supposed to be shared within teams.
91
+
92
+ .idea/*
93
+
94
+ !.idea/codeStyles
95
+ !.idea/runConfigurations
96
+
97
+ # End of https://www.toptal.com/developers/gitignore/api/pycharm+all
Dockerfile ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-bookworm AS builder_global
2
+
3
+ ARG PACKAGE_NAME="app_gradio_fastapi"
4
+ ARG ROOT_DIR="/code"
5
+ WORKDIR ${ROOT_DIR}
6
+ RUN chmod 770 -R ${ROOT_DIR}/
7
+
8
+ COPY ./requirements.txt ${ROOT_DIR}/requirements.txt
9
+
10
+ RUN pip install pip --upgrade
11
+ RUN python -m venv venv
12
+ RUN . ${ROOT_DIR}/venv/bin/activate && pip install --no-cache-dir -r ${ROOT_DIR}/requirements.txt
13
+
14
+ COPY ./scripts ${ROOT_DIR}/scripts
15
+ COPY ./${PACKAGE_NAME} ${ROOT_DIR}/${PACKAGE_NAME}
16
+
17
+ RUN chmod +x ${ROOT_DIR}/scripts/entrypoint.sh
18
+
19
+ EXPOSE 7860
20
+
21
+ CMD ["/code/scripts/entrypoint.sh"]
22
+ # CMD ["uvicorn", "wrappers.main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -8,4 +8,37 @@ pinned: false
8
  license: mit
9
  ---
10
 
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  license: mit
9
  ---
10
 
11
+ # Gradio plus FastAPI with UUID logging sessions
12
+ ## Run the app in a virtual environment
13
+
14
+ 1. create and activate a virtual environment
15
+ 2. install the dependencies
16
+ 3. execute the uvicorn webserver
17
+
18
+ ```bash
19
+ # create and activate a virtual environment
20
+ python3 -m venv venv
21
+ source venv/bin/activate
22
+ # install the project dependencies
23
+ python -m pip install pip --upgrade
24
+ python -m pip install -r requirements.txt
25
+ # execute the uvicorn webserver
26
+ uvicorn app_gradio_fastapi.main:app --host 0.0.0.0 --port 7860 --reload
27
+ ```
28
+
29
+ ## Run the app within a docker container
30
+
31
+ Build the docker image and run the container:
32
+
33
+ ```bash
34
+ docker build . --tag app_gradio_fastapi --progress=plain
35
+ docker run -d --name app_gradio_fastapi -p 7860:7860 app_gradio_fastapi; docker logs -f app_gradio_fastapi
36
+ ```
37
+
38
+ To stop all the container and remove all the docker images:
39
+
40
+
41
+ ```bash
42
+ docker stop $(docker ps -a -q); docker rm $(docker ps -a -q)
43
+ docker rmi $(docker images -q) -f
44
+ ```
app_gradio_fastapi/__init__.py ADDED
File without changes
app_gradio_fastapi/helpers/__init__.py ADDED
File without changes
app_gradio_fastapi/helpers/formatters.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from fastapi import HTTPException
3
+
4
+ from app_gradio_fastapi.helpers import session_logger
5
+
6
+
7
+ def divide(a: int, b: int) -> float:
8
+ logging.info(f"a:{a}, b:{b}.")
9
+ result = a / b
10
+ logging.info(f"result:{result}.")
11
+ return result
12
+
13
+
14
+ @session_logger.set_uuid_logging
15
+ def request_formatter(text: str) -> dict:
16
+ logging.info("start request...")
17
+ try:
18
+ logging.info(f"input text we need to treat as an integer: {text}.")
19
+ b = int(text)
20
+ transformed_text = f"input after integer cast: {b}."
21
+ try:
22
+ result_division = divide(100, b)
23
+ logging.info(f"some_function, result_division:{result_division}.")
24
+ return {"text": transformed_text, "result": result_division}
25
+ except ZeroDivisionError as zde:
26
+ logging.info(f"exception:{zde}.")
27
+ raise HTTPException(status_code=500, detail="Internal server error")
28
+ except ValueError as ve:
29
+ logging.info(f"exception:{ve}.")
30
+ raise HTTPException(status_code=500, detail="Internal server error")
app_gradio_fastapi/helpers/session_logger.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import contextvars
2
+ import logging
3
+ from functools import wraps
4
+ from typing import Callable
5
+
6
+ logging_uuid = contextvars.ContextVar("uuid")
7
+ formatter = '%(asctime)s | %(uuid)s [%(pathname)s:%(module)s %(lineno)d] %(levelname)s | %(message)s'
8
+
9
+
10
+ loggingType = logging.CRITICAL | logging.ERROR | logging.WARNING | logging.INFO | logging.DEBUG
11
+
12
+
13
+ def change_logging(level_log: loggingType = logging.INFO) -> None:
14
+ old_factory = logging.getLogRecordFactory()
15
+
16
+ def record_factory(*args, **kwargs):
17
+ record = old_factory(*args, **kwargs)
18
+ record.uuid = logging_uuid.get("uuid")
19
+ if isinstance(record.msg, str):
20
+ record.msg = record.msg.replace("\\", "\\\\").replace("\n", "\\n")
21
+ return record
22
+
23
+ logging.setLogRecordFactory(record_factory)
24
+ logging.basicConfig(level=level_log, format=formatter, force=True)
25
+
26
+
27
+ def set_uuid_logging(func: Callable) -> Callable:
28
+ @wraps(func)
29
+ def wrapper(*args, **kwargs):
30
+ import uuid
31
+
32
+ current_uuid = f"{uuid.uuid4()}"
33
+ logging_uuid.set(current_uuid)
34
+ return func(*args, **kwargs)
35
+
36
+ return wrapper
app_gradio_fastapi/main.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from fastapi import FastAPI
3
+
4
+ from app_gradio_fastapi import routes
5
+ from app_gradio_fastapi.helpers.formatters import request_formatter
6
+ from app_gradio_fastapi.helpers.session_logger import change_logging
7
+
8
+
9
+ change_logging()
10
+
11
+ CUSTOM_GRADIO_PATH = "/"
12
+ app = FastAPI(title="logging_app", version="1.0")
13
+ app.include_router(routes.router)
14
+ io = gr.Interface(
15
+ request_formatter,
16
+ inputs=[
17
+ gr.Textbox(lines=1, placeholder=None, label="Text input"),
18
+ ],
19
+ outputs=[
20
+ gr.Textbox(lines=1, placeholder=None, label="Text Output"),
21
+ ],
22
+ )
23
+ app = gr.mount_gradio_app(app, io, path=CUSTOM_GRADIO_PATH)
app_gradio_fastapi/routes.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import logging
3
+
4
+ from fastapi import APIRouter
5
+
6
+ from app_gradio_fastapi.helpers import session_logger
7
+
8
+
9
+ router = APIRouter()
10
+
11
+
12
+ @router.get("/health")
13
+ @session_logger.set_uuid_logging
14
+ def health() -> str:
15
+ try:
16
+ logging.info("health check")
17
+ return json.dumps({"msg": "ok"})
18
+ except Exception as e:
19
+ logging.error(f"exception:{e}.")
20
+ return json.dumps({"msg": "request failed"})
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ gradio
2
+ fastapi
scripts/entrypoint.sh ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ WORKDIR="/code"
4
+
5
+ cd ${WORKDIR} || exit
6
+ pwd
7
+ source ${WORKDIR}/venv/bin/activate
8
+
9
+ which python
10
+ python --version
11
+ which pip
12
+ pip --version
13
+
14
+ free -m
15
+ pip list
16
+ ls -l
17
+ echo "uvicorn"
18
+ ls -l ${WORKDIR}/venv/bin/uvicorn
19
+
20
+ # python ${WORKDIR}/app.py --version='xinlai/LISA-13B-llama2-v1-explanatory' --precision='fp16' --load_in_4bit
21
+ echo "${WORKDIR}/venv/bin/uvicorn app_gradio_fastapi.main:app --host 0.0.0.0 --port 7860"
22
+ ${WORKDIR}/venv/bin/uvicorn app_gradio_fastapi.main:app --host 0.0.0.0 --port 7860
23
+
24
+ exit 0