johnbridges commited on
Commit
b2c2f23
·
1 Parent(s): 5de81bd
Files changed (3) hide show
  1. app.py +8 -8
  2. config.py +46 -13
  3. requirements.txt +6 -0
app.py CHANGED
@@ -2,11 +2,11 @@ import asyncio
2
  import gradio as gr
3
  from fastapi import FastAPI
4
 
5
- from app.config import settings
6
- from app.listener import RabbitListenerBase
7
- from app.rabbit_repo import RabbitRepo
8
- from app.service import LLMService
9
- from app.runners.base import ILLMRunner
10
 
11
  # --- Runner factory (stub) ---
12
  class EchoRunner(ILLMRunner):
@@ -72,17 +72,17 @@ with gr.Blocks() as demo:
72
  app = FastAPI()
73
  app = gr.mount_gradio_app(app, demo, path="/")
74
 
75
- @app.get("/health")
76
  async def health():
77
  return {"status":"ok"}
78
 
79
- @app.on_event("startup")
80
  async def on_start():
81
  await publisher.connect()
82
  await service.init()
83
  await listener.start(DECLS)
84
 
85
- @app.on_event("shutdown")
86
  async def on_stop():
87
  # aio-pika RobustConnection closes on GC; optionally add explicit closes if you add references
88
  pass
 
2
  import gradio as gr
3
  from fastapi import FastAPI
4
 
5
+ from config import settings
6
+ from listener import RabbitListenerBase
7
+ from rabbit_repo import RabbitRepo
8
+ from service import LLMService
9
+ from runners.base import ILLMRunner
10
 
11
  # --- Runner factory (stub) ---
12
  class EchoRunner(ILLMRunner):
 
72
  app = FastAPI()
73
  app = gr.mount_gradio_app(app, demo, path="/")
74
 
75
+ @get("/health")
76
  async def health():
77
  return {"status":"ok"}
78
 
79
+ @on_event("startup")
80
  async def on_start():
81
  await publisher.connect()
82
  await service.init()
83
  await listener.start(DECLS)
84
 
85
+ @on_event("shutdown")
86
  async def on_stop():
87
  # aio-pika RobustConnection closes on GC; optionally add explicit closes if you add references
88
  pass
config.py CHANGED
@@ -1,22 +1,55 @@
1
- from pydantic import BaseSettings, AnyUrl
2
- from typing import Optional, Dict
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  class Settings(BaseSettings):
5
- # AMQP
6
- AMQP_URL: AnyUrl # e.g. amqps://user:pass@host:5671/%2F?heartbeat=30
 
7
  RABBIT_INSTANCE_NAME: str = "prod"
8
- RABBIT_EXCHANGE_TYPE: str = "topic" # match your .NET Type
9
- RABBIT_ROUTING_KEY: str = "" # match your .NET RoutingKeys ("" ok)
10
  RABBIT_PREFETCH: int = 1
11
 
12
- # Service identity
13
- SERVICE_ID: str = "monitor" # "monitor"|"nmap"|...
14
  USE_TLS: bool = True
15
 
16
- # Optional exchange type overrides by prefix, like .NET ExchangeTypes
17
- EXCHANGE_TYPES: Dict[str, str] = {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- class Config:
20
- case_sensitive = True
 
 
 
 
 
 
 
 
21
 
22
- settings = Settings() # env-driven
 
1
+ # app/config.py
2
+ import os
3
+ from functools import lru_cache
4
+
5
+ # v2-first import, fallback to v1
6
+ try:
7
+ from pydantic_settings import BaseSettings, SettingsConfigDict # pydantic v2
8
+ from pydantic import AnyUrl, Field
9
+ IS_V2 = True
10
+ except Exception:
11
+ from pydantic import BaseSettings, AnyUrl # pydantic v1
12
+ from pydantic import Field
13
+ IS_V2 = False
14
 
15
  class Settings(BaseSettings):
16
+ # Read from env: set this in your Space Secrets as AMQP_URL
17
+ AMQP_URL: AnyUrl = Field(..., description="amqps://user:pass@host:5671/%2F?heartbeat=30")
18
+
19
  RABBIT_INSTANCE_NAME: str = "prod"
20
+ RABBIT_EXCHANGE_TYPE: str = "topic"
21
+ RABBIT_ROUTING_KEY: str = ""
22
  RABBIT_PREFETCH: int = 1
23
 
24
+ SERVICE_ID: str = "gradllm"
 
25
  USE_TLS: bool = True
26
 
27
+ # Optional: prefix->type map, e.g. {"llmStartSession": "topic"}
28
+ EXCHANGE_TYPES: dict[str, str] = {}
29
+
30
+ if IS_V2:
31
+ # pydantic v2
32
+ model_config = SettingsConfigDict(
33
+ case_sensitive=True,
34
+ env_file=".env", # for local dev; ignored on HF unless you commit it
35
+ env_file_encoding="utf-8",
36
+ )
37
+ else:
38
+ # pydantic v1
39
+ class Config:
40
+ case_sensitive = True
41
+ env_file = ".env"
42
+ env_file_encoding = "utf-8"
43
 
44
+ @lru_cache
45
+ def get_settings() -> Settings:
46
+ try:
47
+ return Settings()
48
+ except Exception as e:
49
+ # Friendlier message when AMQP_URL is missing/invalid
50
+ raise RuntimeError(
51
+ "AMQP_URL is not set or invalid. In your Hugging Face Space, add a Secret "
52
+ "named AMQP_URL (e.g. amqps://user:pass@host:5671/%2F?heartbeat=30)."
53
+ ) from e
54
 
55
+ settings = get_settings()
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ gradio==5.42.0
2
+ fastapi==0.116.1
3
+ uvicorn==0.35.0
4
+ aio-pika==9.5.7
5
+ pydantic==2.11.1
6
+ pydantic-settings==2.10.1