AxL95 commited on
Commit
8b2fcca
·
verified ·
1 Parent(s): 41d60be

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,194 +8,166 @@ 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
- 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;
 
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ération de 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];
31
+
32
+ // 2. Appel à l'endpoint chat avec embedding
33
+ const chatRes = await fetch('/api/chat', {
34
+ method: 'POST',
35
+ headers: { 'Content-Type': 'application/json' },
36
+ body: JSON.stringify({ message, embedding: userEmbedding }),
37
+ });
38
+ if (!chatRes.ok) throw new Error(`Chat API error ${chatRes.status}`);
39
+ const { response: botResponse } = await chatRes.json();
40
+
41
+ setMessages(prev => [
42
+ ...prev,
43
+ { sender: 'user', text: message },
44
+ { sender: 'bot', text: botResponse }
45
+ ]);
46
+ } catch (error) {
47
+ console.error('Erreur:', error);
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
+ } finally {
54
+ setIsLoading(false);
55
+ }
56
+ };
57
 
58
  const handleSubmit = (e) => {
59
  e.preventDefault();
60
+ const txt = inputMessage.trim();
61
+ if (!txt) return;
62
+ sendMessage(txt);
 
 
63
  setInputMessage('');
64
+ if (textareaRef.current) textareaRef.current.style.height = 'auto';
65
  };
66
 
67
+ const isMarkdown = (text) => /[#*_>`-]/.test(text);
68
+
69
  return (
70
  <div className="chat-container">
71
  {messages.length === 0 ? (
72
+ <>
73
+ <div className="chat-header">
74
+ <h2 className="chat-title">Medic.ial</h2>
75
+ <Avatar onClick={toLogin} />
76
+ </div>
77
+ <div className="no-messages-view">
78
+ <div className="welcome-content">
79
+ <div className="welcome-message">
80
+ <p>Bonjour ! Comment puis-je vous aider aujourd'hui ? 🧑‍⚕️</p>
81
+ </div>
82
+ <div className="input-container centered">
83
+ <form onSubmit={handleSubmit} className="input-form">
84
+ <textarea
85
+ value={inputMessage}
86
+ onChange={(e) => setInputMessage(e.target.value)}
87
+ placeholder="Posez une question..."
88
+ disabled={isLoading}
89
+ rows="1"
90
+ ref={textareaRef}
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';
100
+ e.target.style.height = `${e.target.scrollHeight}px`;
101
+ }}
102
+ />
103
+ <button type="submit" 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
  <div className="chat-header">
116
+ <Avatar onClick={toLogin} />
117
  <h2 className="chat-title">Medic.ial</h2>
118
  </div>
119
  <div className="messages-container">
120
+ {messages.map((msg, index) => (
121
+ <div key={index} className={`message ${msg.sender}`}>
122
+ <div className="message-content">
123
+ {isMarkdown(msg.text) ? <ReactMarkdown>{msg.text}</ReactMarkdown> : msg.text}
124
+ </div>
125
+ </div>
126
+ ))}
127
+ {isLoading && (
128
+ <div className="message bot">
129
+ <div className="message-content loading">
130
+ <span>.</span><span>.</span><span>.</span>
131
+ </div>
132
+ </div>
133
+ )}
134
+ <div ref={messagesEndRef} />
135
+ </div>
 
 
 
 
136
  <div className="input-container">
137
  <form onSubmit={handleSubmit} className="input-form">
138
+ <textarea
139
  value={inputMessage}
140
+ onChange={(e) => setInputMessage(e.target.value)}
 
141
  placeholder="Tapez votre message ici..."
142
  disabled={isLoading}
143
+ rows="1"
144
  ref={textareaRef}
145
  className="input-textarea"
146
  onKeyDown={(e) => {
147
+ if (e.key === 'Enter' && !e.shiftKey) {
148
+ e.preventDefault();
149
+ handleSubmit(e);
150
  }
151
  }}
152
  onInput={(e) => {
153
+ e.target.style.height = 'auto';
154
+ e.target.style.height = `${e.target.scrollHeight}px`;
155
  }}
156
+ />
157
+ <button type="submit" disabled={isLoading || !inputMessage.trim()}>
158
  <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3">
159
  <path d="M120-160v-240l320-80-320-80v-240l760 320-760 320Z"/>
160
  </svg>
161
  </button>
162
  </form>
163
+ <figcaption className="disclaimer-text">
164
+ Medic.ial est sujet à faire des erreurs. Vérifiez les informations fournies.
165
+ </figcaption>
166
  </div>
167
  </>
168
  )}
169
  </div>
170
  );
171
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
 
173
  export default ChatInterface;