Be able to enqueue RAG test from frontend

This commit is contained in:
timothycarambat
2023-10-17 19:40:58 -07:00
parent be1cb2690a
commit d0de2bbe2a
5 changed files with 306 additions and 151 deletions
+2 -147
View File
@@ -1,10 +1,8 @@
const { DocumentVectors } = require("../../../models/documentVectors");
const { Organization } = require("../../../models/organization");
const {
OrganizationConnection,
} = require("../../../models/organizationConnection");
const { Queue } = require("../../../models/queue");
const { RagTest } = require("../../../models/ragTest");
const {
userFromSession,
validSessionForUser,
@@ -16,10 +14,10 @@ const {
const {
organizationResetJob,
} = require("../../../utils/jobs/organizationResetJob");
const { createRagTest } = require("../../../utils/toolHelpers/RagTests/create");
const {
workspaceSimilaritySearch,
} = require("../../../utils/toolHelpers/workspaceSimilaritySearch");
const { ragTestingEndpoints } = require("./ragTesting");
process.env.NODE_ENV === "development"
? require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` })
@@ -27,6 +25,7 @@ process.env.NODE_ENV === "development"
function toolEndpoints(app) {
if (!app) return;
ragTestingEndpoints(app);
app.post(
"/v1/tools/org/:orgSlug/migrate",
@@ -182,150 +181,6 @@ function toolEndpoints(app) {
}
);
app.get(
"/v1/tools/org/:orgSlug/rag-tests",
[validSessionForUser],
async function (request, response) {
try {
const { orgSlug } = request.params;
const user = await userFromSession(request);
if (!user || user.role !== "admin") {
response.sendStatus(403).end();
return;
}
const organization = await Organization.getWithOwner(user.id, {
slug: orgSlug,
});
if (!organization) {
response.status(200).json({ ragTests: [], message: "No org found." });
return;
}
const tests = await RagTest.where(
{
organization_id: organization.id,
},
null,
{ lastRun: "desc" },
{
id: true,
promptText: true,
frequencyType: true,
topK: true,
lastRun: true,
comparisons: true,
promptVector: true,
workspace: true,
organization: true,
organization_rag_test_runs: {
select: {
id: true,
status: true,
},
orderBy: {
id: "desc",
},
},
}
);
response.status(200).json({ ragTests: tests, message: null });
return;
} catch (e) {
console.log(e.message, e);
response.sendStatus(500).end();
}
}
);
app.get(
"/v1/tools/org/:orgSlug/rag-tests/:testId",
[validSessionForUser],
async function (request, response) {
try {
const { orgSlug, testId } = request.params;
const user = await userFromSession(request);
if (!user || user.role !== "admin") {
response.sendStatus(403).end();
return;
}
const organization = await Organization.getWithOwner(user.id, {
slug: orgSlug,
});
if (!organization) {
response.status(200).json({ test: null, message: "No org found." });
return;
}
const test = await RagTest.get({ id: Number(testId) });
const runs = await RagTest.getRuns(test.id, {}, 10, {
createdAt: "desc",
});
response.status(200).json({ test, runs, message: null });
return;
} catch (e) {
console.log(e.message, e);
response.sendStatus(500).end();
}
}
);
app.delete(
"/v1/tools/org/:orgSlug/rag-tests/:testId",
[validSessionForUser],
async function (request, response) {
try {
const { orgSlug, testId } = request.params;
const user = await userFromSession(request);
if (!user || user.role !== "admin") {
response.sendStatus(403).end();
return;
}
const organization = await Organization.getWithOwner(user.id, {
slug: orgSlug,
});
if (!organization) {
response.sendStatus(400).end();
return;
}
const test = await RagTest.get({ id: Number(testId) }, { id: true });
if (!test) {
response.sendStatus(400).end();
return;
}
await RagTest.delete({ id: test.id });
response.sendStatus(200).end();
return;
} catch (e) {
console.log(e.message, e);
response.sendStatus(500).end();
}
}
);
app.post(
"/v1/tools/org/:orgSlug/rag-tests/create",
[validSessionForUser],
async function (request, response) {
try {
const user = await userFromSession(request);
if (!user || user.role !== "admin") {
response.sendStatus(403).end();
return;
}
return await createRagTest(user, request, response);
} catch (e) {
console.log(e.message, e);
response.sendStatus(500).end();
}
}
);
app.post(
"/v1/tools/org/:orgSlug/workspace-similarity-search",
[validSessionForUser],
@@ -0,0 +1,213 @@
const { Organization } = require("../../../../models/organization");
const { Queue } = require("../../../../models/queue");
const { RagTest } = require("../../../../models/ragTest");
const {
userFromSession,
validSessionForUser,
} = require("../../../../utils/http");
const {
createRagTestJobRun,
} = require("../../../../utils/jobs/createRagTestJobRun");
const {
createRagTest,
} = require("../../../../utils/toolHelpers/RagTests/create");
const {
workspaceSimilaritySearch,
} = require("../../../../utils/toolHelpers/workspaceSimilaritySearch");
process.env.NODE_ENV === "development"
? require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` })
: require("dotenv").config();
function ragTestingEndpoints(app) {
if (!app) return;
app.get(
"/v1/tools/org/:orgSlug/rag-tests",
[validSessionForUser],
async function (request, response) {
try {
const { orgSlug } = request.params;
const user = await userFromSession(request);
if (!user || user.role !== "admin") {
response.sendStatus(403).end();
return;
}
const organization = await Organization.getWithOwner(user.id, {
slug: orgSlug,
});
if (!organization) {
response.status(200).json({ ragTests: [], message: "No org found." });
return;
}
const tests = await RagTest.where(
{
organization_id: organization.id,
},
null,
{ lastRun: "desc" },
{
id: true,
promptText: true,
frequencyType: true,
topK: true,
lastRun: true,
comparisons: true,
promptVector: true,
workspace: true,
organization: true,
organization_rag_test_runs: {
select: {
id: true,
status: true,
},
orderBy: {
id: "desc",
},
},
}
);
response.status(200).json({ ragTests: tests, message: null });
return;
} catch (e) {
console.log(e.message, e);
response.sendStatus(500).end();
}
}
);
app.get(
"/v1/tools/org/:orgSlug/rag-tests/:testId",
[validSessionForUser],
async function (request, response) {
try {
const { orgSlug, testId } = request.params;
const user = await userFromSession(request);
if (!user || user.role !== "admin") {
response.sendStatus(403).end();
return;
}
const organization = await Organization.getWithOwner(user.id, {
slug: orgSlug,
});
if (!organization) {
response.status(200).json({ test: null, message: "No org found." });
return;
}
const test = await RagTest.get({ id: Number(testId) });
const runs = await RagTest.getRuns(test.id, {}, 10, {
createdAt: "desc",
});
response.status(200).json({ test, runs, message: null });
return;
} catch (e) {
console.log(e.message, e);
response.sendStatus(500).end();
}
}
);
app.delete(
"/v1/tools/org/:orgSlug/rag-tests/:testId",
[validSessionForUser],
async function (request, response) {
try {
const { orgSlug, testId } = request.params;
const user = await userFromSession(request);
if (!user || user.role !== "admin") {
response.sendStatus(403).end();
return;
}
const organization = await Organization.getWithOwner(user.id, {
slug: orgSlug,
});
if (!organization) {
response.sendStatus(400).end();
return;
}
const test = await RagTest.get({ id: Number(testId) }, { id: true });
if (!test) {
response.sendStatus(400).end();
return;
}
await RagTest.delete({ id: test.id });
response.sendStatus(200).end();
return;
} catch (e) {
console.log(e.message, e);
response.sendStatus(500).end();
}
}
);
app.post(
"/v1/tools/org/:orgSlug/rag-tests/create",
[validSessionForUser],
async function (request, response) {
try {
const user = await userFromSession(request);
if (!user || user.role !== "admin") {
response.sendStatus(403).end();
return;
}
return await createRagTest(user, request, response);
} catch (e) {
console.log(e.message, e);
response.sendStatus(500).end();
}
}
);
app.post(
"/v1/tools/org/:orgSlug/rag-tests/:testId/run",
[validSessionForUser],
async function (request, response) {
try {
const { orgSlug, testId } = request.params;
const user = await userFromSession(request);
if (!user || user.role !== "admin") {
response.sendStatus(403).end();
return;
}
const organization = await Organization.getWithOwner(user.id, {
slug: orgSlug,
});
if (!organization) {
response
.status(200)
.json({ success: false, error: "No organization found." });
return;
}
const test = await RagTest.get({ id: Number(testId) }, { id: true });
if (!test) {
response
.status(200)
.json({ success: false, error: "No test found for that id." });
return;
}
const { job, error } = await createRagTestJobRun(
organization,
test.id,
user
);
response.status(200).json({ job, error });
} catch (e) {
console.log(e.message, e);
response.sendStatus(500).end();
}
}
);
}
module.exports = { ragTestingEndpoints };
@@ -0,0 +1,38 @@
const { Queue } = require("../../../models/queue");
async function createRagTestJobRun(organization, testId, user) {
const taskName = `rag-test/run`;
const pendingJob = await Queue.get({
organization_id: Number(organization.id),
status: Queue.status.pending,
taskName,
});
if (pendingJob) {
const pendingJobData = JSON.parse(pendingJob.data);
if (pendingJobData.testId === testId) {
return { job: null, error: "A job like this is currently running." };
}
}
const jobData = { organization, testId };
const { job, error } = await Queue.create(
taskName,
jobData,
user.id,
organization.id
);
if (!!error) return { job, error };
await Queue.sendJob({
name: taskName,
data: {
jobId: job.id,
...jobData,
},
});
return { job, error: null };
}
module.exports = {
createRagTestJobRun,
};
+17
View File
@@ -66,6 +66,23 @@ const Tools = {
return { test: null, error: e.message };
});
},
runRagTest: async (
test: IRagTest
): Promise<{ job: object | null; error: null | string }> => {
return fetch(
`${API_BASE}/v1/tools/org/${test.organization.slug}/rag-tests/${test.id}/run`,
{
method: 'POST',
cache: 'no-cache',
headers: baseHeaders(),
}
)
.then((res) => res.json())
.catch((e) => {
console.error(e);
return { job: null, error: e.message };
});
},
deleteRagTest: async (test: IRagTest): Promise<boolean> => {
return fetch(
`${API_BASE}/v1/tools/org/${test.organization.slug}/rag-tests/${test.id}`,
@@ -1,9 +1,10 @@
import { Box, Trash } from 'react-feather';
import { Box, Loader, Trash } from 'react-feather';
import Tools, { IRagTest } from '../../../../models/tools';
import moment from 'moment';
import paths from '../../../../utils/paths';
import showToast from '../../../../utils/toast';
import TestDetailsModal from '../TestDetails';
import { useState } from 'react';
export default function RecentTestRuns({
tests,
@@ -127,9 +128,7 @@ function TestItem({ test, onDelete }: { test: IRagTest; onDelete: any }) {
View Runs
</a>
)}
<button className="rounded-lg px-2 py-1 text-orange-400 transition-all duration-300 hover:bg-orange-600 hover:text-white">
Run now
</button>
<RunNowButton test={test} />
<button
onClick={handleRemove}
className="rounded-lg px-2 py-1 text-red-400 transition-all duration-300 hover:bg-red-100 hover:text-red-600"
@@ -144,6 +143,39 @@ function TestItem({ test, onDelete }: { test: IRagTest; onDelete: any }) {
);
}
function RunNowButton({ test }: { test: IRagTest }) {
const [loading, setLoading] = useState(false);
const handleRunNow = async () => {
setLoading(true);
const { job, error } = await Tools.runRagTest(test);
if (job) {
showToast(`RAG Test is now running in background jobs`, 'success');
setLoading(false);
return;
}
showToast(error || 'Rag test could not be run.', 'error');
setLoading(false);
};
return (
<button
disabled={loading}
onClick={handleRunNow}
className="flex items-center gap-x-2 rounded-lg px-2 py-1 text-orange-400 transition-all duration-300 hover:bg-orange-600 hover:text-white disabled:bg-orange-600 disabled:text-white"
>
{loading ? (
<>
<Loader className="animate-spin" size={14} />
<p>Running</p>
</>
) : (
'Run now'
)}
</button>
);
}
function TestResultBadge({ test }: { test: IRagTest }) {
const { organization_rag_test_runs = [] } = test;
if (organization_rag_test_runs.length === 0) {