AxL95 commited on
Commit
77db471
·
verified ·
1 Parent(s): 1470fdf

Update frontend/src/components/ChatInterface.jsx

Browse files
frontend/src/components/ChatInterface.jsx CHANGED
@@ -1,219 +1,219 @@
1
- import React, { useState, useRef, useEffect } from 'react';
2
- import ReactMarkdown from 'react-markdown';
3
- import { InferenceClient } from "@huggingface/inference";
4
- import Avatar from './Avatar.jsx';
5
- import '../App.css';
6
-
7
- const ChatInterface = ({ messages = [], setMessages = () => {}, onMessageSent = () => {}, toLogin }) => {
8
- const [inputMessage, setInputMessage] = useState('');
9
- const [isLoading, setIsLoading] = useState(false);
10
- const messagesEndRef = useRef(null);
11
- const textareaRef = useRef(null);
12
-
13
- // Initialisation du client Hugging Face (idéalement dans un .env)
14
- const hfClient = new InferenceClient(process.env.REACT_APP_HF_TOKEN || "votre_token_ici");
15
-
16
- const isMarkdown = (text) => /[#*_>`-]/.test(text);
17
-
18
- const scrollToBottom = () => {
19
- messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
20
- };
21
-
22
- useEffect(() => {
23
- scrollToBottom();
24
- }, [messages]);
25
-
26
- const sendMessage = async (message) => {
27
- try {
28
- setIsLoading(true);
29
-
30
- onMessageSent(message);
31
-
32
- // Appel au modèle Mistral via Hugging Face
33
- const chatCompletion = await hfClient.chatCompletion({
34
- provider: "together", // Vous pouvez aussi utiliser "novita" ou d'autres providers
35
- model: "mistralai/Mistral-7B-Instruct-v0.3",
36
- messages: [
37
- {
38
- role: "system",
39
- content: "Tu es un assistant médical expert spécialisé uniquement dans la schizophrénie. Réponds uniquement aux questions concernant la schizophrénie. Si la question concerne un autre sujet médical, refuse poliment de répondre."
40
- },
41
- {
42
- role: "user",
43
- content: message
44
- }
45
- ],
46
- max_tokens: 512,
47
- temperature: 0.7,
48
- });
49
-
50
- // Extraction de la réponse
51
- const botResponse = chatCompletion.choices[0].message.content;
52
-
53
- setMessages(prev => [
54
- ...prev,
55
- { sender: 'user', text: message },
56
- { sender: 'bot', text: botResponse }
57
- ]);
58
- setIsLoading(false);
59
- } catch (error) {
60
- console.error("Erreur:", error);
61
- setIsLoading(false);
62
- setMessages(prev => [
63
- ...prev,
64
- { sender: 'user', text: message },
65
- { sender: 'bot', text: "Désolé, une erreur s'est produite. Veuillez réessayer. 👍" }
66
- ]);
67
- }
68
- };
69
-
70
-
71
-
72
- const handleSubmit = (e) => {
73
- e.preventDefault();
74
- if (inputMessage.trim() === '') return;
75
- sendMessage(inputMessage);
76
- if (textareaRef.current) {
77
- textareaRef.current.style.height = 'auto';
78
- }
79
- setInputMessage('');
80
-
81
- };
82
-
83
- // Le reste du composant reste inchangé
84
- return (
85
- <div className="chat-container">
86
- {messages.length === 0 ? (
87
- <>
88
- <div className="chat-header">
89
- <h2 className="chat-title">Medic.ial</h2>
90
- <Avatar onClick={toLogin}/>
91
- </div>
92
- <div className="no-messages-view">
93
- <div className="welcome-content">
94
- <div className="welcome-message">
95
- <p>Bonjour ! Comment puis-je vous aider aujourd'hui ? 🧑‍⚕️</p>
96
- </div>
97
- <div className="input-container centered">
98
- <form onSubmit={handleSubmit} className="input-form">
99
- <textarea
100
- value={inputMessage}
101
- onChange={(e) => setInputMessage(e.target.value)}
102
- placeholder="Posez une question..."
103
- disabled={isLoading}
104
- rows="1"
105
- className="input-textarea"
106
- onKeyDown={(e) => {
107
- if (e.key === "Enter" && !e.shiftKey) {
108
- e.preventDefault();
109
- handleSubmit(e);
110
- }
111
- }}
112
- onInput={(e) => {
113
- e.target.style.height = "auto"; // Réinitialise la hauteur
114
- e.target.style.height = `${e.target.scrollHeight}px`; // Ajuste à la hauteur du contenu
115
- }}
116
- />
117
- <button type="submit" style={{background:"none"}} disabled={isLoading || inputMessage.trim() === ''}>
118
- <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3">
119
- <path d="M120-160v-240l320-80-320-80v-240l760 320-760 320Z"/>
120
- </svg>
121
- </button>
122
- </form>
123
- </div>
124
- </div>
125
- </div>
126
- </>
127
-
128
- ) : (
129
- <>
130
- <div className="chat-header">
131
- <Avatar onClick={toLogin}/>
132
- <h2 className="chat-title">Medic.ial</h2>
133
- </div>
134
- <div className="messages-container">
135
- {messages.map((msg, index) => (
136
- <div key={index} className={`message ${msg.sender}`}>
137
- <div className="message-content">
138
- {isMarkdown(msg.text) ? (
139
- <ReactMarkdown>{msg.text}</ReactMarkdown>
140
- ) : (
141
- msg.text
142
- )}
143
- </div>
144
- </div>
145
- ))}
146
- {isLoading && (
147
- <div className="message bot">
148
- <div className="message-content loading">
149
- <span>.</span><span>.</span><span>.</span>
150
- </div>
151
- </div>
152
- )}
153
- <div ref={messagesEndRef} />
154
- </div>
155
- <div className="input-container">
156
- <form onSubmit={handleSubmit} className="input-form">
157
- <textarea
158
- value={inputMessage}
159
- onChange={(e) => setInputMessage(e.target.value)
160
- }
161
- placeholder="Tapez votre message ici..."
162
- disabled={isLoading}
163
- rows="1"
164
- ref={textareaRef}
165
- className="input-textarea"
166
- onKeyDown={(e) => {
167
- if (e.key === "Enter" && !e.shiftKey) {
168
- e.preventDefault();
169
- handleSubmit(e);
170
- }
171
- }}
172
- onInput={(e) => {
173
- e.target.style.height = "auto";
174
- e.target.style.height = `${e.target.scrollHeight}px`;
175
- }}
176
- />
177
- <button type="submit" disabled={isLoading || inputMessage.trim() === ''}>
178
- <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3">
179
- <path d="M120-160v-240l320-80-320-80v-240l760 320-760 320Z"/>
180
- </svg>
181
- </button>
182
- </form>
183
- <figcaption className="disclaimer-text">Medic.ial est sujet à faire des erreurs. Vérifiez les informations fournies.</figcaption>
184
- </div>
185
- </>
186
- )}
187
- </div>
188
- );
189
- };
190
- /*const UserList = () => {
191
- const [users, setUsers] = useState([]);
192
-
193
- useEffect(() => {
194
- const fetchUsers = async () => {
195
- try {
196
- const response = await fetch('/.netlify/functions/get_users');
197
- const data = await response.json();
198
- setUsers(data);
199
- } catch (error) {
200
- console.error('An error occurred while fetching users:', error);
201
- }
202
- };
203
-
204
- fetchUsers();
205
- }, []);
206
-
207
- return (
208
- <div>
209
- <h1>User List</h1>
210
- <ul>
211
- {users.map((user, index) => (
212
- <li key={index}>{user[1]} - {user[2]}</li>
213
- ))}
214
- </ul>
215
- </div>
216
- );
217
- };*/
218
-
219
- export default ChatInterface;
 
1
+ import React, { useState, useRef, useEffect } from 'react';
2
+ import ReactMarkdown from 'react-markdown';
3
+ import { InferenceClient } from "@huggingface/inference";
4
+ import Avatar from './Avatar.jsx';
5
+ import '../App.css';
6
+
7
+ const ChatInterface = ({ messages = [], setMessages = () => {}, onMessageSent = () => {}, toLogin }) => {
8
+ const [inputMessage, setInputMessage] = useState('');
9
+ const [isLoading, setIsLoading] = useState(false);
10
+ const messagesEndRef = useRef(null);
11
+ const textareaRef = useRef(null);
12
+
13
+ // Initialisation du client Hugging Face (idéalement dans un .env)
14
+ const hfClient = new InferenceClient(process.env.REACT_APP_HF_TOKEN || "votre_token_ici");
15
+
16
+ const isMarkdown = (text) => /[#*_>`-]/.test(text);
17
+
18
+ const scrollToBottom = () => {
19
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
20
+ };
21
+
22
+ useEffect(() => {
23
+ scrollToBottom();
24
+ }, [messages]);
25
+
26
+ const sendMessage = async (message) => {
27
+ try {
28
+ setIsLoading(true);
29
+
30
+ onMessageSent(message);
31
+
32
+ // Appel au modèle Mistral via Hugging Face
33
+ const chatCompletion = await hfClient.chatCompletion({
34
+ provider: "novita", // Vous pouvez aussi utiliser "novita" ou d'autres providers
35
+ model: "mistralai/Mistral-7B-Instruct-v0.3",
36
+ messages: [
37
+ {
38
+ role: "system",
39
+ content: "Tu es un assistant médical expert spécialisé uniquement dans la schizophrénie. Réponds uniquement aux questions concernant la schizophrénie. Si la question concerne un autre sujet médical, refuse poliment de répondre."
40
+ },
41
+ {
42
+ role: "user",
43
+ content: message
44
+ }
45
+ ],
46
+ max_tokens: 512,
47
+ temperature: 0.7,
48
+ });
49
+
50
+ // Extraction de la réponse
51
+ const botResponse = chatCompletion.choices[0].message.content;
52
+
53
+ setMessages(prev => [
54
+ ...prev,
55
+ { sender: 'user', text: message },
56
+ { sender: 'bot', text: botResponse }
57
+ ]);
58
+ setIsLoading(false);
59
+ } catch (error) {
60
+ console.error("Erreur:", error);
61
+ setIsLoading(false);
62
+ setMessages(prev => [
63
+ ...prev,
64
+ { sender: 'user', text: message },
65
+ { sender: 'bot', text: "Désolé, une erreur s'est produite. Veuillez réessayer. 👍" }
66
+ ]);
67
+ }
68
+ };
69
+
70
+
71
+
72
+ const handleSubmit = (e) => {
73
+ e.preventDefault();
74
+ if (inputMessage.trim() === '') return;
75
+ sendMessage(inputMessage);
76
+ if (textareaRef.current) {
77
+ textareaRef.current.style.height = 'auto';
78
+ }
79
+ setInputMessage('');
80
+
81
+ };
82
+
83
+ // Le reste du composant reste inchangé
84
+ return (
85
+ <div className="chat-container">
86
+ {messages.length === 0 ? (
87
+ <>
88
+ <div className="chat-header">
89
+ <h2 className="chat-title">Medic.ial</h2>
90
+ <Avatar onClick={toLogin}/>
91
+ </div>
92
+ <div className="no-messages-view">
93
+ <div className="welcome-content">
94
+ <div className="welcome-message">
95
+ <p>Bonjour ! Comment puis-je vous aider aujourd'hui ? 🧑‍⚕️</p>
96
+ </div>
97
+ <div className="input-container centered">
98
+ <form onSubmit={handleSubmit} className="input-form">
99
+ <textarea
100
+ value={inputMessage}
101
+ onChange={(e) => setInputMessage(e.target.value)}
102
+ placeholder="Posez une question..."
103
+ disabled={isLoading}
104
+ rows="1"
105
+ className="input-textarea"
106
+ onKeyDown={(e) => {
107
+ if (e.key === "Enter" && !e.shiftKey) {
108
+ e.preventDefault();
109
+ handleSubmit(e);
110
+ }
111
+ }}
112
+ onInput={(e) => {
113
+ e.target.style.height = "auto"; // Réinitialise la hauteur
114
+ e.target.style.height = `${e.target.scrollHeight}px`; // Ajuste à la hauteur du contenu
115
+ }}
116
+ />
117
+ <button type="submit" style={{background:"none"}} disabled={isLoading || inputMessage.trim() === ''}>
118
+ <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3">
119
+ <path d="M120-160v-240l320-80-320-80v-240l760 320-760 320Z"/>
120
+ </svg>
121
+ </button>
122
+ </form>
123
+ </div>
124
+ </div>
125
+ </div>
126
+ </>
127
+
128
+ ) : (
129
+ <>
130
+ <div className="chat-header">
131
+ <Avatar onClick={toLogin}/>
132
+ <h2 className="chat-title">Medic.ial</h2>
133
+ </div>
134
+ <div className="messages-container">
135
+ {messages.map((msg, index) => (
136
+ <div key={index} className={`message ${msg.sender}`}>
137
+ <div className="message-content">
138
+ {isMarkdown(msg.text) ? (
139
+ <ReactMarkdown>{msg.text}</ReactMarkdown>
140
+ ) : (
141
+ msg.text
142
+ )}
143
+ </div>
144
+ </div>
145
+ ))}
146
+ {isLoading && (
147
+ <div className="message bot">
148
+ <div className="message-content loading">
149
+ <span>.</span><span>.</span><span>.</span>
150
+ </div>
151
+ </div>
152
+ )}
153
+ <div ref={messagesEndRef} />
154
+ </div>
155
+ <div className="input-container">
156
+ <form onSubmit={handleSubmit} className="input-form">
157
+ <textarea
158
+ value={inputMessage}
159
+ onChange={(e) => setInputMessage(e.target.value)
160
+ }
161
+ placeholder="Tapez votre message ici..."
162
+ disabled={isLoading}
163
+ rows="1"
164
+ ref={textareaRef}
165
+ className="input-textarea"
166
+ onKeyDown={(e) => {
167
+ if (e.key === "Enter" && !e.shiftKey) {
168
+ e.preventDefault();
169
+ handleSubmit(e);
170
+ }
171
+ }}
172
+ onInput={(e) => {
173
+ e.target.style.height = "auto";
174
+ e.target.style.height = `${e.target.scrollHeight}px`;
175
+ }}
176
+ />
177
+ <button type="submit" disabled={isLoading || inputMessage.trim() === ''}>
178
+ <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3">
179
+ <path d="M120-160v-240l320-80-320-80v-240l760 320-760 320Z"/>
180
+ </svg>
181
+ </button>
182
+ </form>
183
+ <figcaption className="disclaimer-text">Medic.ial est sujet à faire des erreurs. Vérifiez les informations fournies.</figcaption>
184
+ </div>
185
+ </>
186
+ )}
187
+ </div>
188
+ );
189
+ };
190
+ /*const UserList = () => {
191
+ const [users, setUsers] = useState([]);
192
+
193
+ useEffect(() => {
194
+ const fetchUsers = async () => {
195
+ try {
196
+ const response = await fetch('/.netlify/functions/get_users');
197
+ const data = await response.json();
198
+ setUsers(data);
199
+ } catch (error) {
200
+ console.error('An error occurred while fetching users:', error);
201
+ }
202
+ };
203
+
204
+ fetchUsers();
205
+ }, []);
206
+
207
+ return (
208
+ <div>
209
+ <h1>User List</h1>
210
+ <ul>
211
+ {users.map((user, index) => (
212
+ <li key={index}>{user[1]} - {user[2]}</li>
213
+ ))}
214
+ </ul>
215
+ </div>
216
+ );
217
+ };*/
218
+
219
+ export default ChatInterface;