AxL95 commited on
Commit
41d60be
·
verified ·
1 Parent(s): 20bd18d

Update frontend/src/components/ChatInterface.jsx

Browse files
frontend/src/components/ChatInterface.jsx CHANGED
@@ -1,5 +1,6 @@
1
  import React, { useState, useRef, useEffect } from 'react';
2
  import ReactMarkdown from 'react-markdown';
 
3
  import Avatar from './Avatar.jsx';
4
  import '../App.css';
5
 
@@ -8,124 +9,194 @@ const ChatInterface = ({ messages = [], setMessages = () => {}, onMessageSent =
8
  const [isLoading, setIsLoading] = useState(false);
9
  const messagesEndRef = useRef(null);
10
  const textareaRef = useRef(null);
 
 
 
 
 
11
 
12
  const scrollToBottom = () => {
13
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
14
  };
15
- useEffect(scrollToBottom, [messages]);
16
 
17
- const sendMessage = async (message) => {
18
- try {
19
- setIsLoading(true);
20
- onMessageSent(message);
21
-
22
- // 1️⃣ – récupérer l'embedding
23
- const embedRes = await fetch('/api/embed', {
24
- method: 'POST',
25
- headers: { 'Content-Type': 'application/json' },
26
- body: JSON.stringify({ texts: [message] }),
27
- });
28
- if (!embedRes.ok) throw new Error(`Embed API error ${embedRes.status}`);
29
- const { embeddings } = await embedRes.json();
30
- const userEmbedding = embeddings[0]; // vecteur
31
 
32
- console.log('User embedding:', userEmbedding);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
- // 2️⃣ – envoyer au chat endpoint (on peut inclure l'embedding si besoin pour RAG)
35
- const chatRes = await fetch('/api/chat', {
36
- method: 'POST',
37
- headers: { 'Content-Type': 'application/json' },
38
- body: JSON.stringify({
39
- message,
40
- embedding: userEmbedding, // optionnel selon ton backend
41
- }),
42
- });
43
- if (!chatRes.ok) throw new Error(`Chat API error ${chatRes.status}`);
44
- const { response: botResponse } = await chatRes.json();
45
-
46
- setMessages(prev => [
47
- ...prev,
48
- { sender: 'user', text: message },
49
- { sender: 'bot', text: botResponse }
50
- ]);
51
- } catch (error) {
52
- console.error(error);
53
- setMessages(prev => [
54
- ...prev,
55
- { sender: 'user', text: message },
56
- { sender: 'bot', text: "Désolé, une erreur s'est produite. Veuillez réessayer." }
57
- ]);
58
- } finally {
59
- setIsLoading(false);
60
- }
61
- };
62
 
63
  const handleSubmit = (e) => {
64
  e.preventDefault();
65
- const txt = inputMessage.trim();
66
- if (!txt) return;
67
- sendMessage(txt);
 
 
68
  setInputMessage('');
69
- if (textareaRef.current) textareaRef.current.style.height = 'auto';
70
  };
71
 
 
72
  return (
73
  <div className="chat-container">
74
- <div className="chat-header">
75
- <Avatar onClick={toLogin}/>
76
- <h2 className="chat-title">Medic.ial</h2>
77
- </div>
78
- <div className="messages-container">
79
- {messages.map((msg, i) => (
80
- <div key={i} className={`message ${msg.sender}`}>
81
- <div className="message-content">
82
- {/#|\*|_|`|>/.test(msg.text)
83
- ? <ReactMarkdown>{msg.text}</ReactMarkdown>
84
- : msg.text
85
- }
86
- </div>
87
- </div>
88
- ))}
89
- {isLoading && (
90
- <div className="message bot">
91
- <div className="message-content loading"><span>.</span><span>.</span><span>.</span></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  </div>
 
 
 
 
 
 
 
 
93
  )}
94
- <div ref={messagesEndRef} />
95
  </div>
96
-
97
- <form onSubmit={handleSubmit} className="input-form">
98
- <textarea
99
- ref={textareaRef}
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';
114
- e.target.style.height = `${e.target.scrollHeight}px`;
115
- }}
116
- />
117
- <button type="submit" 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
-
124
- <figcaption className="disclaimer-text">
125
- Medic.ial est sujet à faire des erreurs. Vérifiez les informations fournies.
126
- </figcaption>
 
 
 
 
 
 
 
 
 
 
 
 
127
  </div>
128
  );
129
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
  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
 
 
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 || "token");
15
+ console.log(process.env.REACT_APP_HF_TOKEN);
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
+ onMessageSent(message);
30
+ const response = await fetch("/api/chat", {
31
+ method: "POST",
32
+ headers: {
33
+ "Content-Type": "application/json"
34
+ },
35
+ body: JSON.stringify({ message })
36
+ });
37
+ const data = await response.json();
38
+ const botResponse = data.response;
39
+ setMessages(prev => [
40
+ ...prev,
41
+ { sender: 'user', text: message },
42
+ { sender: 'bot', text: botResponse }
43
+ ]);
44
+ setIsLoading(false);
45
+ } catch (error) {
46
+ console.error("Erreur:", error);
47
+ setIsLoading(false);
48
+ setMessages(prev => [
49
+ ...prev,
50
+ { sender: 'user', text: message },
51
+ { sender: 'bot', text: "Désolé, une erreur s'est produite. Veuillez réessayer. 👍" }
52
+ ]);
53
+ }
54
+ };
55
 
56
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  const handleSubmit = (e) => {
59
  e.preventDefault();
60
+ if (inputMessage.trim() === '') return;
61
+ sendMessage(inputMessage);
62
+ if (textareaRef.current) {
63
+ textareaRef.current.style.height = 'auto';
64
+ }
65
  setInputMessage('');
66
+
67
  };
68
 
69
+ // Le reste du composant reste inchangé
70
  return (
71
  <div className="chat-container">
72
+ {messages.length === 0 ? (
73
+ <>
74
+ <div className="chat-header">
75
+ <h2 className="chat-title">Medic.ial</h2>
76
+ <Avatar onClick={toLogin}/>
77
+ </div>
78
+ <div className="no-messages-view">
79
+ <div className="welcome-content">
80
+ <div className="welcome-message">
81
+ <p>Bonjour ! Comment puis-je vous aider aujourd'hui ? 🧑‍⚕️</p>
82
+ </div>
83
+ <div className="input-container centered">
84
+ <form onSubmit={handleSubmit} className="input-form">
85
+ <textarea
86
+ value={inputMessage}
87
+ onChange={(e) => setInputMessage(e.target.value)}
88
+ placeholder="Posez une question..."
89
+ disabled={isLoading}
90
+ rows="1"
91
+ className="input-textarea"
92
+ onKeyDown={(e) => {
93
+ if (e.key === "Enter" && !e.shiftKey) {
94
+ e.preventDefault();
95
+ handleSubmit(e);
96
+ }
97
+ }}
98
+ onInput={(e) => {
99
+ e.target.style.height = "auto"; // Réinitialise la hauteur
100
+ e.target.style.height = `${e.target.scrollHeight}px`; // Ajuste à la hauteur du contenu
101
+ }}
102
+ />
103
+ <button type="submit" style={{background:"none"}} disabled={isLoading || inputMessage.trim() === ''}>
104
+ <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3">
105
+ <path d="M120-160v-240l320-80-320-80v-240l760 320-760 320Z"/>
106
+ </svg>
107
+ </button>
108
+ </form>
109
+ </div>
110
+ </div>
111
+ </div>
112
+ </>
113
+
114
+ ) : (
115
+ <>
116
+ <div className="chat-header">
117
+ <Avatar onClick={toLogin}/>
118
+ <h2 className="chat-title">Medic.ial</h2>
119
  </div>
120
+ <div className="messages-container">
121
+ {messages.map((msg, index) => (
122
+ <div key={index} className={`message ${msg.sender}`}>
123
+ <div className="message-content">
124
+ {isMarkdown(msg.text) ? (
125
+ <ReactMarkdown>{msg.text}</ReactMarkdown>
126
+ ) : (
127
+ msg.text
128
  )}
 
129
  </div>
130
+ </div>
131
+ ))}
132
+ {isLoading && (
133
+ <div className="message bot">
134
+ <div className="message-content loading">
135
+ <span>.</span><span>.</span><span>.</span>
136
+ </div>
137
+ </div>
138
+ )}
139
+ <div ref={messagesEndRef} />
140
+ </div>
141
+ <div className="input-container">
142
+ <form onSubmit={handleSubmit} className="input-form">
143
+ <textarea
144
+ value={inputMessage}
145
+ onChange={(e) => setInputMessage(e.target.value)
146
+ }
147
+ placeholder="Tapez votre message ici..."
148
+ disabled={isLoading}
149
+ rows="1"
150
+ ref={textareaRef}
151
+ className="input-textarea"
152
+ onKeyDown={(e) => {
153
+ if (e.key === "Enter" && !e.shiftKey) {
154
+ e.preventDefault();
155
+ handleSubmit(e);
156
+ }
157
+ }}
158
+ onInput={(e) => {
159
+ e.target.style.height = "auto";
160
+ e.target.style.height = `${e.target.scrollHeight}px`;
161
+ }}
162
+ />
163
+ <button type="submit" disabled={isLoading || inputMessage.trim() === ''}>
164
+ <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3">
165
+ <path d="M120-160v-240l320-80-320-80v-240l760 320-760 320Z"/>
166
+ </svg>
167
+ </button>
168
+ </form>
169
+ <figcaption className="disclaimer-text">Medic.ial est sujet à faire des erreurs. Vérifiez les informations fournies.</figcaption>
170
+ </div>
171
+ </>
172
+ )}
173
  </div>
174
  );
175
  };
176
+ /*const UserList = () => {
177
+ const [users, setUsers] = useState([]);
178
+ useEffect(() => {
179
+ const fetchUsers = async () => {
180
+ try {
181
+ const response = await fetch('/.netlify/functions/get_users');
182
+ const data = await response.json();
183
+ setUsers(data);
184
+ } catch (error) {
185
+ console.error('An error occurred while fetching users:', error);
186
+ }
187
+ };
188
+ fetchUsers();
189
+ }, []);
190
+ return (
191
+ <div>
192
+ <h1>User List</h1>
193
+ <ul>
194
+ {users.map((user, index) => (
195
+ <li key={index}>{user[1]} - {user[2]}</li>
196
+ ))}
197
+ </ul>
198
+ </div>
199
+ );
200
+ };*/
201
 
202
  export default ChatInterface;