-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathserver.js
More file actions
430 lines (366 loc) · 15.4 KB
/
Copy pathserver.js
File metadata and controls
430 lines (366 loc) · 15.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
const express = require("express");
const axios = require("axios");
const cors = require("cors");
const OpenAI = require("openai");
require('dotenv').config();
const puppeteer = require('puppeteer'); // Ensure Puppeteer is installed
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
const fs = require('fs');
const app = express();
let fileIds = []; // Store file IDs
let uploadedFileIds = []; // Store uploaded file IDs
// Enable CORS for your front-end
const corsOptions = {
origin: "*",
};
app.use(cors(corsOptions));
app.use(express.json());
const openai = new OpenAI({
apiKey: "/* D */", // Replace with your OpenAI API key
});
const threadByUser = {}; // Store thread IDs by user
const tools = [
{
type: "function",
function: {
name: "fetchSearchResults",
description: "Fetch search results for a given query using SERP API used to aid in being PRIVATE INVESTIGATOR",
parameters: {
type: "object",
properties: {
query: {
type: "string",
description: "Query string to search for",
},
},
required: ["query"],
},
},
},
{
type: "code_interpreter",
// Details about the code interpreter tool
},
{
type: "retrieval",
// Details about the retrieval tool
},
{
type: "function",
function: {
name: "analyzeImage",
description: "Analyze the content of an image using OpenAI's Vision API",
parameters: {
type: "object",
properties: {
imageUrl: {
type: "string",
description: "URL of the image to analyze",
},
},
required: ["imageUrl"],
},
// Function logic or reference here (e.g., analyzeImageWithVisionAPI)
},
},
// Additional tools can be added here
];
async function scrapeLinkedIn(url) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
// Implement scraping logic specific to LinkedIn pages
const data = await page.evaluate(() => {
// Example: Scrape profile details
return document.body.innerText; // or more specific data extraction
});
await browser.close();
return data;
}
async function fetchSearchResults(query) {
const config = {
method: "post",
url: "https://google.serper.dev/search",
headers: {
"X-API-KEY": "dink",
"Content-Type": "application/json",
},
data: JSON.stringify({ q: query }),
};
try {
const response = await axios(config);
const results = response.data;
// Filter for LinkedIn URLs
const linkedInUrls = results.organic.filter(res => res.link.includes('linkedin.com'));
// Scrape each LinkedIn URL
for (const result of linkedInUrls) {
const scrapedData = await scrapeLinkedIn(result.link);
result['scrapedContent'] = scrapedData;
}
return results;
} catch (error) {
console.error(`Error: ${error}`);
throw error;
}
}
async function analyzeImage(imageUrl) {
try {
const response = await openai.chat.completions.create({
model: "gpt-4-vision-preview", // Ensure this is the correct model name
messages: [
{
role: "user",
content: [
{ type: "text", text: "What’s in this image?" },
{
type: "image_url",
image_url: {
url: imageUrl, // URL of the image to analyze
detail: "low", // Adjust the detail level as needed
},
},
],
},
],
});
return response.choices[0].message.content; // Adjust according to the actual structure of the response
} catch (error) {
console.error("Error analyzing image with GPT-4 Vision:", error);
return `Could not analyze image: ${error.message}`;
}
}
async function analyzeTextWithGPT(text) {
try {
const response = await openai.Completion.create({
model: "gpt-3.5-turbo", // Use GPT-3.5-turbo model
prompt: `You are a PI,Extract relevant information about the following content:\n\n${text}`,
max_tokens: 200, // Adjust as needed
});
return response.choices[0].text.trim();
} catch (error) {
console.error("Error analyzing text with GPT:", error);
return `Could not analyze content.`;
}
}
function extractUrls(text) {
const urlRegex = /(https?:\/\/[^\s]+)/g;
return text.match(urlRegex) || [];
}
// Function to check if a URL points to an image (basic version)
function isImageUrl(url) {
return url.match(/\.(jpeg|jpg|gif|png)$/) != null;
}
async function analyzeImagesInText(text) {
const imageUrls = extractUrls(text).filter(isImageUrl);
let imageAnalysisResults = [];
for (const url of imageUrls) {
try {
const analysisResult = await analyzeImageWithVisionAPI(url);
imageAnalysisResults.push({ url, analysis: analysisResult });
} catch (error) {
console.error("Error analyzing image:", error);
}
}
return imageAnalysisResults;
}
async function downloadFile(fileId, filePath) {
try {
const response = await openai.files.content(fileId);
// Extract the binary data from the Response object
const fileData = await response.arrayBuffer();
// Convert the binary data to a Buffer
const fileBuffer = Buffer.from(fileData);
// Save the file to the specified location
fs.writeFileSync(filePath, fileBuffer);
console.log(`File downloaded and saved to ${filePath}`);
} catch (error) {
console.error('Error downloading file:', error);
}
}
async function checkStatusAndPrintMessages(threadId, runId, intervalId) {
let runStatus = await openai.beta.threads.runs.retrieve(threadId, runId);
if (runStatus.status === "completed" || runStatus.status === 'failed') {
let messages = await openai.beta.threads.messages.list(threadId);
messages.data.forEach((msg) => {
const role = msg.role;
const content = msg.content[0].text.value;
console.log(`${role.charAt(0).toUpperCase() + role.slice(1)}: ${content}`);
});
clearInterval(intervalId);
} else if (runStatus.status === 'requires_action') {
// Handle required actions
const requiredActions = runStatus.required_action.submit_tool_outputs.tool_calls;
let toolsOutput = [];
for (const action of requiredActions) {
if (action.function.name === "fetchSearchResults") {
const functionArguments = JSON.parse(action.function.arguments);
const output = await fetchSearchResults(functionArguments.query);
toolsOutput.push({
tool_call_id: action.id,
output: JSON.stringify(output)
});
}
}
await openai.beta.threads.runs.submitToolOutputs(threadId, runId, { tool_outputs: toolsOutput });
} else {
console.log("Run is not completed yet.");
}
}
app.post("/chat", async (req, res) => {
const assistantIdToUse = "asst_swKHIz2VerOTdps3oX6bJhqi"; // Replace with your assistant ID
const userId = req.body.userId; // Include the user ID in the request
const assistantId = assistantIdToUse;
// Create a new thread if it's the user's first message
if (!threadByUser[userId]) {
try {
const myThread = await openai.beta.threads.create();
console.log("New thread created with ID: ", myThread.id);
threadByUser[userId] = myThread.id; // Store the thread ID for this user
} catch (error) {
console.error("Error creating thread:", error);
res.status(500).json({ error: "Internal server error" });
return;
}
}
const userMessage = req.body.message;
// Add a Message to the Thread
try {
const myThreadMessage = await openai.beta.threads.messages.create(
threadByUser[userId], // Use the stored thread ID for this user
{
role: "user",
content: userMessage,
file_ids: uploadedFileIds, // Include file_ids inside the message object
}
);
console.log("Message object: ", myThreadMessage);
// Run the Assistant
const myRun = await openai.beta.threads.runs.create(
threadByUser[userId], // Use the stored thread ID for this user
{
assistant_id: assistantIdToUse,
instructions: 'You are an AI Private Investigator tasked with gathering information on a specific object thing or person. Your mission is to collect comprehensive details including but not limited to the followingObject/Thing/Person Clearly identify the object thing or person you are investigating.Background Research and provide background information on the subject. This could include their history associations and any relevant context.Contact Information If applicable find and report any available contact information such as email addresses phone numbers or social media profiles.Physical Description Describe the physical appearance of the subject including any distinguishing features.Location Determine the current or last-known location of the subject.Associations Investigate and document any known associations or relationships the subject has with other individuals or entities.Legal Information If relevant uncover any legal records including criminal records lawsuits or court proceedings.Online Presence Search for and report any online presence or digital footprint including websites social media activity and online publications.Financial Information If applicable gather information on the financial status including income assets and liabilities.Additional Information Collect any other pertinent information that may aid in the investigation.Your goal is to compile a comprehensive dossier by utilizing your investigative skills and available resources. Ensure accuracy and thoroughness in your findings.Looking for email,phone number,images etc. Please Dont include obituary results',
tools: tools,
// Include the file IDs in the request
}
);
console.log("Run object: ", myRun);
// Check and print messages
const intervalId = setInterval(async () => {
try {
const runStatus = await openai.beta.threads.runs.retrieve(
threadByUser[userId],
myRun.id
);
if (runStatus.status === "completed" || runStatus.status === "failed") {
const messages = await openai.beta.threads.messages.list(
threadByUser[userId]
);
messages.data.forEach(async (msg) => {
const contentType = msg.content[0].type;
if (contentType === "text") {
// Check if there are annotations and if the first annotation is a file path
const annotations = msg.content[0].text.annotations;
if (annotations && annotations.length > 0 && annotations[0].type === 'file_path') {
const fileAnnotation = annotations[0];
console.log("File path annotation:", fileAnnotation);
// If there's a file_id, handle the file download
if (fileAnnotation.file_path && fileAnnotation.file_path.file_id) {
const fileId = fileAnnotation.file_path.file_id;
const filePath = `./downloads/${fileId}`; // You may need to determine the correct file extension
// Download the file using the fileId and save it to the specified path
await downloadFile(fileId, filePath);
}
} else {
// Handle normal text content
const textContent = msg.content[0].text.value;
console.log("Text content:", textContent);
}
} else if (contentType === "image_file") {
const fileId = msg.content[0].image_file.file_id;
console.log("Image file ID:", fileId);
// Define the file download path on your server
const filePath = `./downloads/${fileId}.png`; // Change the extension based on the file type
// Download the file using the fileId and save it to the specified path
await downloadFile(fileId, filePath);
}
});
clearInterval(intervalId);
console.log(messages.data[0].content[0].type.file_id)
// Extract the bot's latest message
if (messages.data[0].content[0].type === "text") {
const latestBotMessage = messages.data[0].content[0].text.value;
res.json({ message: latestBotMessage });
} else if (messages.data[0].content[0].type === "image_file") {
const imageFileId = messages.data[0].content[0].image_file.file_id;
// You may need to send a URL or some identifier to the front end
res.json({ imageFileId: imageFileId });
}
// Send the bot's latest message as a JSON response to the front end
} else if (runStatus.status === "requires_action") {
// Handle required actions
const requiredActions =
runStatus.required_action.submit_tool_outputs.tool_calls;
let toolsOutput = [];
for (const action of requiredActions) {
let output;
if (action.function.name === "fetchSearchResults") {
const functionArguments = JSON.parse(action.function.arguments);
output = await fetchSearchResults(functionArguments.query);
} else if (action.function.name === "analyzeImage") {
const functionArguments = JSON.parse(action.function.arguments);
output = await analyzeImage(functionArguments.imageUrl);
}
// Add more 'else if' statements here for additional tools
if (output) {
toolsOutput.push({
tool_call_id: action.id,
output: JSON.stringify(output)
});
}
}
await openai.beta.threads.runs.submitToolOutputs(
threadByUser[userId],
myRun.id,
{ tool_outputs: toolsOutput }
);
} else {
console.log("Run is not completed yet.");
}
} catch (error) {
console.error("Error in interval:", error);
}
}, 5000);
} catch (error) {
console.error("Error in /chat endpoint:", error);
res.status(500).json({ error: "Internal server error" });
}
});
app.post('/upload', upload.single('file'), async (req, res) => {
if (!req.file) {
return res.status(400).send('No file uploaded.');
}
try {
const fileStream = fs.createReadStream(req.file.path);
// Upload the file to OpenAI
const openaiFile = await openai.files.create({
file: fileStream,
purpose: 'assistants', // or 'assistants' depending on your use case
});
// Store the uploaded file ID for later use
uploadedFileIds.push(openaiFile.id);
res.json({ message: 'File uploaded successfully', fileId: openaiFile.id });
console.log(fileIds)
console.log("test" + uploadedFileIds)
} catch (error) {
console.error('Error uploading file to OpenAI:', error);
res.status(500).send('Error processing file.');
} finally {
fs.unlinkSync(req.file.path); // Clean up the local file
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT,"0.0.0.0", () => {
console.log(`Server is running on port ${PORT}`);
});