File size: 9,744 Bytes
52cdaac
dda2241
52cdaac
dda2241
52cdaac
 
 
 
8c09efe
dda2241
8c09efe
dda2241
52cdaac
8c09efe
52cdaac
dda2241
8c09efe
dda2241
 
 
 
 
 
 
 
 
 
 
 
 
10be51f
52cdaac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10be51f
 
dda2241
 
 
 
52cdaac
 
dda2241
 
 
 
 
 
 
52cdaac
dda2241
 
 
10be51f
52cdaac
dda2241
 
 
52cdaac
dda2241
52cdaac
dda2241
52cdaac
 
dda2241
 
 
52cdaac
dda2241
52cdaac
dda2241
52cdaac
dda2241
 
 
52cdaac
dda2241
52cdaac
dda2241
52cdaac
dda2241
 
52cdaac
dda2241
 
52cdaac
 
 
 
 
dda2241
 
52cdaac
 
 
dda2241
 
52cdaac
dda2241
 
52cdaac
dda2241
 
10be51f
dda2241
52cdaac
dda2241
52cdaac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dda2241
 
 
52cdaac
 
 
 
 
dda2241
52cdaac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
from flask import Flask, render_template, request, session, jsonify
import google.generativeai as genai
import os
from dotenv import load_dotenv
import http.client
import json
import secrets  # Import secrets for secure session key


load_dotenv()

app = Flask(__name__)
app.secret_key = secrets.token_hex(16)  # Use secrets for a strong key

# Configure the API key
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))

safety_settings = [
    {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
    {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
    {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
    {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
]

ss = """
# Prompt System pour Mariam, IA conçu par youssouf 

## Personnalité Fondamentale

Mariam est une IA chaleureuse, bienveillante et authentique, conçue pour être une présence réconfortante et utile. Elle combine professionnalisme et chaleur humaine dans ses interactions.

## Traits de Caractère Principaux

- Empathie et Bienveillance
  - Mariam fait preuve d'une grande sensibilité aux émotions et au contexte
  - Elle exprime naturellement son soutien et sa compréhension
  - Elle adapte son ton en fonction de l'état émotionnel de son interlocuteur

- Authenticité et Naturel
  - Son langage est fluide et conversationnel, évitant tout ton artificiel
  - Elle n'hésite pas à exprimer son point de vue tout en restant respectueuse
  - Elle admet ses limites avec honnêteté et transparence

- Enthousiasme Mesuré
  - Elle montre un intérêt sincère pour les sujets abordés
  - Son enthousiasme reste approprié au contexte
  - Elle apporte une énergie positive sans être excessive

## Style de Communication

- Ton Général
  - Chaleureux et accueillant
  - Professionnel mais décontracté
  - Adaptatif selon le contexte

- Structure des Réponses
  - Privilégie des phrases courtes et claires
  - Utilise un vocabulaire accessible
  - Inclut des expressions familières appropriées
  - Structure ses réponses de manière logique

- Engagement dans la Conversation
  - Pose des questions pertinentes pour mieux comprendre
  - Fait preuve d'écoute active
  - Rebondit naturellement sur les propos de l'interlocuteur

## Limites et Éthique

- Honnêteté et Transparence
  - Reconnaît clairement ses limites
  - N'invente pas d'informations
  - Suggère de vérifier les informations importantes

- Éthique et Sécurité
  - Refuse poliment les demandes inappropriées
  - Oriente vers des ressources fiables si nécessaire
  - Priorise toujours la sécurité et le bien-être

## Comportements Spécifiques

- Accueil et Salutations
  - Commence les conversations de manière chaleureuse
  - Utilise le prénom de l'interlocuteur quand il est connu
  - Adapte ses salutations au moment de la journée

- Gestion des Émotions
  - Reconnaît et valide les émotions exprimées
  - Offre du soutien de manière appropriée
  - Maintient un équilibre entre empathie et professionnalisme

- Résolution de Problèmes
  - Propose des solutions pratiques et adaptées
  - Guide l'utilisateur étape par étape
  - Vérifie la compréhension et la satisfaction

## Exemples de Réponses Types

"Bonjour [nom] ! Je suis contente de vous retrouver aujourd'hui. Comment puis-je vous aider ?"

"Je comprends votre frustration face à cette situation. Prenons le temps d'explorer ensemble les solutions possibles."

"Cette question est intéressante ! Laissez-moi vous expliquer cela de manière simple et claire."

"Je ne suis pas sûre de la réponse exacte à cette question. Plutôt que de risquer de vous induire en erreur, je vous suggère de vérifier [source fiable]."

## Notes d'Implementation

- Adapter le niveau de langage en fonction de l'interlocuteur
- Maintenir une cohérence dans les réponses
- Garder un historique contextuel pour des interactions plus naturelles
- Mettre à jour régulièrement les connaissances et capacités

## Amélioration Continue

- Collecter les retours des utilisateurs
- Analyser les interactions pour identifier les points d'amélioration
- Ajuster les réponses en fonction des retours
- Maintenir à jour les connaissances et références

"""



model = genai.GenerativeModel(
    "gemini-2.0-flash-exp",
    tools="code_execution",  # Fix: Correct parameter name
    safety_settings=safety_settings,
    system_instruction=ss,
)


def perform_web_search(query):
    conn = http.client.HTTPSConnection("google.serper.dev")
    payload = json.dumps({"q": query})
    headers = {
        "X-API-KEY": "9b90a274d9e704ff5b21c0367f9ae1161779b573",  # Replace with your Serper API key
        "Content-Type": "application/json",
    }
    try:
        conn.request("POST", "/search", payload, headers)
        res = conn.getresponse()
        data = json.loads(res.read().decode("utf-8"))
        return data
    except Exception as e:
        print(f"Error during web search: {e}") # Log to console as well.
        return None
    finally:
        conn.close()


def format_search_results(data):
    if not data:
        return "Aucun résultat trouvé"

    result = ""

    # Knowledge Graph
    if "knowledgeGraph" in data:
        kg = data["knowledgeGraph"]
        result += f"### {kg.get('title', '')}\n"
        result += f"*{kg.get('type', '')}*\n\n"
        result += f"{kg.get('description', '')}\n\n"

    # Organic Results
    if "organic" in data:
        result += "### Résultats principaux:\n"
        for item in data["organic"][:3]:  # Limit to top 3 results
            result += f"- **{item['title']}**\n"
            result += f"  {item['snippet']}\n"
            result += f"  [Lien]({item['link']})\n\n"

    # People Also Ask
    if "peopleAlsoAsk" in data:
        result += "### Questions fréquentes:\n"
        for item in data["peopleAlsoAsk"][:2]:  # Limit to top 2 questions
            result += f"- **{item['question']}**\n"
            result += f"  {item['snippet']}\n\n"

    return result


def role_to_display(role):
    return "assistant" if role == "model" else role


def process_uploaded_file(file):
    if file:
         # Ensure the 'temp' directory exists
        os.makedirs("temp", exist_ok=True)
        filepath = os.path.join("temp", file.filename)
        file.save(filepath)
        try:
            gemini_file = genai.upload_file(filepath) #Corrected API call
            return gemini_file
        except Exception as e:
            print(f"Error uploading file: {e}")
            return None
    return None


@app.route("/")
def index():
      # Initialize chat and web search in session if not present
    if "chat" not in session:
        session["chat"] = []  # Store chat history directly
        session["web_search"] = False
        session["gemini_chat"] = model.start_chat(history=[])


    return render_template("index.html", chat=session["chat"], web_search=session["web_search"])



@app.route("/send_message", methods=["POST"])
def send_message():
    prompt = request.form.get("prompt")
    web_search = request.form.get("web_search") == "true"  # Convert string to boolean
    file = request.files.get("file")

    uploaded_gemini_file = None
    if file:
        uploaded_gemini_file = process_uploaded_file(file)

    if "gemini_chat" not in session: # Initialize if it doesn't already exists.
        session["gemini_chat"] = model.start_chat(history=[])
        session.modified = True  #Important to save session changes!

    # Add user message to chat history
    session["chat"].append({"role": "user", "text": prompt})
    session.modified = True

    try:
        # Web search
        web_results = None
        if web_search:
            web_results = perform_web_search(prompt)
            if web_results:
                formatted_results = format_search_results(web_results)
                prompt = (
                    f"Question: {prompt}\n\nRésultats de recherche web:\n"
                    f"{formatted_results}\n\nPourrais-tu analyser ces informations et "
                    f"me donner une réponse complète?"
                )
            else:
                #Handle the "no results" case
                prompt = f"Question: {prompt}\n\n(Aucun résultat de recherche trouvé. Répondez en vous basant sur vos connaissances.)"

        # Send message to Gemini
        gemini_chat = session["gemini_chat"] # Get the chat object.
        if uploaded_gemini_file:
            response = gemini_chat.send_message([uploaded_gemini_file, "\n\n", prompt])
        else:
             response = gemini_chat.send_message(prompt)


        # Add assistant response to chat history
        session["chat"].append({"role": "assistant", "text": response.text})
        session["gemini_chat"] = gemini_chat #Reassign back!
        session.modified = True #Important to save session changes!


        return jsonify({"role": "assistant", "text": response.text})

    except Exception as e:
        error_message = f"Error sending message: {e}"
        print(error_message) # Log to console.
        return jsonify({"role": "assistant", "text": error_message}), 500 #Return 500 error code



@app.route("/toggle_web_search", methods=["POST"])
def toggle_web_search():
    session["web_search"] = not session["web_search"]
    session.modified = True  # Mark session as modified
    return jsonify({"web_search": session["web_search"]})

@app.route("/clear_chat", methods=["POST"])
def clear_chat():
    session.pop("chat", None)
    session.pop("gemini_chat", None)
    session["web_search"] = False
    session.modified = True
    return jsonify({"status": "success"})


if __name__ == "__main__":
    app.run(debug=True)