Spaces:
Running
Running
Support user-provided HF token instead of env variable
Browse filesmodified: README.md
modified: src/components/ChatInterface.jsx
new file: src/components/TokenInput.jsx
deleted: src/utils/hfClient.js
- README.md +1 -13
- src/components/ChatInterface.jsx +17 -2
- src/components/TokenInput.jsx +27 -0
- src/utils/hfClient.js +0 -5
README.md
CHANGED
|
@@ -17,24 +17,12 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo
|
|
| 17 |
|
| 18 |
## Features
|
| 19 |
|
| 20 |
-
-
|
| 21 |
- Support UI to send user input and get response of the chatbot.
|
| 22 |
- Keep user input and response in chat history.
|
| 23 |
|
| 24 |
## Usage
|
| 25 |
|
| 26 |
-
### Prerequisite
|
| 27 |
-
|
| 28 |
-
- Create a test token on Hugging Face with read access only.
|
| 29 |
-
- Export it in your shell:\
|
| 30 |
-
`export REACT_APP_HF_TOKEN=your_test_token`
|
| 31 |
-
|
| 32 |
-
### Security note
|
| 33 |
-
|
| 34 |
-
- The token is bundled into client-side JS and visible in browser DevTools.
|
| 35 |
-
- For testing, create a temporary token with read-only permission.
|
| 36 |
-
- After testing, revoke or delete the token to prevent exposure.
|
| 37 |
-
|
| 38 |
### Development mode
|
| 39 |
|
| 40 |
- `npm start`
|
|
|
|
| 17 |
|
| 18 |
## Features
|
| 19 |
|
| 20 |
+
- Support user input of Hugging Face Access Token.
|
| 21 |
- Support UI to send user input and get response of the chatbot.
|
| 22 |
- Keep user input and response in chat history.
|
| 23 |
|
| 24 |
## Usage
|
| 25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
### Development mode
|
| 27 |
|
| 28 |
- `npm start`
|
src/components/ChatInterface.jsx
CHANGED
|
@@ -1,13 +1,19 @@
|
|
| 1 |
import { useState } from "react";
|
| 2 |
-
import { hf } from "../utils/hfClient";
|
| 3 |
import MessageInput from "./MessageInput";
|
| 4 |
import MessagePair from "./MessagePair";
|
|
|
|
| 5 |
|
| 6 |
export default function ChatInterface() {
|
|
|
|
| 7 |
const [chatHistory, setChatHistory] = useState([]);
|
| 8 |
|
| 9 |
const handleMessageSend = async (message) => {
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
model: "openai/gpt-oss-20b",
|
| 12 |
messages: [{ role: "user", content: message }],
|
| 13 |
});
|
|
@@ -17,6 +23,10 @@ export default function ChatInterface() {
|
|
| 17 |
setChatHistory([newPair, ...chatHistory]);
|
| 18 |
};
|
| 19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
return (
|
| 21 |
<div
|
| 22 |
style={{
|
|
@@ -28,6 +38,11 @@ export default function ChatInterface() {
|
|
| 28 |
gap: "24px",
|
| 29 |
}}
|
| 30 |
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
{/* Input area */}
|
| 32 |
<div>
|
| 33 |
<MessageInput onSend={handleMessageSend} />
|
|
|
|
| 1 |
import { useState } from "react";
|
|
|
|
| 2 |
import MessageInput from "./MessageInput";
|
| 3 |
import MessagePair from "./MessagePair";
|
| 4 |
+
import TokenInput from "./TokenInput";
|
| 5 |
|
| 6 |
export default function ChatInterface() {
|
| 7 |
+
const [hfClient, setHFClient] = useState(null);
|
| 8 |
const [chatHistory, setChatHistory] = useState([]);
|
| 9 |
|
| 10 |
const handleMessageSend = async (message) => {
|
| 11 |
+
if (!hfClient) {
|
| 12 |
+
alert("Please enter a valid Hugging Face token first.");
|
| 13 |
+
return;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
const result = await hfClient.chatCompletion({
|
| 17 |
model: "openai/gpt-oss-20b",
|
| 18 |
messages: [{ role: "user", content: message }],
|
| 19 |
});
|
|
|
|
| 23 |
setChatHistory([newPair, ...chatHistory]);
|
| 24 |
};
|
| 25 |
|
| 26 |
+
const handleHFClientReady = (client) => {
|
| 27 |
+
setHFClient(client);
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
return (
|
| 31 |
<div
|
| 32 |
style={{
|
|
|
|
| 38 |
gap: "24px",
|
| 39 |
}}
|
| 40 |
>
|
| 41 |
+
{/* Token input */}
|
| 42 |
+
<div>
|
| 43 |
+
<TokenInput onHFClientReady={handleHFClientReady} />
|
| 44 |
+
</div>
|
| 45 |
+
|
| 46 |
{/* Input area */}
|
| 47 |
<div>
|
| 48 |
<MessageInput onSend={handleMessageSend} />
|
src/components/TokenInput.jsx
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { InferenceClient } from "@huggingface/inference";
|
| 2 |
+
import { useState } from "react";
|
| 3 |
+
|
| 4 |
+
export default function TokenInput({ onHFClientReady }) {
|
| 5 |
+
const [token, setToken] = useState("");
|
| 6 |
+
|
| 7 |
+
const handleConfirm = async () => {
|
| 8 |
+
if (!token.trim()) return;
|
| 9 |
+
const client = new InferenceClient(token);
|
| 10 |
+
onHFClientReady(client);
|
| 11 |
+
};
|
| 12 |
+
|
| 13 |
+
return (
|
| 14 |
+
<div style={{ display: "flex", gap: "10px" }}>
|
| 15 |
+
<input
|
| 16 |
+
type="password"
|
| 17 |
+
value={token}
|
| 18 |
+
onChange={(e) => setToken(e.target.value)}
|
| 19 |
+
placeholder="Enter Hugging Face token"
|
| 20 |
+
style={{ flex: 1, padding: "10px", fontSize: "16px" }}
|
| 21 |
+
/>
|
| 22 |
+
<button onClick={handleConfirm} style={{ padding: "10px 20px" }}>
|
| 23 |
+
Confirm
|
| 24 |
+
</button>
|
| 25 |
+
</div>
|
| 26 |
+
);
|
| 27 |
+
}
|
src/utils/hfClient.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
| 1 |
-
import { InferenceClient } from "@huggingface/inference";
|
| 2 |
-
|
| 3 |
-
const HF_TOKEN = process.env.REACT_APP_HF_TOKEN;
|
| 4 |
-
|
| 5 |
-
export const hf = new InferenceClient(HF_TOKEN);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|