Skip to content

Commit

Permalink
feature: user generated logs
Browse files Browse the repository at this point in the history
This commit implements the ability to upload user generated logs to a
project. It adds a new route for uploading logs and a new page for the
user to upload logs. Logs are stored in the same way as regular document
logs but they lack some optional fields such as duration, cost, token
count or finish reason. The only required field is the messages array.
  • Loading branch information
geclos committed Oct 28, 2024
1 parent fb7edca commit b9db3dd
Show file tree
Hide file tree
Showing 49 changed files with 12,651 additions and 224 deletions.
73 changes: 0 additions & 73 deletions apps/gateway/src/common/messageSchema.ts

This file was deleted.

3 changes: 3 additions & 0 deletions apps/gateway/src/common/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ const ROUTES = {
Get: '/:documentPath{.+}',
Run: '/run',
},
Logs: {
Base: '/projects/:projectId/versions/:versionUuid/logs',
},
},
},
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { zValidator } from '@hono/zod-validator'
import { LogSources } from '@latitude-data/core/browser'
import { LogSources, messagesSchema } from '@latitude-data/core/browser'
import { streamToGenerator } from '@latitude-data/core/lib/streamToGenerator'
import { addMessages } from '@latitude-data/core/services/documentLogs/index'
import { captureException } from '@sentry/node'
import { messageSchema } from '$/common/messageSchema'
import { Factory } from 'hono/factory'
import { streamSSE } from 'hono/streaming'
import { z } from 'zod'
Expand All @@ -13,7 +12,7 @@ import { chainEventPresenter } from '../../../projects/[projectId]/versions/[ver
const factory = new Factory()

const schema = z.object({
messages: z.array(messageSchema),
messages: messagesSchema,
__internal: z
.object({
source: z.nativeEnum(LogSources).optional(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { zValidator } from '@hono/zod-validator'
import { LogSources, messagesSchema } from '@latitude-data/core/browser'
import { generateUUIDIdentifier } from '@latitude-data/core/lib/generateUUID'
import { createDocumentLog } from '@latitude-data/core/services/documentLogs/create'
import { getData } from '$/routes/api/v1/projects/[projectId]/versions/[versionUuid]/documents/handlers/_shared'
import { Factory } from 'hono/factory'
import { z } from 'zod'

const factory = new Factory()

const schema = z.object({
path: z.string(),
messages: messagesSchema,
response: z.string().optional(),
})

export const postHandler = factory.createHandlers(
zValidator('json', schema),
async (c) => {
const { projectId, versionUuid } = c.req.param()
const { path, messages, response } = c.req.valid('json')
const workspace = c.get('workspace')
const { document, commit } = await getData({
workspace,
projectId: Number(projectId!),
commitUuid: versionUuid!,
documentPath: path!,
}).then((r) => r.unwrap())

const documentLog = await createDocumentLog({
data: {
uuid: generateUUIDIdentifier(),
documentUuid: document.documentUuid,
resolvedContent: document.content,
source: LogSources.API,
parameters: {},
providerLog: {
messages,
responseText:
response ??
(messages[messages.length - 1].content?.text ||
messages[messages.length - 1].content),
},
},
commit,
}).then((r) => r.unwrap())

return c.json(documentLog)
},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import ROUTES from '$/common/routes'
import { Hono } from 'hono'

import { postHandler } from './handlers/post'

const router = new Hono()

router.post(ROUTES.Api.V2.Logs.Base, ...postHandler)

export { router as documentsRouter }
22 changes: 6 additions & 16 deletions apps/web/src/actions/datasets/create.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
'use server'

import {
DELIMITER_VALUES,
DELIMITERS_KEYS,
MAX_SIZE,
MAX_UPLOAD_SIZE_IN_MB,
} from '@latitude-data/core/browser'
import { DatasetsRepository } from '@latitude-data/core/repositories'
import { createDataset } from '@latitude-data/core/services/datasets/create'
import { z } from 'zod'

import { authProcedure } from '../procedures'

const DELIMITERS_KEYS = [
'comma',
'semicolon',
'tab',
'space',
'custom',
] as const
const DELIMITER_VALUES = {
comma: ',',
semicolon: ';',
tab: '\t',
space: ' ',
}

const MAX_SIZE = 15
const MAX_UPLOAD_SIZE_IN_MB = MAX_SIZE * 1024 * 1024
export const createDatasetAction = authProcedure
.createServerAction()
.input(
Expand Down
50 changes: 50 additions & 0 deletions apps/web/src/actions/documentLogs/upload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use server'

import {
DELIMITERS_KEYS,
MAX_SIZE,
MAX_UPLOAD_SIZE_IN_MB,
} from '@latitude-data/core/browser'
import { CommitsRepository } from '@latitude-data/core/repositories'
import { bulkUploadDocumentLogs } from '@latitude-data/core/services/documentLogs/bulkUpload'
import { z } from 'zod'

import { withDocument } from '../procedures'

export const uploadDocumentLogsAction = withDocument
.createServerAction()
.input(
z.object({
csvDelimiter: z.enum(DELIMITERS_KEYS, {
message: 'Choose a valid delimiter option',
}),
logsFile: z
.instanceof(File)
.refine((file) => {
return !file || file.size <= MAX_UPLOAD_SIZE_IN_MB
}, `Your file must be less than ${MAX_SIZE}MB in size`)
.refine(
(file) => file.type === 'text/csv',
'Your file must be a CSV file',
),
}),
)
.handler(async ({ ctx, input }) => {
const commitsScope = new CommitsRepository(ctx.workspace.id)
const commit = await commitsScope
.getCommitByUuid({
projectId: ctx.project.id,
uuid: ctx.currentCommitUuid,
})
.then((r) => r.unwrap())

await bulkUploadDocumentLogs({
workspace: ctx.workspace,
document: ctx.document,
commit,
csvDelimiter: input.csvDelimiter,
logsFile: input.logsFile,
})

return { success: true }
})
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,22 @@ export enum DelimiterEnum {
}

const DELIMITERS = [
{ value: DelimiterEnum.Comma, label: 'Comma (ex.: column1,column2,column3)' },
{
value: DelimiterEnum.Comma,
label: 'Comma (e.g.: column1,column2,column3)',
},
{
value: DelimiterEnum.Semicolon,
label: 'Semicolon (ex.: column1;column2;column3)',
label: 'Semicolon (e.g.: column1;column2;column3)',
},
{
value: DelimiterEnum.Tab,
label: 'Tab (ex.: column1 \\t column2 \\t column3)',
label: 'Tab (e.g.: column1 \\t column2 \\t column3)',
},
{
value: DelimiterEnum.Space,
label: 'Space (e.g.: column1 column2 column3)',
},
{ value: DelimiterEnum.Space, label: 'Space (ex.: column1 column2 column3)' },
{ value: DelimiterEnum.Custom, label: 'Custom' },
]
export const DELIMITER_KEYS = DELIMITERS.map(({ value }) => value)
Expand All @@ -32,15 +38,15 @@ export default function DelimiterSelector({
customDelimiterInputName,
delimiterErrors,
customDelimiterErrors,
delimiterValue,
delimiterDefaultValue,
customDelimiterValue,
}: {
delimiterInputName: string
delimiterValue: string | undefined
delimiterErrors: string[] | undefined
delimiterDefaultValue?: string | undefined
delimiterErrors?: string[] | undefined
customDelimiterInputName: string
customDelimiterValue: string
customDelimiterErrors: string[] | undefined
customDelimiterValue?: string
customDelimiterErrors?: string[] | undefined
}) {
const inputRef = useRef<HTMLInputElement>(null)
const [isCustom, setIsCustom] = useState(false)
Expand All @@ -60,7 +66,7 @@ export default function DelimiterSelector({
<Select
name={delimiterInputName}
options={DELIMITERS}
defaultValue={delimiterValue}
defaultValue={delimiterDefaultValue}
onChange={onSelectChange}
errors={delimiterErrors}
/>
Expand Down
1 change: 0 additions & 1 deletion apps/web/src/app/(private)/datasets/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export default function NewDataset() {
placeholder='Amazing dataset'
/>
<DelimiterSelector
delimiterValue={undefined}
delimiterInputName='csvDelimiter'
delimiterErrors={errors?.csvDelimiter}
customDelimiterInputName='csvCustomDelimiter'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ function ProviderLogItems({
value={format(evaluationResult.createdAt, 'PPp')}
/>
<FinishReasonItem providerLog={providerLog} />
<MetadataItem label='Tokens' value={providerLog.tokens.toString()} />
<MetadataItem
label='Tokens'
value={providerLog?.tokens?.toString() ?? '-'}
/>
<MetadataItem label='Model' value={providerLog.model ?? 'Unknown'} />
<MetadataItem label='Provider' value={providerName} />
<MetadataItemTooltip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export function DocumentLogMessages({

const messages = useMemo<Message[]>(() => {
if (!providerLog) return [] as Message[]
if (!providerLog.response) return providerLog.messages

const responseMessage = {
role: MessageRole.assistant,
Expand Down
Loading

0 comments on commit b9db3dd

Please sign in to comment.