mirror of
https://github.com/spliit-app/spliit.git
synced 2026-02-21 15:06:13 +01:00
Automatic category from expense title (#80)
* environment variable * random category draft * get category from ai * input limit and documentation * use watch * use field.name * prettier * presigned upload, readme warning, category to string util * prettier * check whether feature is enabled * use process.env * improved prompt to return id only * remove console.debug * show loader * share class name * prettier * use template literals * rename format util * prettier
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
'use server'
|
||||
import { getCategories } from '@/lib/api'
|
||||
import { env } from '@/lib/env'
|
||||
import { formatCategoryForAIPrompt } from '@/lib/utils'
|
||||
import OpenAI from 'openai'
|
||||
import { ChatCompletionCreateParamsNonStreaming } from 'openai/resources/index.mjs'
|
||||
|
||||
const openai = new OpenAI({ apiKey: env.OPENAI_API_KEY })
|
||||
|
||||
@@ -9,7 +11,7 @@ export async function extractExpenseInformationFromImage(imageUrl: string) {
|
||||
'use server'
|
||||
const categories = await getCategories()
|
||||
|
||||
const body = {
|
||||
const body: ChatCompletionCreateParamsNonStreaming = {
|
||||
model: 'gpt-4-vision-preview',
|
||||
messages: [
|
||||
{
|
||||
@@ -21,7 +23,7 @@ export async function extractExpenseInformationFromImage(imageUrl: string) {
|
||||
This image contains a receipt.
|
||||
Read the total amount and store it as a non-formatted number without any other text or currency.
|
||||
Then guess the category for this receipt amoung the following categories and store its ID: ${categories.map(
|
||||
({ id, grouping, name }) => `"${grouping}/${name}" (ID: ${id})`,
|
||||
(category) => formatCategoryForAIPrompt(category),
|
||||
)}.
|
||||
Guess the expense’s date and store it as yyyy-mm-dd.
|
||||
Guess a title for the expense.
|
||||
@@ -35,7 +37,7 @@ export async function extractExpenseInformationFromImage(imageUrl: string) {
|
||||
},
|
||||
],
|
||||
}
|
||||
const completion = await openai.chat.completions.create(body as any)
|
||||
const completion = await openai.chat.completions.create(body)
|
||||
|
||||
const [amountString, categoryId, date, title] = completion.choices
|
||||
.at(0)
|
||||
|
||||
@@ -29,7 +29,7 @@ import { useMediaQuery } from '@/lib/hooks'
|
||||
import { formatExpenseDate } from '@/lib/utils'
|
||||
import { Category } from '@prisma/client'
|
||||
import { ChevronRight, FileQuestion, Loader2, Receipt } from 'lucide-react'
|
||||
import { getImageData, useS3Upload } from 'next-s3-upload'
|
||||
import { getImageData, usePresignedUpload } from 'next-s3-upload'
|
||||
import Image from 'next/image'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { PropsWithChildren, ReactNode, useState } from 'react'
|
||||
@@ -46,7 +46,7 @@ export function CreateFromReceiptButton({
|
||||
categories,
|
||||
}: Props) {
|
||||
const [pending, setPending] = useState(false)
|
||||
const { uploadToS3, FileInput, openFileDialog } = useS3Upload()
|
||||
const { uploadToS3, FileInput, openFileDialog } = usePresignedUpload()
|
||||
const { toast } = useToast()
|
||||
const router = useRouter()
|
||||
const [receiptInfo, setReceiptInfo] = useState<
|
||||
|
||||
Reference in New Issue
Block a user