135 lines
4.8 KiB
JavaScript
135 lines
4.8 KiB
JavaScript
import React, { useState } from "react";
|
||
import axios from "axios";
|
||
import "./Chatbot.css";
|
||
|
||
const Chatbot = ({ context }) => {
|
||
|
||
const [messages, setMessages] = useState([
|
||
{
|
||
role: "assistant",
|
||
content:
|
||
"Hi! I’m here to help you with career suggestions, ROI analysis, and any questions you have about your career. How can I assist you today?",
|
||
},
|
||
]);
|
||
const [input, setInput] = useState("");
|
||
const [loading, setLoading] = useState(false);
|
||
|
||
const sendMessage = async (content) => {
|
||
const userMessage = { role: "user", content };
|
||
|
||
// Ensure career data is injected into every API call
|
||
const contextSummary = `
|
||
You are an advanced AI career advisor for AptivaAI.
|
||
Your role is to not only provide career suggestions but to analyze them based on salary potential, job stability, education costs, and market trends.
|
||
|
||
Use the following user-specific data:
|
||
- Career Suggestions: ${context.careerSuggestions?.map((c) => c.title).join(", ") || "No suggestions available."}
|
||
- Selected Career: ${context.selectedCareer?.title || "None"}
|
||
- Job Description: ${context.careerDetails?.jobDescription || "No job description available."}
|
||
- Expected Tasks: ${context.careerDetails?.tasks?.join(", ") || "No tasks available."}
|
||
- Salary Data:
|
||
${context.salaryData?.length > 0
|
||
? context.salaryData.map(sd => `${sd.percentile}: $${sd.regionalSalary || "N/A"} (Regional), $${sd.nationalSalary || "N/A"} (National)`).join(", ")
|
||
: "Not available"}
|
||
- Schools Available: ${
|
||
context.schools?.length > 0
|
||
? context.schools
|
||
.map(school => `${school.INSTNM} (Distance: ${school.distance || "N/A"}, Tuition: $${school["In_state cost"] || "N/A"})`)
|
||
.join("; ")
|
||
: "No schools available."
|
||
}
|
||
|
||
- Economic Projections: ${
|
||
context.economicProjections && Object.keys(context.economicProjections).length > 0
|
||
? `2022 Employment: ${context.economicProjections["2022 Employment"] || "N/A"}, ` +
|
||
`2032 Employment: ${context.economicProjections["2032 Employment"] || "N/A"}, ` +
|
||
`Total Change: ${context.economicProjections["Total Change"] || "N/A"}`
|
||
: "Not available"
|
||
}
|
||
|
||
- User State: ${context.userState || "Not provided"}
|
||
- User Area: ${context.areaTitle || "Not provided"}
|
||
- User Zipcode: ${context.userZipcode || "Not provided"}
|
||
|
||
**Your response should ALWAYS provide analysis, not just list careers.**
|
||
Example responses:
|
||
- "If you're looking for a high salary right away, X might be a great option, but it has slow growth."
|
||
- "If you prefer job stability, Y is projected to grow in demand over the next 10 years."
|
||
- "If work-life balance is a priority, avoid Z as it has high stress and irregular hours."
|
||
|
||
If the user asks about "the best career," do not assume a single best choice. Instead, explain trade-offs like:
|
||
- "If you want high pay now, X is great, but it has limited upward growth."
|
||
- "If you prefer stability, Y is a better long-term bet."
|
||
`;
|
||
|
||
const messagesToSend = [
|
||
{ role: "system", content: contextSummary }, // Inject AptivaAI data on every request
|
||
...messages,
|
||
userMessage,
|
||
];
|
||
|
||
try {
|
||
setLoading(true);
|
||
const response = await axios.post(
|
||
"https://api.openai.com/v1/chat/completions",
|
||
{
|
||
model: "gpt-3.5-turbo",
|
||
messages: messagesToSend,
|
||
temperature: 0.7,
|
||
},
|
||
{
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
Authorization: `Bearer ${process.env.REACT_APP_OPENAI_API_KEY}`,
|
||
},
|
||
}
|
||
);
|
||
|
||
const botMessage = response.data.choices[0].message;
|
||
setMessages([...messages, userMessage, botMessage]);
|
||
} catch (error) {
|
||
console.error("Chatbot Error:", error);
|
||
setMessages([
|
||
...messages,
|
||
userMessage,
|
||
{ role: "assistant", content: "Error: Unable to fetch response. Please try again." },
|
||
]);
|
||
} finally {
|
||
setLoading(false);
|
||
setInput("");
|
||
}
|
||
};
|
||
|
||
const handleSubmit = (e) => {
|
||
e.preventDefault();
|
||
if (input.trim()) {
|
||
sendMessage(input.trim());
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="chatbot-container">
|
||
<div className="chat-messages">
|
||
{messages.map((msg, index) => (
|
||
<div key={index} className={`message ${msg.role}`}>
|
||
{msg.content}
|
||
</div>
|
||
))}
|
||
{loading && <div className="message assistant">Typing...</div>}
|
||
</div>
|
||
<form onSubmit={handleSubmit} className="chat-input-form">
|
||
<input
|
||
type="text"
|
||
placeholder="Ask a question..."
|
||
value={input}
|
||
onChange={(e) => setInput(e.target.value)}
|
||
/>
|
||
<button type="submit" disabled={loading}>
|
||
Send
|
||
</button>
|
||
</form>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default Chatbot; |