Basti1110 commited on
Commit
f4f2ff0
·
1 Parent(s): 2199741

Initial commit

Browse files
Files changed (9) hide show
  1. .env +3 -0
  2. README.md +15 -0
  3. main.py +49 -0
  4. models.py +15 -0
  5. requirements.txt +5 -0
  6. space-config.json +3 -0
  7. static/app.js +20 -0
  8. static/index.html +28 -0
  9. static/style.css +6 -0
.env ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # Optional environment variables
2
+ OPENAI_API_KEY=YOUR_KEY
3
+ DEFAULT_EXPIRY=2026-05-10
README.md CHANGED
@@ -1,3 +1,4 @@
 
1
  ---
2
  title: Schulcomply Beta
3
  emoji: 📉
@@ -12,3 +13,17 @@ short_description: AI Compliance Coach for Schools
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ HEAD
2
  ---
3
  title: Schulcomply Beta
4
  emoji: 📉
 
13
  ---
14
 
15
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
16
+
17
+ Dieses Proje
18
+ kt stellt einen einfachen GDPR-Compliance-Coach als Web-App bereit.
19
+
20
+ ## Setup
21
+ ```bash
22
+ pip install -r requirements.txt
23
+ export OPENAI_API_KEY=YOUR_KEY
24
+ python main.py
25
+ ```
26
+
27
+ ## Deployment
28
+ In Hugging Face Spaces: keine Docker nötig, der Space liest SDK `static` ein und liefert das Frontend mit FastAPI.
29
+ >>>>>>> c3d1599 (Initial commit)
main.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from fastapi.staticfiles import StaticFiles
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from models import ChatRequest, ChatResponse, ContractRequest, ContractResponse
5
+ import os
6
+ import openai
7
+
8
+ # Load environment
9
+ from dotenv import load_dotenv
10
+ load_dotenv()
11
+ openai.api_key = os.getenv("OPENAI_API_KEY")
12
+
13
+ app = FastAPI(title="SchulComply 2025 Backend")
14
+ app.add_middleware(
15
+ CORSMiddleware,
16
+ allow_origins=["*"],
17
+ allow_methods=["GET", "POST"],
18
+ allow_headers=["*"],
19
+ )
20
+
21
+ # Serve static files
22
+ app.mount("/", StaticFiles(directory="static", html=True), name="static")
23
+
24
+ @app.post("/api/chat", response_model=ChatResponse)
25
+ async def chat(req: ChatRequest):
26
+ # call OpenAI to generate compliance advice
27
+ resp = openai.ChatCompletion.create(
28
+ model="gpt-4",
29
+ messages=[{"role": "system", "content": "You are a GDPR compliance assistant."},
30
+ {"role": "user", "content": req.message}]
31
+ )
32
+ reply = resp.choices[0].message.content
33
+ return ChatResponse(reply=reply)
34
+
35
+ @app.post("/api/contracts", response_model=ContractResponse)
36
+ async def create_contract(req: ContractRequest):
37
+ # Dummy contract generation
38
+ contract_id = f"AV-{os.urandom(4).hex().upper()}"
39
+ expires = (os.getenv("DEFAULT_EXPIRY", "2026-05-10"))
40
+ return ContractResponse(contract_id=contract_id, expires_on=expires)
41
+
42
+ @app.get("/api/risk-analysis/{tool_name}")
43
+ async def risk_analysis(tool_name: str):
44
+ # Placeholder risk scores
45
+ return {"tool": tool_name, "risk_level": "niedrig"}
46
+
47
+ if __name__ == "__main__":
48
+ import uvicorn
49
+ uvicorn.run("main:app", host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))
models.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+
3
+ class ChatRequest(BaseModel):
4
+ message: str
5
+
6
+ class ChatResponse(BaseModel):
7
+ reply: str
8
+
9
+ class ContractRequest(BaseModel):
10
+ vendor: str
11
+ services: str
12
+
13
+ class ContractResponse(BaseModel):
14
+ contract_id: str
15
+ expires_on: str
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn[standard]
3
+ pydantic
4
+ python-dotenv
5
+ openai
space-config.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "sdk": "static"
3
+ }
static/app.js ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ async function postData(url = '', data = {}) {
2
+ const res = await fetch(url, {
3
+ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data)
4
+ });
5
+ return res.json();
6
+ }
7
+
8
+ document.getElementById('chat-send').onclick = async () => {
9
+ const msg = document.getElementById('chat-input').value;
10
+ const res = await postData('/api/chat', { message: msg });
11
+ document.getElementById('chat-output').innerText = res.reply;
12
+ };
13
+
14
+ document.getElementById('contract-send').onclick = async () => {
15
+ const vendor = document.getElementById('vendor').value;
16
+ const services = document.getElementById('services').value;
17
+ const res = await postData('/api/contracts', { vendor, services });
18
+ document.getElementById('contract-output').innerText = `Vertrag-ID: ${res.contract_id}
19
+ Gültig bis: ${res.expires_on}`;
20
+ };
static/index.html ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="de">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>SchulComply 2025</title>
7
+ <link rel="stylesheet" href="/style.css">
8
+ </head>
9
+ <body>
10
+ <header><h1>SchulComply 2025</h1></header>
11
+ <main>
12
+ <section id="chat-section">
13
+ <h2>Compliance-Chat</h2>
14
+ <textarea id="chat-input" placeholder="Ihre Frage zur DSGVO..."></textarea>
15
+ <button id="chat-send">Senden</button>
16
+ <div id="chat-output"></div>
17
+ </section>
18
+ <section id="contract-section">
19
+ <h2>AV-Vertrag erstellen</h2>
20
+ <input id="vendor" placeholder="Anbieter...">
21
+ <input id="services" placeholder="Leistungen...">
22
+ <button id="contract-send">Erstellen</button>
23
+ <div id="contract-output"></div>
24
+ </section>
25
+ </main>
26
+ <script src="/app.js"></script>
27
+ </body>
28
+ </html>
static/style.css ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ body { font-family: Arial, sans-serif; max-width: 800px; margin: auto; padding: 1rem; }
2
+ header { text-align: center; margin-bottom: 2rem; }
3
+ section { margin-bottom: 2rem; border: 1px solid #ccc; padding: 1rem; border-radius: 8px; }
4
+ textarea, input { width: 100%; padding: .5rem; margin-bottom: .5rem; }
5
+ button { padding: .5rem 1rem; border: none; cursor: pointer; border-radius: 4px; background: #007ACC; color: white; }
6
+ #chat-output, #contract-output { margin-top: 1rem; white-space: pre-wrap; background: #f9f9f9; padding: .5rem; border-radius: 4px; }