Next.js 14 drink collection tracker with AI-powered search, menu scanning, ratings, wishlist, sharing, and CSV backup/restore. Features: - Auth (credentials + OAuth ready) - Drink collection with ratings and reviews - AI search via Claude/OpenAI with search history - Menu photo scanning with AI extraction - Wishlist / Try Later system - Public sharing via slug URLs - CSV backup and restore (merge/replace modes) - Docker Compose for Postgres + MinIO + dev server Security: docker-compose files use env var interpolation instead of hardcoded secrets. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
82 lines
1.8 KiB
TypeScript
82 lines
1.8 KiB
TypeScript
import OpenAI from "openai"
|
|
import { BaseAIProvider } from "./base-provider"
|
|
|
|
export class OpenAIProvider extends BaseAIProvider {
|
|
name = "openai"
|
|
private client: OpenAI
|
|
|
|
constructor(apiKey: string) {
|
|
super()
|
|
this.client = new OpenAI({ apiKey })
|
|
}
|
|
|
|
async sendVisionRequest(
|
|
systemPrompt: string,
|
|
imageBase64: string,
|
|
mimeType: string
|
|
): Promise<string> {
|
|
const dataUrl = `data:${mimeType};base64,${imageBase64}`
|
|
|
|
const response = await this.client.chat.completions.create({
|
|
model: "gpt-4o",
|
|
max_tokens: 4096,
|
|
messages: [
|
|
{
|
|
role: "system",
|
|
content: systemPrompt,
|
|
},
|
|
{
|
|
role: "user",
|
|
content: [
|
|
{
|
|
type: "image_url",
|
|
image_url: {
|
|
url: dataUrl,
|
|
detail: "high",
|
|
},
|
|
},
|
|
{
|
|
type: "text",
|
|
text: "Please analyze this image and extract the information as instructed.",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
})
|
|
|
|
const message = response.choices[0]?.message?.content
|
|
if (!message) {
|
|
throw new Error("No response received from OpenAI")
|
|
}
|
|
|
|
return message
|
|
}
|
|
|
|
async sendTextRequest(
|
|
systemPrompt: string,
|
|
userMessage: string
|
|
): Promise<string> {
|
|
const response = await this.client.chat.completions.create({
|
|
model: "gpt-4o",
|
|
max_tokens: 4096,
|
|
messages: [
|
|
{
|
|
role: "system",
|
|
content: systemPrompt,
|
|
},
|
|
{
|
|
role: "user",
|
|
content: userMessage,
|
|
},
|
|
],
|
|
})
|
|
|
|
const message = response.choices[0]?.message?.content
|
|
if (!message) {
|
|
throw new Error("No response received from OpenAI")
|
|
}
|
|
|
|
return message
|
|
}
|
|
}
|