Tanveer539mbw8 commited on
Commit
1020044
Β·
verified Β·
1 Parent(s): f53e56b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -178
app.py CHANGED
@@ -1,127 +1,19 @@
1
- # ================================
2
- # AVIA AI BACKEND (Single File)
3
- # ================================
4
-
5
  import os
6
- import re
7
  import uuid
8
- import logging
9
- import asyncio
10
- from typing import List, Optional, Dict
11
- from urllib.parse import quote
12
-
13
  import uvicorn
14
- from fastapi import FastAPI, HTTPException
 
15
  from fastapi.responses import FileResponse
16
  from fastapi.middleware.cors import CORSMiddleware
17
- from pydantic import BaseModel
18
-
19
- # HF
20
- from huggingface_hub import InferenceClient
21
-
22
- # Search
23
  from duckduckgo_search import DDGS
 
24
 
25
- # TTS
26
- import edge_tts
27
-
28
-
29
- # ================================
30
- # CONFIG
31
- # ================================
32
-
33
- HF_TOKEN = os.getenv("HF_TOKEN")
34
-
35
- MODEL_LIST = [
36
- "microsoft/Phi-3.5-mini-instruct",
37
- "Qwen/Qwen2-1.5B-Instruct",
38
- ]
39
-
40
- logging.basicConfig(level=logging.INFO)
41
- logger = logging.getLogger("avia")
42
-
43
- ddgs = DDGS()
44
-
45
- SYSTEM_PROMPT = """
46
- You are Avia AI assistant created by Tanveer Ali.
47
- Speak in Hinglish.
48
- If user wants image β†’ output only:
49
- [IMAGE_PROMPT: detailed english prompt]
50
- """
51
-
52
-
53
- # ================================
54
- # UTIL
55
- # ================================
56
-
57
- def contains_hindi(text: str) -> bool:
58
- return bool(re.search(r'[\u0900-\u097F]', text))
59
-
60
-
61
- async def search_internet(query: str) -> str:
62
- try:
63
- results = await asyncio.to_thread(lambda: list(ddgs.text(query, max_results=3)))
64
- if not results:
65
- return ""
66
- return "\n".join([r.get("body", "") for r in results])
67
- except Exception as e:
68
- logger.error(e)
69
- return ""
70
-
71
-
72
- def extract_image_prompt(text: str):
73
- m = re.search(r"\[IMAGE_PROMPT:\s*(.*?)\]", text, re.I)
74
- return m.group(1) if m else None
75
-
76
-
77
- def generate_image_url(prompt: str):
78
- return f"https://image.pollinations.ai/prompt/{quote(prompt)}?seed={uuid.uuid4().int%1000}"
79
-
80
-
81
- def user_wants_image(msg: str):
82
- words = ["image", "photo", "picture", "tasveer", "banao", "draw"]
83
- return any(w in msg.lower() for w in words)
84
-
85
-
86
- async def call_llm(messages):
87
-
88
- for model in MODEL_LIST:
89
- try:
90
- logger.info(f"Trying model {model}")
91
- client = InferenceClient(model=model, token=HF_TOKEN)
92
-
93
- resp = await asyncio.to_thread(
94
- lambda: client.chat_completion(
95
- messages=messages,
96
- max_tokens=400,
97
- temperature=0.7,
98
- )
99
- )
100
-
101
- return resp.choices[0].message.content
102
-
103
- except Exception as e:
104
- logger.error(f"{model} failed {e}")
105
-
106
- return None
107
-
108
-
109
- # ================================
110
- # SCHEMA
111
- # ================================
112
-
113
- class ChatRequest(BaseModel):
114
- message: str
115
- history: Optional[List[Dict[str, str]]] = None
116
-
117
-
118
- class ChatResponse(BaseModel):
119
- reply: str
120
-
121
-
122
- # ================================
123
- # APP
124
- # ================================
125
 
126
  app = FastAPI()
127
 
@@ -132,75 +24,121 @@ app.add_middleware(
132
  allow_headers=["*"],
133
  )
134
 
135
-
136
- # ================================
137
- # ROUTES
138
- # ================================
139
-
140
  @app.get("/")
141
- def root():
142
- return {"status": "ok", "avia": True}
143
-
144
-
145
- @app.post("/chat", response_model=ChatResponse)
146
- async def chat(req: ChatRequest):
147
-
148
- msg = req.message.strip()
149
- history = req.history or []
150
-
151
- # search trigger
152
- search_words = ["news", "weather", "price", "who", "latest"]
153
- search_ctx = ""
154
-
155
- if any(w in msg.lower() for w in search_words):
156
- search_ctx = await search_internet(msg)
157
-
158
- system = SYSTEM_PROMPT
159
- if search_ctx:
160
- system += "\n" + search_ctx
161
 
162
- messages = [{"role": "system", "content": system}]
163
- messages.extend(history[-4:])
164
- messages.append({"role": "user", "content": msg})
165
-
166
- # call model
167
- reply = await call_llm(messages)
168
-
169
- if not reply:
170
- return ChatResponse(reply="Server busy. Try again.")
171
-
172
- # image logic
173
- img_prompt = extract_image_prompt(reply)
174
-
175
- if img_prompt:
176
- return ChatResponse(reply="IMAGE_URL:" + generate_image_url(img_prompt))
177
-
178
- if user_wants_image(msg):
179
- return ChatResponse(reply="IMAGE_URL:" + generate_image_url(msg))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
- return ChatResponse(reply=reply)
 
 
182
 
 
 
183
 
 
184
  @app.get("/tts")
185
  async def tts(text: str):
186
-
187
- if not text:
188
- raise HTTPException(400)
189
-
190
- voice = "hi-IN-SwaraNeural" if contains_hindi(text) else "en-US-AriaNeural"
191
-
192
- filename = f"voice_{uuid.uuid4()}.mp3"
193
-
194
  try:
195
- await edge_tts.Communicate(text, voice).save(filename)
 
 
 
 
 
196
  return FileResponse(filename, media_type="audio/mpeg")
197
- except Exception:
198
- raise HTTPException(500)
199
-
200
-
201
- # ================================
202
- # RUN
203
- # ================================
204
 
205
  if __name__ == "__main__":
206
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
 
 
 
 
1
  import os
 
2
  import uuid
3
+ import requests
 
 
 
 
4
  import uvicorn
5
+ import edge_tts
6
+ from fastapi import FastAPI, Request
7
  from fastapi.responses import FileResponse
8
  from fastapi.middleware.cors import CORSMiddleware
 
 
 
 
 
 
9
  from duckduckgo_search import DDGS
10
+ import google.generativeai as genai # 🟒 NEW: Gemini Import
11
 
12
+ # βœ… 1. SETUP & CONFIGURATION
13
+ # Ab HF_TOKEN ki jagah hum GEMINI_API_KEY use karenge
14
+ GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
15
+ if GEMINI_API_KEY:
16
+ genai.configure(api_key=GEMINI_API_KEY)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  app = FastAPI()
19
 
 
24
  allow_headers=["*"],
25
  )
26
 
 
 
 
 
 
27
  @app.get("/")
28
+ async def home():
29
+ return {"status": "Avia AI (Gemini Powered Stable Version) is Ready! πŸš€"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
+ # 🌍 2. INTERNET SEARCH (Real-time Data)
32
+ def search_web(query):
33
+ try:
34
+ with DDGS() as ddgs:
35
+ results = [r for r in ddgs.text(query, region='in-en', max_results=3)]
36
+ if results:
37
+ summary = "\n".join([f"β€’ {r['title']}: {r['body']}" for r in results])
38
+ return f"\n[INTERNET DATA - Use this if relevant]:\n{summary}\n"
39
+ except: pass
40
+ return ""
41
+
42
+ # 🧠 3. SYSTEM PROMPT (The Persona)
43
+ def get_avia_prompt(search_context):
44
+ return f"""
45
+ You are Avia, a smart and friendly AI Assistant created by Tanveer Ali.
46
+
47
+ YOUR RULES:
48
+ 1. Language: Answer in a natural mix of Hindi and English (Hinglish).
49
+ 2. Personality: Helpful, intelligent, and polite.
50
+ 3. Creator: Tanveer Ali.
51
+
52
+ CAPABILITIES:
53
+ 1. IMAGE GENERATION:
54
+ - If the user asks to "generate", "create", "draw", "make" an image or photo:
55
+ - You MUST output a special tag: [IMAGE_PROMPT: <detailed English description>].
56
+ - Example: User: "Ek futuristic car banao" -> Response: "Sure! [IMAGE_PROMPT: A futuristic sports car, neon lights, cyberpunk city background, 8k resolution]"
57
+
58
+ 2. INTERNET:
59
+ - You have access to real-time information. Use the data below if needed.
60
+
61
+ {search_context}
62
+ """
63
+
64
+ # πŸ“¨ 4. CHAT API (The Main Logic)
65
+ @app.post("/chat")
66
+ async def chat(request: Request):
67
+ try:
68
+ data = await request.json()
69
+ user_msg = data.get("message", "")
70
+ history = data.get("history", [])
71
+
72
+ # --- Step A: Internet Search Check ---
73
+ search_context = ""
74
+ triggers = ["news", "price", "who is", "weather", "today", "search", "score", "match", "latest"]
75
+ if "?" in user_msg or any(w in user_msg.lower() for w in triggers):
76
+ web_data = search_web(user_msg)
77
+ if web_data: search_context = web_data
78
+
79
+ # --- Step B: Initialize Gemini Brain with Persona ---
80
+ system_instruction = get_avia_prompt(search_context)
81
+
82
+ # 🟒 NEW: Setup Gemini Model
83
+ model = genai.GenerativeModel(
84
+ model_name="gemini-1.5-flash",
85
+ system_instruction=system_instruction
86
+ )
87
+
88
+ # 🟒 NEW: Convert history to Gemini format (Last 4 messages)
89
+ gemini_history = []
90
+ for h in history[-4:]:
91
+ role = "model" if h['role'] in ["assistant", "model"] else "user"
92
+ content = h.get('content', '')
93
+ if content:
94
+ gemini_history.append({"role": role, "parts": [content]})
95
+
96
+ # --- Step C: Call Internal Brain (Gemini API) ---
97
+ try:
98
+ chat_session = model.start_chat(history=gemini_history)
99
+ response = chat_session.send_message(user_msg)
100
+ ai_reply = response.text
101
+
102
+ # --- Step D: Image Generation Logic (Pollinations) ---
103
+
104
+ # 1. Check if AI gave the tag
105
+ if "[IMAGE_PROMPT" in ai_reply:
106
+ try:
107
+ start = ai_reply.find("[IMAGE_PROMPT:") + 14
108
+ end = ai_reply.find("]", start)
109
+ if end != -1:
110
+ prompt = ai_reply[start:end].strip()
111
+ img_url = f"https://image.pollinations.ai/prompt/{requests.utils.quote(prompt)}?nologo=true&seed={uuid.uuid4().int % 1000}"
112
+ return {"reply": f"IMAGE_URL:{img_url}"}
113
+ except: pass
114
+
115
+ # 2. Backup Logic
116
+ keywords = ["generate", "draw", "create", "banao", "tasveer", "photo", "image"]
117
+ if any(w in user_msg.lower() for w in keywords) and ("image" in user_msg.lower() or "photo" in user_msg.lower() or "tasveer" in user_msg.lower()):
118
+ img_url = f"https://image.pollinations.ai/prompt/{requests.utils.quote(user_msg)}?nologo=true&seed={uuid.uuid4().int % 1000}"
119
+ return {"reply": f"IMAGE_URL:{img_url}"}
120
+
121
+ return {"reply": ai_reply}
122
 
123
+ except Exception as e:
124
+ print(f"Brain Error: {e}")
125
+ return {"reply": "Sorry Tanveer, mera server abhi thoda busy hai. Please try again in 5 seconds."}
126
 
127
+ except Exception as e:
128
+ return {"reply": f"Error: {str(e)}"}
129
 
130
+ # πŸ”Š 5. TTS API (Voice)
131
  @app.get("/tts")
132
  async def tts(text: str):
 
 
 
 
 
 
 
 
133
  try:
134
+ is_hindi = any('\u0900' <= c <= '\u097f' for c in text)
135
+ voice = "hi-IN-SwaraNeural" if is_hindi else "en-US-AriaNeural"
136
+
137
+ communicate = edge_tts.Communicate(text, voice)
138
+ filename = f"voice_{uuid.uuid4()}.mp3"
139
+ await communicate.save(filename)
140
  return FileResponse(filename, media_type="audio/mpeg")
141
+ except: return {"error": "TTS Error"}
 
 
 
 
 
 
142
 
143
  if __name__ == "__main__":
144
+ uvicorn.run(app, host="0.0.0.0", port=7860)