AxL95 commited on
Commit
20bd18d
·
verified ·
1 Parent(s): 8d88407

Update frontend/src/components/ChatInterface.jsx

Browse files
frontend/src/components/ChatInterface.jsx CHANGED
@@ -1,6 +1,5 @@
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,197 +8,124 @@ const ChatInterface = ({ messages = [], setMessages = () => {}, onMessageSent =
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
-
179
- useEffect(() => {
180
- const fetchUsers = async () => {
181
- try {
182
- const response = await fetch('/.netlify/functions/get_users');
183
- const data = await response.json();
184
- setUsers(data);
185
- } catch (error) {
186
- console.error('An error occurred while fetching users:', error);
187
- }
188
- };
189
 
190
- fetchUsers();
191
- }, []);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
 
193
- return (
194
- <div>
195
- <h1>User List</h1>
196
- <ul>
197
- {users.map((user, index) => (
198
- <li key={index}>{user[1]} - {user[2]}</li>
199
- ))}
200
- </ul>
201
  </div>
202
  );
203
- };*/
204
 
205
  export default ChatInterface;
 
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
  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;