Pepguy commited on
Commit
f062f34
·
verified ·
1 Parent(s): 1148777

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +108 -109
app.py CHANGED
@@ -1,111 +1,110 @@
1
- # To run this code you need to install the following dependencies:
2
- # pip install flask google-genai
3
-
4
- import os
5
- from flask import Flask, request, render_template_string, jsonify
6
- from google import genai
7
- from google.genai import types
8
-
9
- app = Flask(__name__)
10
-
11
- HTML = """
12
- <!DOCTYPE html>
13
- <html lang="en">
14
- <head>
15
- <meta charset="UTF-8" />
16
- <title>Gemini Test</title>
17
- </head>
18
- <body style="font-family:sans-serif;padding:2rem;">
19
- <h1>Gemini-2.0-Flash Test</h1>
20
- <form id="genai-form">
21
- <textarea id="prompt" rows="6" cols="60" placeholder="Enter your prompt here"></textarea><br/><br/>
22
- <button type="submit">Generate</button>
23
- </form>
24
- <pre id="output" style="background:#f4f4f4;padding:1rem;margin-top:1rem;"></pre>
25
-
26
- <script>
27
- const form = document.getElementById('genai-form');
28
- form.addEventListener('submit', async e => {
29
- e.preventDefault();
30
- const prompt = document.getElementById('prompt').value.trim();
31
- const out = document.getElementById('output');
32
- out.textContent = 'Generating…';
33
-
34
- try {
35
- const resp = await fetch('/generate', {
36
- method: 'POST',
37
- headers: { 'Content-Type': 'application/json' },
38
- body: JSON.stringify({ prompt }),
39
- });
40
-
41
- // if you want to debug status codes:
42
- if (!resp.ok) {
43
- const errText = await resp.text();
44
- throw new Error(`Server returned ${resp.status}: ${errText}`);
45
- }
46
-
47
- const data = await resp.json();
48
- if (data.error) {
49
- // show the backend error message
50
- out.textContent = 'Error: ' + data.error;
51
- } else if (data.result) {
52
- out.textContent = data.result;
53
- } else {
54
- out.textContent = 'Unexpected response payload';
55
- }
56
- } catch (err) {
57
- console.error(err);
58
- out.textContent = 'Fetch error: ' + err.message;
59
- }
60
- });
61
- </script>
62
- </body>
63
- </html>
64
- """
65
-
66
- def generate_from_gemini(prompt: str) -> str:
67
- client = genai.Client(
68
- api_key="AIzaSyDolbPUZBPUPvQUu-RGktJmvnUpkcEKIYo",
69
- )
70
-
71
- model = "gemini-2.0-flash"
72
- contents = [
73
- types.Content(
74
- role="user",
75
- parts=[types.Part.from_text(text=prompt)],
76
- )
77
- ]
78
- config = types.GenerateContentConfig(response_mime_type="text/plain")
79
-
80
- # Synchronous, non-streaming call:
81
- response = client.models.generate_content(
82
- model=model,
83
- contents=contents,
84
- config=config,
85
- )
86
- # The full text is in response.text
87
- return response.text
88
-
89
- @app.route('/')
90
- def index():
91
- return render_template_string(HTML)
92
-
93
- @app.route('/generate', methods=['POST'])
94
- def gen():
95
- data = request.get_json(silent=True) or {}
96
- prompt = data.get("prompt", "")
97
- app.logger.info(f"Received prompt: {prompt!r}")
98
- if not prompt:
99
- return jsonify({"error": "No prompt provided"}), 400
100
  try:
101
- output = generate_from_gemini(prompt)
102
- app.logger.info("Generation succeeded, length=%d", len(output))
103
- return jsonify({"result": output})
104
- except Exception as e:
105
- app.logger.exception("Generation failed")
106
- return jsonify({"error": str(e)}), 500
107
-
108
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  if __name__ == "__main__":
110
- port = int(os.environ.get("PORT", 7860))
111
- app.run(host="0.0.0.0", port=port)
 
 
 
 
 
 
 
 
 
 
1
+ # server.py
2
+
3
+ from typing import List, Dict, Optional, Tuple
4
+ from fastapi import FastAPI, HTTPException
5
+ from pydantic import BaseModel, Field
6
+ from sklearn.neighbors import KDTree
7
+ import numpy as np
8
+
9
+ # Configurable number of scales
10
+ NUM_SCALES = 8
11
+
12
+ # Pydantic models
13
+ class Profile(BaseModel):
14
+ id: str
15
+ scales: List[float] = Field(..., min_items=NUM_SCALES, max_items=NUM_SCALES)
16
+
17
+ class Content(BaseModel):
18
+ id: str
19
+ scales: List[float] = Field(..., min_items=NUM_SCALES, max_items=NUM_SCALES)
20
+ metadata: Optional[Dict] = None
21
+
22
+ class Recommendation(BaseModel):
23
+ content_id: str
24
+ distance: float
25
+
26
+ # Abstract repository interface
27
+ class DataRepository:
28
+ def add_user(self, user: Profile): ...
29
+ def add_content(self, content: Content): ...
30
+ def get_user(self, user_id: str) -> Profile: ...
31
+ def query_region(self, mins: List[float], maxs: List[float]) -> List[Content]: ...
32
+
33
+ # In-memory implementation
34
+ class InMemoryRepo(DataRepository):
35
+ def __init__(self):
36
+ self.users: Dict[str, Profile] = {}
37
+ self.contents: Dict[str, Content] = {}
38
+
39
+ def add_user(self, user: Profile):
40
+ self.users[user.id] = user
41
+
42
+ def add_content(self, content: Content):
43
+ self.contents[content.id] = content
44
+
45
+ def get_user(self, user_id: str) -> Profile:
46
+ user = self.users.get(user_id)
47
+ if not user:
48
+ raise ValueError("User not found")
49
+ return user
50
+
51
+ def query_region(self, mins: List[float], maxs: List[float]) -> List[Content]:
52
+ # Filter contents by N-dimensional bounding box
53
+ return [
54
+ c for c in self.contents.values()
55
+ if all(mn <= v <= mx for v, mn, mx in zip(c.scales, mins, maxs))
56
+ ]
57
+
58
+ # FastAPI setup
59
+ app = FastAPI()
60
+ repo = InMemoryRepo()
61
+
62
+ @app.post("/users", response_model=Profile)
63
+ def create_user(user: Profile):
64
+ repo.add_user(user)
65
+ return user
66
+
67
+ @app.post("/contents", response_model=Content)
68
+ def create_content(content: Content):
69
+ repo.add_content(content)
70
+ return content
71
+
72
+ @app.get("/recommendations/{user_id}", response_model=List[Recommendation])
73
+ def recommend(user_id: str, region_radius: float = 0.2, top_k: int = 5):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  try:
75
+ user = repo.get_user(user_id)
76
+ except ValueError:
77
+ raise HTTPException(status_code=404, detail="User not found")
78
+
79
+ # Build bounding region
80
+ mins = [max(0.0, v - region_radius) for v in user.scales]
81
+ maxs = [min(1.0, v + region_radius) for v in user.scales]
82
+
83
+ # Query region
84
+ candidates = repo.query_region(mins, maxs)
85
+ if not candidates:
86
+ return []
87
+
88
+ # Build KDTree over candidates to find nearest neighbors
89
+ mat = np.array([c.scales for c in candidates])
90
+ tree = KDTree(mat)
91
+ dist, idx = tree.query(np.array(user.scales).reshape(1, -1), k=min(top_k, len(candidates)))
92
+
93
+ return [
94
+ Recommendation(content_id=candidates[i].id, distance=float(d))
95
+ for d, i in zip(dist[0], idx[0])
96
+ ]
97
+
98
+ # Sample test data when run directly
99
  if __name__ == "__main__":
100
+ # Install dependencies: fastapi, uvicorn, numpy, scikit-learn, pydantic
101
+ import uvicorn
102
+ # Create random test users and content
103
+ repo.add_user(Profile(id="user1", scales=list(np.random.rand(NUM_SCALES))))
104
+ for i in range(1, 21):
105
+ repo.add_content(Content(
106
+ id=f"content{i}",
107
+ scales=list(np.random.rand(NUM_SCALES)),
108
+ metadata={"title": f"Item {i}"}
109
+ ))
110
+ uvicorn.run(app, host="0.0.0.0", port=8000)