Skip to content

Commit

Permalink
add chatgpt bridge example
Browse files Browse the repository at this point in the history
  • Loading branch information
Laurent2916 committed Jan 31, 2025
1 parent 5b913df commit f77317e
Show file tree
Hide file tree
Showing 28 changed files with 2,109 additions and 0 deletions.
5 changes: 5 additions & 0 deletions examples/chatgpt/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
LOGLEVEL='INFO'
APP_LOGLEVEL='INFO'
FG_API_USER='myuser@something.com'
FG_API_PASSWORD='VERY_SECURE_PASSWORD'
CHATGPT_AUTH_TOKEN='VERY_SECURE_TOKEN'
14 changes: 14 additions & 0 deletions examples/chatgpt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# python generated files
__pycache__/
*.py[oc]
build/
dist/
wheels/
*.egg-info


.env
.venv
.coverage
coverage.xml
requirements-dev.lock
1 change: 1 addition & 0 deletions examples/chatgpt/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12.8
21 changes: 21 additions & 0 deletions examples/chatgpt/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Module",
"type": "debugpy",
"request": "launch",
"module": "quart",
"args": [
"run",
"--port",
"8601",
"--host",
"0.0.0.0",
],
"env": {
"QUART_APP": "chatgpt_bridge:app",
}
}
]
}
13 changes: 13 additions & 0 deletions examples/chatgpt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# ChatGPT bridge

Use the Finegrain API right from ChatGPT.

## Usage

```bash
rye sync --all-features
```

```bash
QUART_APP=chatgpt_bridge quart run
```
81 changes: 81 additions & 0 deletions examples/chatgpt/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
[project]
authors = [
{ name = "Laurent Fainsin", email = "laurent@lagon.tech" },
]
dependencies = [
"environs>=14.1.0",
"finegrain @ git+https://github.com/finegrain-ai/finegrain-python.git#subdirectory=finegrain",
"pydantic>=2.10.5",
"quart>=0.20.0",
"pillow>=11.1.0",
]
description = "Finegrain API ChatGPT bridge"
name = "chatgpt-bridge"
readme = "README.md"
requires-python = ">= 3.12"
version = "0.1.0"

[tool.rye]
dev-dependencies = [
"pyright>=1.1.392",
"pytest-asyncio>=0.25.2",
"pytest>=8.3.4",
"ruff>=0.9.2",
"typos>=1.29.4",
"pytest-cov>=6.0.0",
]
managed = true

[build-system]
build-backend = "hatchling.build"
requires = ["hatchling"]

[tool.hatch.metadata]
allow-direct-references = true

[tool.hatch.build.targets.wheel]
packages = ["src/chatgpt_bridge"]

[tool.ruff]
line-length = 120
target-version = "py312"

[tool.ruff.lint]
ignore = [
"C901", # is too complex
"E731", # do-not-assign-lambda
"EM101", # exception must not use a string literal
"EM102", # f-string literal in exception message
"G004", # f-string literal in logging message
"N812", # imported as non-lowercase
"S101", # use of assert
"S311", # non secure cryptographic random
]
select = [
"A", # flake8-builtins
"B", # flake8-bugbear
"E", # pycodestyle errors
"EM", # flake8-errmsg
"F", # Pyflakes
"G", # flake8-logging-format
"I", # isort
"N", # pep8-naming
"PIE", # flake8-pie
"PTH", # flake8-use-pathlib
"RUF", # ruff
"S", # flake8-bandit
"TID", # flake8-tidy-imports
"UP", # pyupgrade
"W", # pycodestyle warnings
]

[tool.pyright]
pythonVersion = "3.12"
reportMissingImports = true
reportMissingTypeStubs = false
reportPrivateUsage = false
reportUntypedFunctionDecorator = false

[tool.pytest.ini_options]
asyncio_mode = "auto"
log_cli = true
91 changes: 91 additions & 0 deletions examples/chatgpt/requirements.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: true
# with-sources: false
# generate-hashes: false
# universal: false

-e file:.
aiofiles==24.1.0
# via quart
annotated-types==0.7.0
# via pydantic
anyio==4.8.0
# via httpx
blinker==1.9.0
# via flask
# via quart
certifi==2024.12.14
# via httpcore
# via httpx
click==8.1.8
# via flask
# via quart
environs==14.1.0
# via chatgpt-bridge
finegrain @ git+https://github.com/finegrain-ai/finegrain-python.git@f0760005675992988c2913afee37cdec7d7d9327#subdirectory=finegrain
# via chatgpt-bridge
flask==3.1.0
# via quart
h11==0.14.0
# via httpcore
# via hypercorn
# via wsproto
h2==4.1.0
# via hypercorn
hpack==4.1.0
# via h2
httpcore==1.0.7
# via httpx
httpx==0.28.1
# via finegrain
httpx-sse==0.4.0
# via finegrain
hypercorn==0.17.3
# via quart
hyperframe==6.1.0
# via h2
idna==3.10
# via anyio
# via httpx
itsdangerous==2.2.0
# via flask
# via quart
jinja2==3.1.5
# via flask
# via quart
markupsafe==3.0.2
# via jinja2
# via quart
# via werkzeug
marshmallow==3.26.0
# via environs
packaging==24.2
# via marshmallow
pillow==11.1.0
# via chatgpt-bridge
priority==2.0.0
# via hypercorn
pydantic==2.10.6
# via chatgpt-bridge
pydantic-core==2.27.2
# via pydantic
python-dotenv==1.0.1
# via environs
quart==0.20.0
# via chatgpt-bridge
sniffio==1.3.1
# via anyio
typing-extensions==4.12.2
# via anyio
# via pydantic
# via pydantic-core
werkzeug==3.1.3
# via flask
# via quart
wsproto==1.2.0
# via hypercorn
115 changes: 115 additions & 0 deletions examples/chatgpt/src/chatgpt_bridge/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import logging
from typing import Any

from finegrain import EditorAPIContext
from quart import Quart, Response, jsonify, request

from chatgpt_bridge.env import (
APP_LOGLEVEL,
CHATGPT_AUTH_TOKEN,
FG_API_PASSWORD,
FG_API_PRIORITY,
FG_API_TIMEOUT,
FG_API_URL,
FG_API_USER,
LOGLEVEL,
)
from chatgpt_bridge.skills.box import _box
from chatgpt_bridge.skills.cutout import _cutout
from chatgpt_bridge.skills.erase import _eraser
from chatgpt_bridge.skills.recolor import _recolor
from chatgpt_bridge.skills.shadow import _shadow
from chatgpt_bridge.skills.undo import _undo
from chatgpt_bridge.skills.upscale import _upscale
from chatgpt_bridge.utils import json_error, require_basic_auth_token

ctx = EditorAPIContext(
base_url=FG_API_URL,
user=FG_API_USER,
password=FG_API_PASSWORD,
priority=FG_API_PRIORITY,
default_timeout=FG_API_TIMEOUT,
)

app = Quart(__name__)

logging.basicConfig(level=LOGLEVEL)
app.logger.setLevel(APP_LOGLEVEL)
app.logger.info(f"LOGLEVEL: {LOGLEVEL}")
app.logger.info(f"FG_API_URL: {FG_API_URL}")
app.logger.info(f"FG_API_USER: {FG_API_USER}")
app.logger.info(f"FG_API_TIMEOUT: {FG_API_TIMEOUT}")
app.logger.info(f"FG_API_PRIORITY: {FG_API_PRIORITY}")


@app.before_serving
async def login() -> None:
await ctx.login()


@app.before_serving
async def sse_start() -> None:
await ctx.sse_start()


@app.after_serving
async def sse_stop() -> None:
await ctx.sse_stop()


@app.before_request
async def log_request() -> None:
app.logger.debug(f"Incoming request: {request.method} {request.path}")


@app.errorhandler(RuntimeError)
async def handle_runtime_error(error: RuntimeError) -> Response:
app.logger.error(f"RuntimeError: {error}")
return json_error(str(error))


@app.route("/health")
async def health() -> Response:
return jsonify({"status": "healthy"})


@app.post("/upscale")
@require_basic_auth_token(CHATGPT_AUTH_TOKEN)
async def upscale() -> Any:
return await _upscale(ctx, request)


@app.post("/box")
@require_basic_auth_token(CHATGPT_AUTH_TOKEN)
async def infer_bbox() -> Any:
return await _box(ctx, request)


@app.post("/cutout")
@require_basic_auth_token(CHATGPT_AUTH_TOKEN)
async def cutout() -> Any:
return await _cutout(ctx, request)


@app.post("/erase")
@require_basic_auth_token(CHATGPT_AUTH_TOKEN)
async def erase() -> Any:
return await _eraser(ctx, request)


@app.post("/recolor")
@require_basic_auth_token(CHATGPT_AUTH_TOKEN)
async def recolor() -> Any:
return await _recolor(ctx, request)


@app.post("/shadow")
@require_basic_auth_token(CHATGPT_AUTH_TOKEN)
async def shadow() -> Any:
return await _shadow(ctx, request)


@app.post("/undo")
@require_basic_auth_token(CHATGPT_AUTH_TOKEN)
async def undo() -> Any:
return await _undo(ctx, request)
20 changes: 20 additions & 0 deletions examples/chatgpt/src/chatgpt_bridge/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from typing import cast

from environs import Env
from finegrain import Priority

env = Env()
env.read_env()

with env.prefixed("FG_"):
FG_API_URL: str = str(env.str("API_URL", "https://api.finegrain.ai/editor"))
FG_API_USER: str = env.str("API_USER")
FG_API_PASSWORD: str = env.str("API_PASSWORD")
FG_API_PRIORITY: Priority = cast(Priority, env.str("API_PRIORITY", "low").lower())
FG_API_TIMEOUT: int = env.int("API_TIMEOUT", 60)

with env.prefixed("CHATGPT_"):
CHATGPT_AUTH_TOKEN: str = env.str("AUTH_TOKEN")

LOGLEVEL = env.str("LOGLEVEL", "INFO").upper()
APP_LOGLEVEL = env.str("APP_LOGLEVEL", "INFO").upper()
Empty file.
Empty file.
Loading

0 comments on commit f77317e

Please sign in to comment.