Skip to content

Commit

Permalink
dumili: WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
bperel committed Dec 28, 2024
1 parent 0732f51 commit 279b7c2
Show file tree
Hide file tree
Showing 20 changed files with 353 additions and 219 deletions.
2 changes: 1 addition & 1 deletion apps/dumili/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"prisma-pull-generate": "prisma db pull && prisma generate",
"prisma-generate": "prisma generate",
"prisma-migrate": "prisma migrate deploy",
"dev": "docker compose -f docker-compose-dev.yml up --force-recreate -d && bash ../../../packages/prisma-schemas/wait-until-db-ready.bash && prisma migrate deploy && prisma generate && concurrently --kill-others-on-fail -n docker-compose,typecheck,bun \"docker compose -f docker-compose-dev.yml logs -f\" \"tsc --noEmit\" \"bun --inspect run --hot index.ts\"",
"dev": "docker compose -f docker-compose-dev.yml up --force-recreate -d && bash ../../../packages/prisma-schemas/wait-until-db-ready.bash && prisma migrate deploy && prisma generate && concurrently --kill-others-on-fail -n docker-compose,typecheck \"docker compose -f docker-compose-dev.yml logs -f\" \"tsc --noEmit\"",
"prod:deploy": "DIR=apps/dumili/api pnpm -F '~ci' prod:docker-compose-up",
"prod-build-docker-api": "REPO_NAME=ghcr.io/bperel/dumili-api pnpm -F '~ci' prod:build-docker -f apps/dumili/api/Dockerfile",
"prod-build-docker-kumiko": "REPO_NAME=ghcr.io/bperel/kumiko pnpm -F '~ci' prod:build-docker -f apps/dumili/api/kumiko/Dockerfile",
Expand Down
40 changes: 19 additions & 21 deletions apps/dumili/api/services/_auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,27 @@ import type { SessionUser } from "~dm-types/SessionUser";

export const authenticateUser = async (
token?: string | null,
): Promise<SessionUser> => {
return new Promise((resolve, reject) => {
if (!token) {
reject("No token provided");
return;
}
): Promise<SessionUser> => new Promise((resolve, reject) => {
if (!token) {
reject("No token provided");
return;
}

jwt.verify(
token,
process.env.TOKEN_SECRET as string,
(err: unknown, user: unknown) => {
if (err) {
reject(`Invalid token: ${err}`);
} else {
if (user) {
resolve(user as SessionUser);
}
reject(`Invalid user: ${user}`);
jwt.verify(
token,
process.env.TOKEN_SECRET as string,
(err: unknown, user: unknown) => {
if (err) {
reject(`Invalid token: ${err}`);
} else {
if (user) {
resolve(user as SessionUser);
}
},
);
});
};
reject(`Invalid user: ${user}`);
}
}
);
});

export const RequiredAuthMiddleware = (
socket: Socket,
Expand Down
86 changes: 68 additions & 18 deletions apps/dumili/api/services/indexation/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Server, Socket } from "socket.io";
import "~group-by";

import type { NamespaceWithData, SessionDataWithIndexation } from "~/index";
import { prisma } from "~/index";
Expand Down Expand Up @@ -26,25 +27,29 @@ type IndexationSocket = Socket<
SessionDataWithIndexation
>;

let isAiRunning = false
const getFullIndexation = (socket: IndexationSocket, indexationId: string) =>
prisma.indexation
.findUnique({
where: { id: indexationId },
include: indexationPayloadInclude,
})
.then((indexation) => {
if (indexation && 1>2) {
if (indexation && !isAiRunning) {
runKumikoOnPages(socket, indexation)
.then(() =>
runOcrOnImages(
socket,
indexation.pages
.filter(({ image }) => !!image)
.map(({ image }) => image!),
.map(({ pageNumber, image }) => ({pageNumber, image: image!})),
),
)
.then(() => setInferredEntriesStoryKinds(socket, indexation.entries))
.then(() => createAiStorySuggestions(socket, indexation));
.then(() => createAiStorySuggestions(socket, indexation))
.finally(() => {
isAiRunning = false
});
}
return indexation;
});
Expand All @@ -55,16 +60,17 @@ const createAiStorySuggestions = async (
) => {
for (const entry of indexation.entries) {
if (entry?.acceptedStoryKind?.kind === STORY) {
socket.emit("createAiStorySuggestions", entry.id);

const firstPageOfEntry = getEntryPages(indexation, entry.id)[0];
const ocrResults = firstPageOfEntry.image?.aiOcrResult?.matches;

if (!ocrResults) {
console.log(`No OCR results found for this entry`);
console.log(`Entry ${entry.id}: No OCR results found on the first page`);
continue;
}

socket.emit("createAiStorySuggestions", entry.id);

const { results: searchResults } = await coaServices.searchStory(
ocrResults.map(({ text }) => text),
false,
Expand Down Expand Up @@ -149,7 +155,7 @@ const setInferredEntriesStoryKinds = async (
force?: boolean,
) => {
for (const entry of entries) {
if (!entry.storyKindSuggestions.some(({ ai }) => ai) && !force) {
if (entry.storyKindSuggestions.some(({ ai }) => ai) && !force) {
console.log(`Entry ${entry.id} already has an inferred story kind`);
continue;
}
Expand Down Expand Up @@ -261,15 +267,15 @@ export default (io: Server) => {
data: {
image: url
? {
connectOrCreate: {
create: {
url,
},
where: {
url,
},
connectOrCreate: {
create: {
url,
},
where: {
url,
},
}
},
}
: { disconnect: true },
},
where: {
Expand All @@ -290,9 +296,53 @@ export default (io: Server) => {
});

indexationSocket.on("loadIndexation", async (callback) => {
indexationSocket.emit('setKumikoInferredPageStoryKinds', 1)
callback({ indexation: indexationSocket.data.indexation });
});

indexationSocket.on("deleteEntry", async (entryId, entryIdToExtend, callback) => {
const { indexation } = indexationSocket.data;
const entry = indexation.entries.find(
({ id }) => id === entryId,
);
if (!entry) {
callback({ error: "This indexation does not have any entry with this ID" });
return;
}
const entryIdx = indexation.entries.findIndex(
({ id }) => id === entryId,
);
const entryToExtend = indexation.entries[entryToExtendIdx][entryIdToExtend === "previous" ? entryIdx - 1 : entryIdx + 1];
if (!entryToExtend) {
if (entryIdToExtend === "previous") {
callback({ error: "This entry does not have any previous entry" });
}
else {
callback({ error: "This entry does not have any next entry" });
}
return;
}

await prisma.entry.delete({
include: {
storySuggestions: true,
storyKindSuggestions: true,
},
where: {
id: entryId,
},
});

await prisma.entry.update({
data: {
entirepages: entryToExtend.entirepages + entry.entirepages,
},
where: {
id: entryToExtend.id,
},
});
});

indexationSocket.on(
"swapPageUrls",
async (pageNumber1, pageNumber2, callback) => {
Expand Down Expand Up @@ -380,11 +430,11 @@ export default (io: Server) => {
suggestionId === null
? { disconnect: true }
: {
connect: {
id: suggestionId,
indexationId: indexationSocket.data.indexation.id,
},
connect: {
id: suggestionId,
indexationId: indexationSocket.data.indexation.id,
},
},
},
where: {
id: indexationSocket.data.indexation.id,
Expand Down
49 changes: 33 additions & 16 deletions apps/dumili/api/services/indexation/kumiko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const runKumikoOnPage = async (
`Kumiko: page ${page.pageNumber}: inferred story kind is ${inferredStoryKind}`,
);

prisma.image.update({
await prisma.image.update({
include: {
aiKumikoResult: {
include: {
Expand All @@ -75,14 +75,24 @@ const runKumikoOnPage = async (
},
data: {
aiKumikoResult: {
update: {
inferredStoryKind: inferredStoryKind,
detectedPanels: {
deleteMany: {},
createMany: {
data: panelsOfPage,
},
upsert: {
create: {
inferredStoryKind: inferredStoryKind,
detectedPanels: {
createMany: {
data: panelsOfPage,
},
}
},
update: {
inferredStoryKind: inferredStoryKind,
detectedPanels: {
deleteMany: {},
createMany: {
data: panelsOfPage,
},
}
}
},
},
},
Expand All @@ -102,22 +112,29 @@ export const runKumikoOnPages = async (
indexation: FullIndexation,
force = false,
) => {
const updatedImageIds = indexation.pages.filter(async (page) =>
runKumikoOnPage(socket, page, force),
);
let updatedImageIds = []
for (const page of indexation.pages) {
if (await runKumikoOnPage(socket, page, force)) {
updatedImageIds.push(page.id);
}
}

const outdatedEntryIds = updatedImageIds
.map(({ id }) => getEntryFromPage(indexation, id)?.id)
const outdatedEntryIds = new Set(updatedImageIds
.map((id ) => getEntryFromPage(indexation, id)?.id)
.filter((id) => !!id)
.map((id) => id!);
.map((id) => id!))

if (!outdatedEntryIds.size) {
return
}

// Invalidate story kind suggestions for entries whose pages have been updated
await prisma.storyKindSuggestionAi.deleteMany({
where: {
storyKindSuggestion: {
entry: {
id: {
in: outdatedEntryIds,
in: outdatedEntryIds.values().toArray(),
},
},
},
Expand All @@ -130,7 +147,7 @@ export const runKumikoOnPages = async (
storySuggestion: {
entry: {
id: {
in: outdatedEntryIds,
in: outdatedEntryIds.values().toArray(),
},
},
},
Expand Down
Loading

0 comments on commit 279b7c2

Please sign in to comment.