14 if (!text?.trim()) return new Response("No text provided", { status: 400 });
15
16 const openaiKey = process.env.OPENAI_API_KEY;
17 if (!openaiKey) return new Response("Missing API key", { status: 500 });
18
19 const keyphrases = await generateKeyphrases(text, openaiKey);
20 return new Response(JSON.stringify(keyphrases), {
21 headers: { ...corsHeaders, "Content-Type": "application/json" },
34 `Analyze this text and output EXACTLY 10 unique keyphrases (2+ words each) as JSON array. Text: "${text}"`;
35
36 const response = await fetch("https://api.openai.com/v1/chat/completions", {
37 method: "POST",
38 headers: {
198 },
199 {
200 "title": "An Introduction to OpenAI fine-tuning",
201 "slug": "an-introduction-to-openai-fine-tuning",
202 "link": "/blog/an-introduction-to-openai-fine-tuning",
203 "description": "How to customize OpenAI to your liking",
204 "pubDate": "Fri, 25 Aug 2023 00:00:00 GMT",
205 "author": "Steve Krouse",
417 "slug": "val-town-newsletter-16",
418 "link": "/blog/val-town-newsletter-16",
419 "description": "Our seed round, growing team, Codeium completions, @std/openai, and more",
420 "pubDate": "Mon, 22 Apr 2024 00:00:00 GMT",
421 "author": "Steve Krouse",
198 },
199 {
200 "title": "An Introduction to OpenAI fine-tuning",
201 "slug": "an-introduction-to-openai-fine-tuning",
202 "link": "/blog/an-introduction-to-openai-fine-tuning",
203 "description": "How to customize OpenAI to your liking",
204 "pubDate": "Fri, 25 Aug 2023 00:00:00 GMT",
205 "author": "Steve Krouse",
417 "slug": "val-town-newsletter-16",
418 "link": "/blog/val-town-newsletter-16",
419 "description": "Our seed round, growing team, Codeium completions, @std/openai, and more",
420 "pubDate": "Mon, 22 Apr 2024 00:00:00 GMT",
421 "author": "Steve Krouse",
1// Combined Frontend (React/ChakraUI) and Backend (Hono/OpenAI) for Val Town
2// Funding Assistant Dashboard Prototype - v6 (Corrected AgencyInfo Prompt Logic)
3
509export default async function server(request: Request): Promise<Response> {
510 // Only import server-side dependencies here
511 const { OpenAI } = await import("https://esm.town/v/std/openai");
512 // const { sqlite } = await import("https://esm.town/v/stevekrouse/sqlite"); // DB optional
513 const { Hono } = await import("npm:hono");
514
515 // --- OpenAI Client ---
516 // Ensure API key is set as Val Town env var 'openai'
517 let openai;
518 try {
519 openai = new OpenAI();
520 } catch (e) {
521 console.error("FATAL: Failed to initialize OpenAI client. Is the 'openai' environment variable set?", e);
522 // Return a generic server error response if OpenAI cannot be initialized
523 return new Response(JSON.stringify({ error: "Server configuration error. Unable to initialize OpenAI client." }), {
524 status: 500,
525 headers: { "Content-Type": "application/json" },
675 ];
676
677 // --- Call OpenAI ---
678 console.log(`Calling OpenAI for agent: ${agentType}...`);
679 const completion = await openai.chat.completions.create({
680 messages: messages,
681 model: "gpt-4o",
706
707 } catch (error) {
708 // Catches errors in request handling, OpenAI API call itself, etc.
709 console.error(`Critical error initiating agent ${agentType}:`, error);
710 let errorMsg = `Server error initiating agent ${agentType}.`;
711 // Check for specific OpenAI errors if needed for better diagnostics
712 // if (error instanceof OpenAI.APIError) { errorMsg = `OpenAI API Error: ${error.status} ${error.message}`; }
713 else if (error.message) {
714 errorMsg = `${errorMsg} Details: ${error.message}`;
198 },
199 {
200 "title": "An Introduction to OpenAI fine-tuning",
201 "slug": "an-introduction-to-openai-fine-tuning",
202 "link": "/blog/an-introduction-to-openai-fine-tuning",
203 "description": "How to customize OpenAI to your liking",
204 "pubDate": "Fri, 25 Aug 2023 00:00:00 GMT",
205 "author": "Steve Krouse",
417 "slug": "val-town-newsletter-16",
418 "link": "/blog/val-town-newsletter-16",
419 "description": "Our seed round, growing team, Codeium completions, @std/openai, and more",
420 "pubDate": "Mon, 22 Apr 2024 00:00:00 GMT",
421 "author": "Steve Krouse",
198 },
199 {
200 "title": "An Introduction to OpenAI fine-tuning",
201 "slug": "an-introduction-to-openai-fine-tuning",
202 "link": "/blog/an-introduction-to-openai-fine-tuning",
203 "description": "How to customize OpenAI to your liking",
204 "pubDate": "Fri, 25 Aug 2023 00:00:00 GMT",
205 "author": "Steve Krouse",
417 "slug": "val-town-newsletter-16",
418 "link": "/blog/val-town-newsletter-16",
419 "description": "Our seed round, growing team, Codeium completions, @std/openai, and more",
420 "pubDate": "Mon, 22 Apr 2024 00:00:00 GMT",
421 "author": "Steve Krouse",
12
13async function gpt4(prompt: string): Promise<string> {
14 const { OpenAI } = await import("https://esm.town/v/std/openai");
15 const openai = new OpenAI();
16 const completion = await openai.chat.completions.create({
17 messages: [{ role: "user", content: prompt }],
18 model: "gpt-4-mini",
137Note: When changing a SQLite table's schema, change the table's name (e.g., add _2 or _3) to create a fresh table.
138
139### OpenAI
140```ts
141import { OpenAI } from "https://esm.town/v/std/openai";
142const openai = new OpenAI();
143const completion = await openai.chat.completions.create({
144 messages: [
145 { role: "user", content: "Say hello in a creative way" },
137Note: When changing a SQLite table's schema, change the table's name (e.g., add _2 or _3) to create a fresh table.
138
139### OpenAI
140```ts
141import { OpenAI } from "https://esm.town/v/std/openai";
142const openai = new OpenAI();
143const completion = await openai.chat.completions.create({
144 messages: [
145 { role: "user", content: "Say hello in a creative way" },
567// --- Backend Server (Val Town) ---
568export default async function server(request: Request): Promise<Response> {
569 const { OpenAI } = await import("https://esm.town/v/std/openai");
570
571 if (request.method === "OPTIONS") {
590 if (request.method === "POST" && new URL(request.url).pathname === "/grade-card") {
591 try {
592 // Check for OpenAI API Key in Val Town secrets
593 const openai = new OpenAI(); // Assumes OPENAI_API_KEY is set in Val Town secrets
594 const { imageBase64 } = await request.json();
595 if (!imageBase64 || typeof imageBase64 !== "string") {
600 }
601
602 console.log("Received image data, preparing request to OpenAI...");
603
604 const modelChoice = "gpt-4o"; // Or "gpt-4o-mini"
605
606 // --- Construct the detailed prompt for OpenAI ---
607 const prompt = `
608Alright, listen up, collector fam—here’s the no-BS, sharp-as-a-PSA-10 shorthand guide to grading and authenticating cards. No fluff, just gospel truths. Let’s get it:
712`;
713
714 const response = await openai.chat.completions.create({
715 model: modelChoice,
716 response_format: { type: "json_object" },
734 });
735
736 console.log("Received response from OpenAI.");
737
738 const jsonString = response.choices[0]?.message?.content;
739 if (!jsonString) {
740 throw new Error("OpenAI did not return valid response content.");
741 }
742
746 console.log("Successfully parsed JSON response.");
747 } catch (parseError) {
748 console.error("Failed to parse JSON from OpenAI:", jsonString);
749 throw new Error("AI returned improperly formatted JSON data.");
750 }