Skip to content

Commit

Permalink
Merge pull request #29 from passadis/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
passadis authored Nov 12, 2024
2 parents d6f24f0 + 08feadf commit 3f7c86d
Show file tree
Hide file tree
Showing 9 changed files with 370 additions and 189 deletions.
59 changes: 54 additions & 5 deletions Notebooks/Users-Pipeline/new-users-index.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,14 @@
"\n",
"# Configuration\n",
"openai.api_type = \"azure\"\n",
"openai.api_base = \"https://xxxxx.openai.azure.com/\"\n",
"openai.api_base = \"https://xxxxxx.openai.azure.com/\"\n",
"openai.api_version = \"2024-02-01\"\n",
"openai.api_key = \"xxxxxxxx\"\n",
"openai.api_key = \"xxxxxxxxxxxxx\"\n",
"deployment_id = \"text-embedding-ada-002\"\n",
"\n",
"search_service_name = \"xxxxx\"\n",
"search_index_name = \"xxxxx-index\"\n",
"admin_key = \"xxxxxxxx\"\n",
"search_index_name = \"users-index\"\n",
"admin_key = \"xxxxxxxxxxxxxxxxxx\"\n",
"endpoint = f\"https://{search_service_name}.search.windows.net\"\n",
"\n",
"# Initialize the search client\n",
Expand Down Expand Up @@ -268,7 +268,56 @@
"\n",
" print(f\"Uploaded {len(documents)} documents in total\")\n",
"except Exception as e:\n",
" print(f\"Error uploading documents: {e}\")\n"
" print(f\"Error uploading documents: {e}\")\n",
"\n",
"\n",
"\n",
"# Get the list of UserIds for which embeddings were successfully generated\n",
"processed_user_ids = [user['UserId'] for user in new_users if 'Embedding' in user]\n",
"\n",
"# # Update the RecommendationsReady flag in Azure SQL using PySpark\n",
"# if processed_user_ids:\n",
"# update_recommendations_ready(processed_user_ids)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1ac203ef-19b8-464f-8e00-25c630de942b",
"metadata": {
"jupyter": {
"outputs_hidden": false,
"source_hidden": false
},
"microsoft": {
"language": "python",
"language_group": "synapse_pyspark"
},
"nteract": {
"transient": {
"deleting": false
}
}
},
"outputs": [],
"source": [
"import requests\n",
"\n",
"def notify_user(user_id):\n",
" url = \"https://xxxxxxxxxxxxxx.azurewebsites.net/api/update-recommendations\"\n",
" payload = {\n",
" \"userId\": user_id,\n",
" \"recommendationsReady\": True\n",
" }\n",
" response = requests.post(url, json=payload)\n",
" if response.status_code == 200:\n",
" print(f\"Notification sent to user {user_id}\")\n",
" else:\n",
" print(f\"Failed to send notification: {response.text}\")\n",
"\n",
"# Assuming 'processed_user_ids' is already populated\n",
"for user_id in processed_user_ids:\n",
" notify_user(user_id)"
]
}
],
Expand Down
175 changes: 42 additions & 133 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import bodyParser from 'body-parser';

dotenv.config();




const app = express();
app.use(cors({ origin: '*' }));
app.use((req, res, next) => {
Expand Down Expand Up @@ -49,6 +52,7 @@ app.get('/:path', function(req, res) {
});



const vaultName = process.env.AZURE_KEY_VAULT_NAME;
const vaultUrl = `https://${vaultName}.vault.azure.net`;
const credential = new DefaultAzureCredential({
Expand Down Expand Up @@ -92,6 +96,10 @@ async function initializeApp() {
searchApiKey = await getSecret("search-apikey");
openaiEndpoint = await getSecret("openai-endpoint");
openaiApiKey = await getSecret("openai-apikey");





//console.log("SQL Config:", sqlConfig);
// console.log("Storage Account Name:", storageAccountName);
Expand Down Expand Up @@ -266,141 +274,42 @@ app.get('/user/:UserId', async (req, res) => {
}
});

// // AI Assistant endpoint for book questions and recommendations
// app.post('/ai-assistant', async (req, res) => {
// const { query, userId } = req.body;
// Check if personalized recommendations are ready for a user
app.get('/api/check-recommendations', async (req, res) => {
const { userId } = req.query;

// Validate user ID
if (!userId) {
return res.status(400).json({ message: 'User ID is required' });
}

try {
// Connect to the database
let pool = await sql.connect(sqlConfig);
let result = await pool.request()
.input('UserId', sql.Int, userId)
.query('SELECT RecommendationsReady FROM Users WHERE UserId = @UserId');

// Check if user exists
if (result.recordset.length === 0) {
return res.status(404).send({ message: 'User not found' });
}

// Get the status from the database
const isReady = result.recordset[0].RecommendationsReady;

// Send the status back to the client
res.json({ recommendationsReady: isReady });
} catch (error) {
console.error('Error checking recommendations status:', error);
res.status(500).json({ message: 'Error checking recommendations status' });
}
});


// console.log('Received request body:', req.body);
// console.log('Extracted userId:', userId);

// try {
// if (!userId) {
// console.error('User ID is missing from the request.');
// return res.status(400).send({ message: 'User ID is required.' });
// }

// //console.log(`Received request for user ID: ${userId}`);

// // Retrieve user data
// let pool = await sql.connect(sqlConfig);
// let userResult = await pool.request()
// .input('UserId', sql.Int, userId)
// .query('SELECT * FROM Users WHERE UserId = @UserId');

// const user = userResult.recordset[0];

// if (!user) {
// console.error(`User with ID ${userId} not found.`);
// return res.status(404).send({ message: `User with ID ${userId} not found.` });
// }

// console.log(`User data: ${JSON.stringify(user)}`);

// if (query.toLowerCase().includes("recommendation")) {
// // Fetch user genres
// const userGenresResult = await pool.request()
// .input('UserId', sql.Int, userId)
// .query('SELECT GenreName FROM Genres g JOIN UsersGenres ug ON g.GenreId = ug.GenreId WHERE ug.UserId = @UserId');

// const userGenres = userGenresResult.recordset.map(record => record.GenreName).join(' ');

// //console.log(`User genres: ${userGenres}`);

// // Fetch user embedding from search index
// const userSearchClient = new SearchClient(searchEndpoint, 'users-index', new AzureKeyCredential(searchApiKey));
// const userEmbeddingResult = await userSearchClient.getDocument(String(user.UserId));
// const userEmbedding = userEmbeddingResult.Embedding;

// //console.log(`User embedding result: ${JSON.stringify(userEmbeddingResult)}`);
// //console.log(`User embedding: ${userEmbedding}`);

// if (!userEmbedding || userEmbedding.length === 0) {
// console.error('User embedding not found.');
// return res.status(500).send({ message: 'User embedding not found.' });
// }

// // Search for recommendations
// const bookSearchClient = new SearchClient(searchEndpoint, 'books-index', new AzureKeyCredential(searchApiKey));
// const searchResponse = await bookSearchClient.search("*", {
// vectors: [{
// value: userEmbedding,
// fields: ["Embedding"],
// kNearestNeighborsCount: 5
// }],
// includeTotalCount: true,
// select: ["Title", "Author"]
// });

// const recommendations = [];
// for await (const result of searchResponse.results) {
// recommendations.push({
// title: result.document.Title,
// author: result.document.Author,
// score: result.score
// });
// }

// // Limit recommendations to top 5
// const topRecommendations = recommendations.slice(0, 5);

// return res.json({ response: "Here are some personalized recommendations for you:", recommendations: topRecommendations });
// } else {
// // General book query
// const openaiClient = new OpenAIClient(openaiEndpoint, new AzureKeyCredential(openaiApiKey));
// const deploymentId = "gpt"; // Replace with your deployment ID

// // Extract rating and genre from query
// const ratingMatch = query.match(/rating over (\d+(\.\d+)?)/);
// const genreMatch = query.match(/genre (\w+)/i);
// const rating = ratingMatch ? parseFloat(ratingMatch[1]) : null;
// const genre = genreMatch ? genreMatch[1] : null;

// if (rating && genre) {
// // Search for books with the specified genre and rating
// const bookSearchClient = new SearchClient(searchEndpoint, 'books-index', new AzureKeyCredential(searchApiKey));
// const searchResponse = await bookSearchClient.search("*", {
// filter: `Rating gt ${rating} and Genres/any(g: g eq '${genre}')`,
// top: 5,
// select: ["Title", "Author", "Rating"]
// });

// const books = [];
// for await (const result of searchResponse.results) {
// books.push({
// title: result.document.Title,
// author: result.document.Author,
// rating: result.document.Rating
// });
// }

// const bookResponse = books.map(book => `${book.title} by ${book.author} with rating ${book.rating}`).join('\n');
// return res.json({ response: `Here are 5 books with rating over ${rating} in ${genre} genre:\n${bookResponse}` });
// } else {
// // Handle general queries about books using OpenAI with streaming chat completions
// const events = await openaiClient.streamChatCompletions(
// deploymentId,
// [
// { role: "system", content: "You are a helpful assistant that answers questions about books and provides personalized recommendations." },
// { role: "user", content: query }
// ],
// { maxTokens: 350 }
// );

// let aiResponse = "";
// for await (const event of events) {
// for (const choice of event.choices) {
// aiResponse += choice.delta?.content || '';
// }
// }

// return res.json({ response: aiResponse });
// }
// }
// } catch (error) {
// console.error('Error processing AI Assistant request:', error);
// return res.status(500).send({ message: 'Error processing your request.' });
// }
// });

// AI Assistant endpoint for book questions and recommendations
app.post('/ai-assistant', async (req, res) => {
Expand Down Expand Up @@ -494,10 +403,10 @@ app.post('/ai-assistant', async (req, res) => {
const events = await openaiClient.streamChatCompletions(
deploymentId,
[
{ role: "system", content: "You are a helpful assistant that answers questions about books and provides personalized recommendations." },
{ role: "system", content: "You are a helpful assistant that answers questions about books and provides 5 personalized recommendations." },
{ role: "user", content: query }
],
{ maxTokens: 350 }
{ maxTokens: 550 }
);

let aiResponse = "";
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ h1 {
}

p {
color: #f0f8ff;
color: #0f1010;
margin-bottom: 20px;
}

Expand Down
29 changes: 20 additions & 9 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import React, { useContext } from 'react';
import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom';
import './App.css';
import MainContent from './MainContent';
import Register from './Components/Register/Register';
import Dashboard from './Components/Dashboard/Dashboard';
import { AuthContext } from './AuthContext';

function App() {
const { auth } = useContext(AuthContext);

return (
<Router>
<div className="App">
<Routes>
<Route exact path="/" element={<MainContent />} />
<Route path="/signup" element={<Register />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</div>
<Routes>
<Route
path="/"
element={auth.token ? <Navigate to="/dashboard" /> : <MainContent />}
/>
<Route
path="/dashboard"
element={auth.token ? <Dashboard /> : <Navigate to="/" />}
/>
<Route
path="/signup"
element={auth.token ? <Navigate to="/dashboard" /> : <Register />}
/>
{/* Add other routes as needed */}
</Routes>
</Router>
);
}
Expand Down
47 changes: 47 additions & 0 deletions frontend/src/AuthContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// AuthContext.js

import React, { createContext, useState, useEffect } from 'react';

// Create the AuthContext
export const AuthContext = createContext();

// Create a Provider component
export const AuthProvider = ({ children }) => {
const [auth, setAuth] = useState({
token: localStorage.getItem('token') || null,
userId: localStorage.getItem('UserId') || null,
});

// Function to handle login
const login = (token, userId) => {
localStorage.setItem('token', token);
localStorage.setItem('UserId', userId);
setAuth({ token, userId });
};

// Function to handle logout
const logout = () => {
localStorage.removeItem('token');
localStorage.removeItem('UserId');
setAuth({ token: null, userId: null });
};

// Optional: Sync state with localStorage changes (e.g., when multiple tabs are open)
useEffect(() => {
const handleStorageChange = () => {
setAuth({
token: localStorage.getItem('token'),
userId: localStorage.getItem('UserId'),
});
};

window.addEventListener('storage', handleStorageChange);
return () => window.removeEventListener('storage', handleStorageChange);
}, []);

return (
<AuthContext.Provider value={{ auth, login, logout }}>
{children}
</AuthContext.Provider>
);
};
Loading

0 comments on commit 3f7c86d

Please sign in to comment.