Spaces:
Sleeping
Sleeping
Commit
·
4add55f
0
Parent(s):
Update app.py
Browse files- .env.example +15 -0
- .gitattributes +35 -0
- .gitignore +1 -0
- README.md +14 -0
- app.py +105 -0
- custom.css +119 -0
- requirements.txt +3 -0
.env.example
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Whether to use the HuggingFace API or Ollama
|
2 |
+
# Set this to yes or no
|
3 |
+
USE_HUGGINGFACE=
|
4 |
+
|
5 |
+
# This token is optional but you'll have more restrictive rate limits and model options without it
|
6 |
+
# Get your HuggingFace token from https://huggingface.co/settings/tokens
|
7 |
+
HUGGINGFACE_API_TOKEN=
|
8 |
+
|
9 |
+
# The model ID to use from HuggingFace for the tool calling LLM
|
10 |
+
# Example: meta-llama/Llama-3.3-70B-Instruct
|
11 |
+
TOOL_MODEL_ID=
|
12 |
+
|
13 |
+
AGENT_ENDPOINT=
|
14 |
+
|
15 |
+
AGENT_KEY=
|
.gitattributes
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.env
|
README.md
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: Vie Publique
|
3 |
+
emoji: 💬
|
4 |
+
colorFrom: yellow
|
5 |
+
colorTo: purple
|
6 |
+
sdk: gradio
|
7 |
+
sdk_version: 5.0.1
|
8 |
+
app_file: app.py
|
9 |
+
pinned: false
|
10 |
+
license: mit
|
11 |
+
short_description: Chat with vie-publique.sn
|
12 |
+
---
|
13 |
+
|
14 |
+
An example chatbot using [Gradio](https://gradio.app), [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/v0.22.2/en/index), and the [Hugging Face Inference API](https://huggingface.co/docs/api-inference/index).
|
app.py
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from dotenv import load_dotenv
|
2 |
+
import gradio as gr
|
3 |
+
import openai
|
4 |
+
import os
|
5 |
+
|
6 |
+
load_dotenv()
|
7 |
+
|
8 |
+
MAX_HISTORY_LENGTH = 10
|
9 |
+
|
10 |
+
def load_css():
|
11 |
+
try:
|
12 |
+
with open('custom.css', 'r', encoding='utf-8') as file:
|
13 |
+
return file.read()
|
14 |
+
except FileNotFoundError:
|
15 |
+
logging.warning("⚠️ custom.css non trouvé, chargement ignoré.")
|
16 |
+
return ""
|
17 |
+
|
18 |
+
def format_history_for_api(history):
|
19 |
+
"""
|
20 |
+
Convertit l'historique Gradio en format OpenAI.
|
21 |
+
"""
|
22 |
+
formatted_messages = []
|
23 |
+
for message in history:
|
24 |
+
formatted_messages.extend([
|
25 |
+
{"role": "user", "content": str(message[0])},
|
26 |
+
{"role": "assistant", "content": str(message[1])}
|
27 |
+
])
|
28 |
+
return formatted_messages
|
29 |
+
|
30 |
+
def rag_with_reasoner(user_query: str, history: list) -> dict:
|
31 |
+
"""
|
32 |
+
Outil RAG qui prend une requête utilisateur et renvoie une réponse basée sur le contexte historique.
|
33 |
+
"""
|
34 |
+
client = openai.OpenAI(
|
35 |
+
base_url=os.getenv("AGENT_ENDPOINT"),
|
36 |
+
api_key=os.getenv("AGENT_KEY"),
|
37 |
+
)
|
38 |
+
|
39 |
+
# Formatage des messages pour l'API
|
40 |
+
messages = format_history_for_api(history) if history else []
|
41 |
+
messages.append({"role": "user", "content": str(user_query)})
|
42 |
+
|
43 |
+
try:
|
44 |
+
response = client.chat.completions.create(
|
45 |
+
model="n/a",
|
46 |
+
messages=messages
|
47 |
+
)
|
48 |
+
return {"role": "assistant", "content": response.choices[0].message.content}
|
49 |
+
except Exception as e:
|
50 |
+
print(f"Error calling OpenAI API: {e}")
|
51 |
+
return {"role": "assistant", "content": f"Une erreur s'est produite: {str(e)}"}
|
52 |
+
|
53 |
+
def chat_function(message, history):
|
54 |
+
"""
|
55 |
+
Fonction de chat pour Gradio.
|
56 |
+
"""
|
57 |
+
try:
|
58 |
+
# Limiter la taille de l'historique
|
59 |
+
if len(history) > MAX_HISTORY_LENGTH:
|
60 |
+
history = history[-MAX_HISTORY_LENGTH:]
|
61 |
+
|
62 |
+
response = rag_with_reasoner(message, history)
|
63 |
+
return response["content"]
|
64 |
+
except Exception as e:
|
65 |
+
print(f"Error in chat function: {e}")
|
66 |
+
return f"Une erreur s'est produite: {str(e)}"
|
67 |
+
|
68 |
+
# Configuration de l'interface Gradio
|
69 |
+
css = """
|
70 |
+
.message.tool-call { background-color: #f0f8ff; }
|
71 |
+
.message.tool-result { background-color: #f5f5f5; }
|
72 |
+
.message.error { background-color: #fff0f0; }
|
73 |
+
.chat-header {
|
74 |
+
display: flex;
|
75 |
+
align-items: center;
|
76 |
+
justify-content: center;
|
77 |
+
gap: 10px;
|
78 |
+
background: linear-gradient(90deg, #0000d3, #010272);
|
79 |
+
}
|
80 |
+
.chat-header img {
|
81 |
+
height: 40px;
|
82 |
+
}
|
83 |
+
"""
|
84 |
+
|
85 |
+
# Création de l'interface de chat avec Gradio
|
86 |
+
chat_interface = gr.ChatInterface(
|
87 |
+
fn=chat_function,
|
88 |
+
title="<div class='chat-header'><img src='https://www.vie-publique.sn/_nuxt/vie-publique-logo-4.BGl8Bhgm.svg' alt='Logo'><span>🤖</span></div>",
|
89 |
+
description="Discutez avec un agent IA pour des analyses précises et des conseils sur la vie publique du Sénégal 🇸🇳",
|
90 |
+
examples=["Sénégal 2050", "Budget 2025", "Constitution du Sénégal", "Rapports publics"],
|
91 |
+
textbox=gr.Textbox(
|
92 |
+
placeholder="Posez votre question ici...",
|
93 |
+
submit_btn="Envoyer 📤",
|
94 |
+
container=False,
|
95 |
+
scale=7
|
96 |
+
),
|
97 |
+
theme=gr.themes.Soft(),
|
98 |
+
css=css + load_css()
|
99 |
+
)
|
100 |
+
|
101 |
+
def main():
|
102 |
+
chat_interface.launch()
|
103 |
+
|
104 |
+
if __name__ == "__main__":
|
105 |
+
main()
|
custom.css
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
/* Custom theme colors */
|
3 |
+
:root {
|
4 |
+
--primary-color: #0000d3;
|
5 |
+
--secondary-color: #c3c3f5;
|
6 |
+
--background-color: #f8fafc;
|
7 |
+
--text-color: white;
|
8 |
+
--text-secondary: #000050;
|
9 |
+
}
|
10 |
+
|
11 |
+
@media (prefers-color-scheme: dark) {
|
12 |
+
:root {
|
13 |
+
--primary-color: #c3c3f5;
|
14 |
+
--secondary-color: #0000d3;
|
15 |
+
--background-color: #1e1e2e;
|
16 |
+
--text-color: white;
|
17 |
+
--text-secondary: #000050;
|
18 |
+
}
|
19 |
+
|
20 |
+
.chat-interface {
|
21 |
+
background: rgba(30, 30, 46, 0.8) !important;
|
22 |
+
}
|
23 |
+
|
24 |
+
.message {
|
25 |
+
background: rgba(40, 40, 56, 0.8) !important;
|
26 |
+
color: var(--text-color) !important;
|
27 |
+
}
|
28 |
+
|
29 |
+
.input-box {
|
30 |
+
background: rgba(30, 30, 46, 0.9) !important;
|
31 |
+
color: var(--text-color) !important;
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
/* Main container styling */
|
36 |
+
.gradio-container {
|
37 |
+
/* background-color: var(--background-color) !important */
|
38 |
+
background-image: url('https://gradientsss.app/mesh.svg');
|
39 |
+
background-attachment: fixed;
|
40 |
+
background-size: cover;
|
41 |
+
}
|
42 |
+
|
43 |
+
/* Chat interface styling */
|
44 |
+
.chat-interface {
|
45 |
+
max-width: 800px;
|
46 |
+
margin: 0 auto;
|
47 |
+
padding: 2rem;
|
48 |
+
border-radius: 1rem;
|
49 |
+
background: rgba(255, 255, 255, 0.8);
|
50 |
+
backdrop-filter: blur(10px);
|
51 |
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
52 |
+
}
|
53 |
+
|
54 |
+
@media (prefers-color-scheme: dark) {
|
55 |
+
.chat-interface {
|
56 |
+
background: rgba(30, 30, 46, 0.8) !important;
|
57 |
+
}
|
58 |
+
|
59 |
+
.gradio-container {
|
60 |
+
background-color: #1e1e2e !important;
|
61 |
+
}
|
62 |
+
|
63 |
+
.message-wrap {
|
64 |
+
background: rgba(40, 40, 56, 0.8) !important;
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/* Title styling */
|
69 |
+
.title {
|
70 |
+
color: var(--primary-color);
|
71 |
+
font-size: 2.5rem;
|
72 |
+
font-weight: bold;
|
73 |
+
text-align: center;
|
74 |
+
margin-bottom: 1rem;
|
75 |
+
}
|
76 |
+
|
77 |
+
.title span {
|
78 |
+
font-size: 24px;
|
79 |
+
font-weight: 600;
|
80 |
+
}
|
81 |
+
|
82 |
+
/* Message container */
|
83 |
+
.message {
|
84 |
+
padding: 1rem;
|
85 |
+
margin: 0.5rem 0;
|
86 |
+
border-radius: 0.5rem;
|
87 |
+
color: var(--text-color) !important;
|
88 |
+
}
|
89 |
+
|
90 |
+
/* Input box styling */
|
91 |
+
.input-box {
|
92 |
+
border: 2px solid var(--primary-color);
|
93 |
+
border-radius: 0.5rem;
|
94 |
+
padding: 0.75rem;
|
95 |
+
background: white;
|
96 |
+
}
|
97 |
+
|
98 |
+
/* Button styling */
|
99 |
+
button {
|
100 |
+
background: var(--primary-color) !important;
|
101 |
+
color: var(--text-color) !important;
|
102 |
+
border-radius: 0.5rem !important;
|
103 |
+
padding: 0.75rem 1.5rem !important;
|
104 |
+
transition: all 0.3s ease !important;
|
105 |
+
}
|
106 |
+
|
107 |
+
button p {
|
108 |
+
color: var(--text-color) !important;
|
109 |
+
}
|
110 |
+
|
111 |
+
button:hover {
|
112 |
+
background: var(--secondary-color) !important;
|
113 |
+
transform: translateY(-2px);
|
114 |
+
}
|
115 |
+
|
116 |
+
button:hover p {
|
117 |
+
color: var(--text-secondary) !important;
|
118 |
+
}
|
119 |
+
/* footer {visibility: hidden} */
|
requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
smolagents
|
2 |
+
openai
|
3 |
+
gradio
|