Include voice recording payload in analysis
Build and deploy Worker / build (push) Successful in 53s
Build and deploy Worker / build (push) Successful in 53s
This commit is contained in:
@@ -24,7 +24,16 @@ model Place {
|
|||||||
longitude Float
|
longitude Float
|
||||||
googlePrimaryType String?
|
googlePrimaryType String?
|
||||||
googleTypes String[] @default([])
|
googleTypes String[] @default([])
|
||||||
|
googleBusinessStatus String?
|
||||||
|
googleRating Float?
|
||||||
|
googleUserRatingCount Int?
|
||||||
|
googleRegularOpeningHours Json?
|
||||||
|
googleCurrentOpeningHours Json?
|
||||||
|
googlePhotos Json?
|
||||||
|
googlePayload Json?
|
||||||
|
googlePayloadFetchedAt DateTime?
|
||||||
experiences VoiceExperience[]
|
experiences VoiceExperience[]
|
||||||
|
favoriteUsers UserFavoritePlace[]
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
@@ -39,10 +48,22 @@ model User {
|
|||||||
languageCode String?
|
languageCode String?
|
||||||
isAdmin Boolean @default(false)
|
isAdmin Boolean @default(false)
|
||||||
voiceExperiences VoiceExperience[]
|
voiceExperiences VoiceExperience[]
|
||||||
|
favoritePlaces UserFavoritePlace[]
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model UserFavoritePlace {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
userId String
|
||||||
|
user User @relation(fields: [userId], references: [id])
|
||||||
|
placeId String
|
||||||
|
place Place @relation(fields: [placeId], references: [id])
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
@@unique([userId, placeId])
|
||||||
|
}
|
||||||
|
|
||||||
model VoiceExperience {
|
model VoiceExperience {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
placeId String
|
placeId String
|
||||||
@@ -57,6 +78,8 @@ model VoiceExperience {
|
|||||||
status VoiceExperienceStatus @default(UPLOADED)
|
status VoiceExperienceStatus @default(UPLOADED)
|
||||||
transcript String?
|
transcript String?
|
||||||
analysis Json?
|
analysis Json?
|
||||||
|
recordingPayload Json?
|
||||||
|
promptHintsShown String[] @default([])
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -128,6 +128,14 @@ exports.Prisma.PlaceScalarFieldEnum = {
|
|||||||
longitude: 'longitude',
|
longitude: 'longitude',
|
||||||
googlePrimaryType: 'googlePrimaryType',
|
googlePrimaryType: 'googlePrimaryType',
|
||||||
googleTypes: 'googleTypes',
|
googleTypes: 'googleTypes',
|
||||||
|
googleBusinessStatus: 'googleBusinessStatus',
|
||||||
|
googleRating: 'googleRating',
|
||||||
|
googleUserRatingCount: 'googleUserRatingCount',
|
||||||
|
googleRegularOpeningHours: 'googleRegularOpeningHours',
|
||||||
|
googleCurrentOpeningHours: 'googleCurrentOpeningHours',
|
||||||
|
googlePhotos: 'googlePhotos',
|
||||||
|
googlePayload: 'googlePayload',
|
||||||
|
googlePayloadFetchedAt: 'googlePayloadFetchedAt',
|
||||||
createdAt: 'createdAt',
|
createdAt: 'createdAt',
|
||||||
updatedAt: 'updatedAt'
|
updatedAt: 'updatedAt'
|
||||||
};
|
};
|
||||||
@@ -145,6 +153,13 @@ exports.Prisma.UserScalarFieldEnum = {
|
|||||||
updatedAt: 'updatedAt'
|
updatedAt: 'updatedAt'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.Prisma.UserFavoritePlaceScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
userId: 'userId',
|
||||||
|
placeId: 'placeId',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
exports.Prisma.VoiceExperienceScalarFieldEnum = {
|
exports.Prisma.VoiceExperienceScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
placeId: 'placeId',
|
placeId: 'placeId',
|
||||||
@@ -157,6 +172,8 @@ exports.Prisma.VoiceExperienceScalarFieldEnum = {
|
|||||||
status: 'status',
|
status: 'status',
|
||||||
transcript: 'transcript',
|
transcript: 'transcript',
|
||||||
analysis: 'analysis',
|
analysis: 'analysis',
|
||||||
|
recordingPayload: 'recordingPayload',
|
||||||
|
promptHintsShown: 'promptHintsShown',
|
||||||
createdAt: 'createdAt',
|
createdAt: 'createdAt',
|
||||||
updatedAt: 'updatedAt'
|
updatedAt: 'updatedAt'
|
||||||
};
|
};
|
||||||
@@ -176,16 +193,16 @@ exports.Prisma.QueryMode = {
|
|||||||
insensitive: 'insensitive'
|
insensitive: 'insensitive'
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Prisma.NullsOrder = {
|
|
||||||
first: 'first',
|
|
||||||
last: 'last'
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.Prisma.JsonNullValueFilter = {
|
exports.Prisma.JsonNullValueFilter = {
|
||||||
DbNull: Prisma.DbNull,
|
DbNull: Prisma.DbNull,
|
||||||
JsonNull: Prisma.JsonNull,
|
JsonNull: Prisma.JsonNull,
|
||||||
AnyNull: Prisma.AnyNull
|
AnyNull: Prisma.AnyNull
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.Prisma.NullsOrder = {
|
||||||
|
first: 'first',
|
||||||
|
last: 'last'
|
||||||
|
};
|
||||||
exports.VoiceExperienceStatus = exports.$Enums.VoiceExperienceStatus = {
|
exports.VoiceExperienceStatus = exports.$Enums.VoiceExperienceStatus = {
|
||||||
UPLOADED: 'UPLOADED',
|
UPLOADED: 'UPLOADED',
|
||||||
TRANSCRIBING: 'TRANSCRIBING',
|
TRANSCRIBING: 'TRANSCRIBING',
|
||||||
@@ -198,6 +215,7 @@ exports.VoiceExperienceStatus = exports.$Enums.VoiceExperienceStatus = {
|
|||||||
exports.Prisma.ModelName = {
|
exports.Prisma.ModelName = {
|
||||||
Place: 'Place',
|
Place: 'Place',
|
||||||
User: 'User',
|
User: 'User',
|
||||||
|
UserFavoritePlace: 'UserFavoritePlace',
|
||||||
VoiceExperience: 'VoiceExperience'
|
VoiceExperience: 'VoiceExperience'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Vendored
+2433
-118
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "prisma-client-404088dc715856cb4ed2e7f2d4b8eb35c87427ce32c0e67bc04d6ff67961fc2b",
|
"name": "prisma-client-baa0475e783dd87e65df5f828f4a43807c3762e0c66b9d15b841a12e00ad0bd4",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"types": "index.d.ts",
|
"types": "index.d.ts",
|
||||||
"browser": "default.js",
|
"browser": "default.js",
|
||||||
|
|||||||
@@ -24,7 +24,16 @@ model Place {
|
|||||||
longitude Float
|
longitude Float
|
||||||
googlePrimaryType String?
|
googlePrimaryType String?
|
||||||
googleTypes String[] @default([])
|
googleTypes String[] @default([])
|
||||||
|
googleBusinessStatus String?
|
||||||
|
googleRating Float?
|
||||||
|
googleUserRatingCount Int?
|
||||||
|
googleRegularOpeningHours Json?
|
||||||
|
googleCurrentOpeningHours Json?
|
||||||
|
googlePhotos Json?
|
||||||
|
googlePayload Json?
|
||||||
|
googlePayloadFetchedAt DateTime?
|
||||||
experiences VoiceExperience[]
|
experiences VoiceExperience[]
|
||||||
|
favoriteUsers UserFavoritePlace[]
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
@@ -39,10 +48,22 @@ model User {
|
|||||||
languageCode String?
|
languageCode String?
|
||||||
isAdmin Boolean @default(false)
|
isAdmin Boolean @default(false)
|
||||||
voiceExperiences VoiceExperience[]
|
voiceExperiences VoiceExperience[]
|
||||||
|
favoritePlaces UserFavoritePlace[]
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model UserFavoritePlace {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
userId String
|
||||||
|
user User @relation(fields: [userId], references: [id])
|
||||||
|
placeId String
|
||||||
|
place Place @relation(fields: [placeId], references: [id])
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
@@unique([userId, placeId])
|
||||||
|
}
|
||||||
|
|
||||||
model VoiceExperience {
|
model VoiceExperience {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
placeId String
|
placeId String
|
||||||
@@ -57,6 +78,8 @@ model VoiceExperience {
|
|||||||
status VoiceExperienceStatus @default(UPLOADED)
|
status VoiceExperienceStatus @default(UPLOADED)
|
||||||
transcript String?
|
transcript String?
|
||||||
analysis Json?
|
analysis Json?
|
||||||
|
recordingPayload Json?
|
||||||
|
promptHintsShown String[] @default([])
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ type PlaceAnalysis = {
|
|||||||
summary: string;
|
summary: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type RecordingContext = {
|
||||||
|
promptHintsShown: string[];
|
||||||
|
recordingPayload: unknown;
|
||||||
|
};
|
||||||
|
|
||||||
export async function analyzeVoiceExperience(experienceId: string) {
|
export async function analyzeVoiceExperience(experienceId: string) {
|
||||||
const experience = await prisma.voiceExperience.findUnique({
|
const experience = await prisma.voiceExperience.findUnique({
|
||||||
where: { id: experienceId },
|
where: { id: experienceId },
|
||||||
@@ -48,6 +53,8 @@ export async function analyzeVoiceExperience(experienceId: string) {
|
|||||||
const analysis = await buildPlaceAnalysis({
|
const analysis = await buildPlaceAnalysis({
|
||||||
placeName: experience.place.name,
|
placeName: experience.place.name,
|
||||||
transcript: experience.transcript,
|
transcript: experience.transcript,
|
||||||
|
promptHintsShown: experience.promptHintsShown,
|
||||||
|
recordingPayload: experience.recordingPayload,
|
||||||
});
|
});
|
||||||
|
|
||||||
await prisma.voiceExperience.update({
|
await prisma.voiceExperience.update({
|
||||||
@@ -64,6 +71,8 @@ export async function analyzeVoiceExperience(experienceId: string) {
|
|||||||
async function buildPlaceAnalysis(input: {
|
async function buildPlaceAnalysis(input: {
|
||||||
placeName: string;
|
placeName: string;
|
||||||
transcript: string;
|
transcript: string;
|
||||||
|
promptHintsShown: string[];
|
||||||
|
recordingPayload: unknown;
|
||||||
}): Promise<PlaceAnalysis> {
|
}): Promise<PlaceAnalysis> {
|
||||||
if (!config.openRouterApiKey) {
|
if (!config.openRouterApiKey) {
|
||||||
throw new Error('OPENROUTER_API_KEY is required for voice analysis.');
|
throw new Error('OPENROUTER_API_KEY is required for voice analysis.');
|
||||||
@@ -146,6 +155,7 @@ async function buildPlaceAnalysis(input: {
|
|||||||
},
|
},
|
||||||
placeName: input.placeName,
|
placeName: input.placeName,
|
||||||
ontology,
|
ontology,
|
||||||
|
recordingContext: recordingContext(input),
|
||||||
transcript: input.transcript,
|
transcript: input.transcript,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -174,6 +184,13 @@ async function buildPlaceAnalysis(input: {
|
|||||||
return analysis;
|
return analysis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function recordingContext(input: RecordingContext) {
|
||||||
|
return {
|
||||||
|
promptHintsShown: input.promptHintsShown,
|
||||||
|
recordingPayload: input.recordingPayload,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function assertValidAnalysis(analysis: PlaceAnalysis) {
|
function assertValidAnalysis(analysis: PlaceAnalysis) {
|
||||||
const allowedTags = new Set(
|
const allowedTags = new Set(
|
||||||
placeOntology.flatMap((axis) =>
|
placeOntology.flatMap((axis) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user