AI Coach fixed
This commit is contained in:
@@ -29,7 +29,7 @@ const AICoach: React.FC<AICoachProps> = ({ history, lang }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
const chat = createFitnessChat(history);
|
const chat = createFitnessChat(history, lang);
|
||||||
if (chat) {
|
if (chat) {
|
||||||
chatSessionRef.current = chat;
|
chatSessionRef.current = chat;
|
||||||
} else {
|
} else {
|
||||||
@@ -108,8 +108,8 @@ const AICoach: React.FC<AICoachProps> = ({ history, lang }) => {
|
|||||||
{messages.map((msg) => (
|
{messages.map((msg) => (
|
||||||
<div key={msg.id} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
|
<div key={msg.id} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
|
||||||
<div className={`max-w-[85%] p-4 rounded-[20px] text-sm leading-relaxed shadow-sm ${msg.role === 'user'
|
<div className={`max-w-[85%] p-4 rounded-[20px] text-sm leading-relaxed shadow-sm ${msg.role === 'user'
|
||||||
? 'bg-primary text-on-primary rounded-br-none'
|
? 'bg-primary text-on-primary rounded-br-none'
|
||||||
: 'bg-surface-container-high text-on-surface border border-outline-variant/20 rounded-bl-none'
|
: 'bg-surface-container-high text-on-surface border border-outline-variant/20 rounded-bl-none'
|
||||||
}`}>
|
}`}>
|
||||||
{msg.text}
|
{msg.text}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import jwt from 'jsonwebtoken';
|
|||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const JWT_SECRET = process.env.JWT_SECRET || 'secret';
|
const JWT_SECRET = process.env.JWT_SECRET || 'secret';
|
||||||
const API_KEY = process.env.API_KEY;
|
const API_KEY = process.env.API_KEY;
|
||||||
const MODEL_ID = 'gemini-1.5-flash';
|
const MODEL_ID = 'gemini-2.0-flash';
|
||||||
|
|
||||||
const authenticate = (req: any, res: any, next: any) => {
|
const authenticate = (req: any, res: any, next: any) => {
|
||||||
const token = req.headers.authorization?.split(' ')[1];
|
const token = req.headers.authorization?.split(' ')[1];
|
||||||
@@ -35,11 +35,11 @@ router.post('/chat', async (req, res) => {
|
|||||||
const { systemInstruction, userMessage } = req.body;
|
const { systemInstruction, userMessage } = req.body;
|
||||||
|
|
||||||
const model = ai.getGenerativeModel({
|
const model = ai.getGenerativeModel({
|
||||||
model: MODEL_ID,
|
model: MODEL_ID
|
||||||
systemInstruction
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await model.generateContent(userMessage);
|
const prompt = `${systemInstruction}\n\nUser: ${userMessage}`;
|
||||||
|
const result = await model.generateContent(prompt);
|
||||||
const response = result.response.text();
|
const response = result.response.text();
|
||||||
|
|
||||||
res.json({ response });
|
res.json({ response });
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { WorkoutSession } from '../types';
|
import { WorkoutSession } from '../types';
|
||||||
import { api } from './api';
|
import { api } from './api';
|
||||||
|
|
||||||
export const createFitnessChat = (history: WorkoutSession[]): any => {
|
export const createFitnessChat = (history: WorkoutSession[], lang: 'en' | 'ru' = 'ru'): any => {
|
||||||
// The original returned a Chat object.
|
// The original returned a Chat object.
|
||||||
// Now we need to return something that behaves like it or refactor the UI.
|
// Now we need to return something that behaves like it or refactor the UI.
|
||||||
// The UI likely calls `chat.sendMessage(msg)`.
|
// The UI likely calls `chat.sendMessage(msg)`.
|
||||||
@@ -9,12 +9,12 @@ export const createFitnessChat = (history: WorkoutSession[]): any => {
|
|||||||
|
|
||||||
// Summarize data to reduce token count while keeping relevant context
|
// Summarize data to reduce token count while keeping relevant context
|
||||||
const summary = history.slice(0, 10).map(s => ({
|
const summary = history.slice(0, 10).map(s => ({
|
||||||
date: new Date(s.startTime).toLocaleDateString('ru-RU'),
|
date: new Date(s.startTime).toLocaleDateString(lang === 'ru' ? 'ru-RU' : 'en-US'),
|
||||||
userWeight: s.userBodyWeight,
|
userWeight: s.userBodyWeight,
|
||||||
exercises: s.sets.map(set => `${set.exerciseName}: ${set.weight ? set.weight + 'кг' : ''}${set.reps ? ' x ' + set.reps + 'повт' : ''} ${set.distanceMeters ? set.distanceMeters + 'м' : ''}`).join(', ')
|
exercises: s.sets.map(set => `${set.exerciseName}: ${set.weight ? set.weight + (lang === 'ru' ? 'кг' : 'kg') : ''}${set.reps ? ' x ' + set.reps + (lang === 'ru' ? 'повт' : 'reps') : ''} ${set.distanceMeters ? set.distanceMeters + (lang === 'ru' ? 'м' : 'm') : ''}`).join(', ')
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const systemInstruction = `
|
const systemInstruction = lang === 'ru' ? `
|
||||||
Ты — опытный и поддерживающий фитнес-тренер.
|
Ты — опытный и поддерживающий фитнес-тренер.
|
||||||
Твоя задача — анализировать тренировки пользователя и давать краткие, полезные советы на русском языке.
|
Твоя задача — анализировать тренировки пользователя и давать краткие, полезные советы на русском языке.
|
||||||
|
|
||||||
@@ -25,6 +25,18 @@ export const createFitnessChat = (history: WorkoutSession[]): any => {
|
|||||||
|
|
||||||
Если пользователь спрашивает о прогрессе, используй эти данные.
|
Если пользователь спрашивает о прогрессе, используй эти данные.
|
||||||
Отвечай емко, мотивирующе. Избегай длинных лекций, если не просили.
|
Отвечай емко, мотивирующе. Избегай длинных лекций, если не просили.
|
||||||
|
` : `
|
||||||
|
You are an experienced and supportive fitness coach.
|
||||||
|
Your task is to analyze the user's workouts and provide concise, helpful advice in English.
|
||||||
|
|
||||||
|
Consider the user's weight (userWeight in json), if provided, when analyzing progress in bodyweight exercises.
|
||||||
|
|
||||||
|
Here are the user's last 10 workouts (in JSON format):
|
||||||
|
${JSON.stringify(summary)}
|
||||||
|
|
||||||
|
If the user asks about progress, use this data.
|
||||||
|
Answer concisely and motivationally. Avoid long lectures unless asked.
|
||||||
|
ALWAYS answer in the language the user speaks to you, defaulting to English if unsure.
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -34,6 +46,7 @@ export const createFitnessChat = (history: WorkoutSession[]): any => {
|
|||||||
userMessage
|
userMessage
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
|
text: res.response,
|
||||||
response: {
|
response: {
|
||||||
text: () => res.response
|
text: () => res.response
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user