kcrobot102 commited on
Commit
78a5fbc
·
verified ·
1 Parent(s): 09db8af

initial commit

Browse files
Files changed (1) hide show
  1. app.py +192 -190
app.py CHANGED
@@ -1,4 +1,196 @@
1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  # app.py — KC Robot AI v7.5 FINAL (auto-model-select, bilingual, TTS fallback, Telegram, ESP32 endpoints)
3
  # Secrets expected (HF Space -> Settings -> Secrets):
4
  # HF_TOKEN (required)
@@ -661,193 +853,3 @@ if __name__ == "__main__":
661
  app.run(host="0.0.0.0", port=PORT)
662
 
663
 
664
- # ==========================================================
665
- # KC ROBOT AI - APP.PY (V2.0 MAX FINAL)
666
- # Cloud AI Robot with Gemini 2.5 Flash + ESP32 + Telegram
667
- # ==========================================================
668
-
669
- from flask import Flask, request, jsonify, render_template_string
670
- from google import genai
671
- import requests
672
- import os
673
- import time
674
- from gtts import gTTS
675
- from langdetect import detect
676
- import tempfile
677
- import base64
678
-
679
- # ==========================================================
680
- # CONFIGURATION
681
- # ==========================================================
682
-
683
- # Load environment variables from secrets (Cloud Run or Hugging Face)
684
- GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
685
- GEMINI_MODEL = os.getenv("GEMINI_MODEL", "gemini-2.5-flash")
686
- TELEGRAM_TOKEN = os.getenv("TELEGRAM_TOKEN")
687
- TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID")
688
-
689
- # Create Flask app
690
- app = Flask(__name__)
691
-
692
- # ==========================================================
693
- # SETUP GEMINI CLIENT
694
- # ==========================================================
695
- if not GEMINI_API_KEY:
696
- print("❌ ERROR: No Gemini API Key found. Please add GEMINI_API_KEY in Secrets.")
697
- client = None
698
- else:
699
- client = genai.Client(api_key=GEMINI_API_KEY)
700
-
701
- # ==========================================================
702
- # TELEGRAM UTILITIES
703
- # ==========================================================
704
- def send_telegram_message(text):
705
- if not TELEGRAM_TOKEN or not TELEGRAM_CHAT_ID:
706
- print("⚠️ Telegram not configured.")
707
- return
708
- url = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage"
709
- payload = {"chat_id": TELEGRAM_CHAT_ID, "text": text}
710
- try:
711
- requests.post(url, json=payload, timeout=5)
712
- except Exception as e:
713
- print("Telegram Error:", e)
714
-
715
- # ==========================================================
716
- # GEMINI AI RESPONSE
717
- # ==========================================================
718
- def ask_gemini(prompt: str):
719
- if not client:
720
- return "⚠️ Gemini API key missing. Please configure in Secrets."
721
-
722
- try:
723
- response = client.models.generate_content(
724
- model=GEMINI_MODEL,
725
- contents=prompt
726
- )
727
- if hasattr(response, "text"):
728
- return response.text.strip()
729
- elif "text" in response:
730
- return response["text"].strip()
731
- else:
732
- return "⚠️ No response text from Gemini."
733
- except Exception as e:
734
- print("Gemini Error:", e)
735
- return f"⚠️ Gemini Error: {e}"
736
-
737
- # ==========================================================
738
- # LANGUAGE DETECTION & TTS
739
- # ==========================================================
740
- def text_to_speech(text):
741
- try:
742
- lang = detect(text)
743
- if lang not in ["vi", "en"]:
744
- lang = "en"
745
- tts = gTTS(text=text, lang=lang)
746
- tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
747
- tts.save(tmp.name)
748
- with open(tmp.name, "rb") as f:
749
- audio_b64 = base64.b64encode(f.read()).decode("utf-8")
750
- os.unlink(tmp.name)
751
- return audio_b64
752
- except Exception as e:
753
- print("TTS Error:", e)
754
- return None
755
-
756
- # ==========================================================
757
- # SIMPLE HTML INTERFACE (for testing)
758
- # ==========================================================
759
- HTML_PAGE = """
760
- <!DOCTYPE html>
761
- <html>
762
- <head>
763
- <title>KC Robot AI v2.0</title>
764
- <style>
765
- body { font-family: Arial; text-align: center; background-color: #101010; color: white; }
766
- input, button { padding: 10px; font-size: 16px; margin: 5px; }
767
- #chat { max-width: 700px; margin: auto; text-align: left; background: #202020; padding: 20px; border-radius: 10px; }
768
- .msg-user { color: #4af; }
769
- .msg-bot { color: #fa4; margin-left: 20px; }
770
- audio { margin-top: 10px; }
771
- </style>
772
- </head>
773
- <body>
774
- <h1>🤖 KC Robot AI v2.0 MAX FINAL</h1>
775
- <div id="chat"></div>
776
- <br>
777
- <input id="user_input" placeholder="Nói gì đó..." style="width:60%">
778
- <button onclick="sendMessage()">Gửi</button>
779
-
780
- <script>
781
- async function sendMessage() {
782
- const input = document.getElementById("user_input").value;
783
- if (!input) return;
784
- const chat = document.getElementById("chat");
785
- chat.innerHTML += `<div class='msg-user'><b>Bạn:</b> ${input}</div>`;
786
- document.getElementById("user_input").value = "";
787
- const res = await fetch("/api/chat", {
788
- method: "POST",
789
- headers: {"Content-Type": "application/json"},
790
- body: JSON.stringify({message: input})
791
- });
792
- const data = await res.json();
793
- chat.innerHTML += `<div class='msg-bot'><b>Robot:</b> ${data.reply}</div>`;
794
- if (data.audio) {
795
- const audio = document.createElement("audio");
796
- audio.src = "data:audio/mp3;base64," + data.audio;
797
- audio.controls = true;
798
- chat.appendChild(audio);
799
- }
800
- chat.scrollTop = chat.scrollHeight;
801
- }
802
- </script>
803
- </body>
804
- </html>
805
- """
806
-
807
- @app.route("/")
808
- def home():
809
- return render_template_string(HTML_PAGE)
810
-
811
- # ==========================================================
812
- # API ENDPOINTS
813
- # ==========================================================
814
-
815
- @app.route("/api/chat", methods=["POST"])
816
- def api_chat():
817
- data = request.get_json()
818
- if not data or "message" not in data:
819
- return jsonify({"error": "Missing 'message'"}), 400
820
-
821
- user_message = data["message"]
822
- print(f"🧠 User said: {user_message}")
823
- send_telegram_message(f"User: {user_message}")
824
-
825
- ai_reply = ask_gemini(user_message)
826
- send_telegram_message(f"Robot: {ai_reply}")
827
-
828
- audio_b64 = text_to_speech(ai_reply)
829
- return jsonify({"reply": ai_reply, "audio": audio_b64})
830
-
831
- # ESP32 sensor endpoint
832
- @app.route("/api/sensor", methods=["POST"])
833
- def sensor_data():
834
- data = request.get_json()
835
- if not data:
836
- return jsonify({"error": "No data"}), 400
837
- msg = f"👁️ ESP32 Sensor update: {data}"
838
- send_telegram_message(msg)
839
- return jsonify({"status": "received"})
840
-
841
- # Health check
842
- @app.route("/ping")
843
- def ping():
844
- return jsonify({"status": "ok", "model": GEMINI_MODEL})
845
-
846
- # ==========================================================
847
- # MAIN ENTRY POINT
848
- # ==========================================================
849
- if __name__ == "__main__":
850
- port = int(os.getenv("PORT", 8080))
851
- print(f"🚀 KC Robot AI v2.0 running on port {port}")
852
- app.run(host="0.0.0.0", port=port)
853
-
 
1
 
2
+ # ==========================================================
3
+ # KC ROBOT AI - APP.PY (V2.0 MAX FINAL)
4
+ # Cloud AI Robot with Gemini 2.5 Flash + ESP32 + Telegram
5
+ # ==========================================================
6
+
7
+ from flask import Flask, request, jsonify, render_template_string
8
+ from google import genai
9
+ import requests
10
+ import os
11
+ import time
12
+ from gtts import gTTS
13
+ from langdetect import detect
14
+ import tempfile
15
+ import base64
16
+
17
+ # ==========================================================
18
+ # CONFIGURATION
19
+ # ==========================================================
20
+
21
+ # Load environment variables from secrets (Cloud Run or Hugging Face)
22
+ GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
23
+ GEMINI_MODEL = os.getenv("GEMINI_MODEL", "gemini-2.5-flash")
24
+ TELEGRAM_TOKEN = os.getenv("TELEGRAM_TOKEN")
25
+ TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID")
26
+
27
+ # Create Flask app
28
+ app = Flask(__name__)
29
+
30
+ # ==========================================================
31
+ # SETUP GEMINI CLIENT
32
+ # ==========================================================
33
+ if not GEMINI_API_KEY:
34
+ print("❌ ERROR: No Gemini API Key found. Please add GEMINI_API_KEY in Secrets.")
35
+ client = None
36
+ else:
37
+ client = genai.Client(api_key=GEMINI_API_KEY)
38
+
39
+ # ==========================================================
40
+ # TELEGRAM UTILITIES
41
+ # ==========================================================
42
+ def send_telegram_message(text):
43
+ if not TELEGRAM_TOKEN or not TELEGRAM_CHAT_ID:
44
+ print("⚠️ Telegram not configured.")
45
+ return
46
+ url = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage"
47
+ payload = {"chat_id": TELEGRAM_CHAT_ID, "text": text}
48
+ try:
49
+ requests.post(url, json=payload, timeout=5)
50
+ except Exception as e:
51
+ print("Telegram Error:", e)
52
+
53
+ # ==========================================================
54
+ # GEMINI AI RESPONSE
55
+ # ==========================================================
56
+ def ask_gemini(prompt: str):
57
+ if not client:
58
+ return "⚠️ Gemini API key missing. Please configure in Secrets."
59
+
60
+ try:
61
+ response = client.models.generate_content(
62
+ model=GEMINI_MODEL,
63
+ contents=prompt
64
+ )
65
+ if hasattr(response, "text"):
66
+ return response.text.strip()
67
+ elif "text" in response:
68
+ return response["text"].strip()
69
+ else:
70
+ return "⚠️ No response text from Gemini."
71
+ except Exception as e:
72
+ print("Gemini Error:", e)
73
+ return f"⚠️ Gemini Error: {e}"
74
+
75
+ # ==========================================================
76
+ # LANGUAGE DETECTION & TTS
77
+ # ==========================================================
78
+ def text_to_speech(text):
79
+ try:
80
+ lang = detect(text)
81
+ if lang not in ["vi", "en"]:
82
+ lang = "en"
83
+ tts = gTTS(text=text, lang=lang)
84
+ tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
85
+ tts.save(tmp.name)
86
+ with open(tmp.name, "rb") as f:
87
+ audio_b64 = base64.b64encode(f.read()).decode("utf-8")
88
+ os.unlink(tmp.name)
89
+ return audio_b64
90
+ except Exception as e:
91
+ print("TTS Error:", e)
92
+ return None
93
+
94
+ # ==========================================================
95
+ # SIMPLE HTML INTERFACE (for testing)
96
+ # ==========================================================
97
+ HTML_PAGE = """
98
+ <!DOCTYPE html>
99
+ <html>
100
+ <head>
101
+ <title>KC Robot AI v2.0</title>
102
+ <style>
103
+ body { font-family: Arial; text-align: center; background-color: #101010; color: white; }
104
+ input, button { padding: 10px; font-size: 16px; margin: 5px; }
105
+ #chat { max-width: 700px; margin: auto; text-align: left; background: #202020; padding: 20px; border-radius: 10px; }
106
+ .msg-user { color: #4af; }
107
+ .msg-bot { color: #fa4; margin-left: 20px; }
108
+ audio { margin-top: 10px; }
109
+ </style>
110
+ </head>
111
+ <body>
112
+ <h1>🤖 KC Robot AI v2.0 MAX FINAL</h1>
113
+ <div id="chat"></div>
114
+ <br>
115
+ <input id="user_input" placeholder="Nói gì đó..." style="width:60%">
116
+ <button onclick="sendMessage()">Gửi</button>
117
+
118
+ <script>
119
+ async function sendMessage() {
120
+ const input = document.getElementById("user_input").value;
121
+ if (!input) return;
122
+ const chat = document.getElementById("chat");
123
+ chat.innerHTML += `<div class='msg-user'><b>Bạn:</b> ${input}</div>`;
124
+ document.getElementById("user_input").value = "";
125
+ const res = await fetch("/api/chat", {
126
+ method: "POST",
127
+ headers: {"Content-Type": "application/json"},
128
+ body: JSON.stringify({message: input})
129
+ });
130
+ const data = await res.json();
131
+ chat.innerHTML += `<div class='msg-bot'><b>Robot:</b> ${data.reply}</div>`;
132
+ if (data.audio) {
133
+ const audio = document.createElement("audio");
134
+ audio.src = "data:audio/mp3;base64," + data.audio;
135
+ audio.controls = true;
136
+ chat.appendChild(audio);
137
+ }
138
+ chat.scrollTop = chat.scrollHeight;
139
+ }
140
+ </script>
141
+ </body>
142
+ </html>
143
+ """
144
+
145
+ @app.route("/")
146
+ def home():
147
+ return render_template_string(HTML_PAGE)
148
+
149
+ # ==========================================================
150
+ # API ENDPOINTS
151
+ # ==========================================================
152
+
153
+ @app.route("/api/chat", methods=["POST"])
154
+ def api_chat():
155
+ data = request.get_json()
156
+ if not data or "message" not in data:
157
+ return jsonify({"error": "Missing 'message'"}), 400
158
+
159
+ user_message = data["message"]
160
+ print(f"🧠 User said: {user_message}")
161
+ send_telegram_message(f"User: {user_message}")
162
+
163
+ ai_reply = ask_gemini(user_message)
164
+ send_telegram_message(f"Robot: {ai_reply}")
165
+
166
+ audio_b64 = text_to_speech(ai_reply)
167
+ return jsonify({"reply": ai_reply, "audio": audio_b64})
168
+
169
+ # ESP32 sensor endpoint
170
+ @app.route("/api/sensor", methods=["POST"])
171
+ def sensor_data():
172
+ data = request.get_json()
173
+ if not data:
174
+ return jsonify({"error": "No data"}), 400
175
+ msg = f"👁️ ESP32 Sensor update: {data}"
176
+ send_telegram_message(msg)
177
+ return jsonify({"status": "received"})
178
+
179
+ # Health check
180
+ @app.route("/ping")
181
+ def ping():
182
+ return jsonify({"status": "ok", "model": GEMINI_MODEL})
183
+
184
+ # ==========================================================
185
+ # MAIN ENTRY POINT
186
+ # ==========================================================
187
+ if __name__ == "__main__":
188
+ port = int(os.getenv("PORT", 8080))
189
+ print(f"🚀 KC Robot AI v2.0 running on port {port}")
190
+ app.run(host="0.0.0.0", port=port)
191
+
192
+
193
+
194
  # app.py — KC Robot AI v7.5 FINAL (auto-model-select, bilingual, TTS fallback, Telegram, ESP32 endpoints)
195
  # Secrets expected (HF Space -> Settings -> Secrets):
196
  # HF_TOKEN (required)
 
853
  app.run(host="0.0.0.0", port=PORT)
854
 
855