Files
mkdirs/scripts/explore-aisdk.ts
T
2026-08-09 23:23:29 +08:00

163 lines
5.0 KiB
TypeScript

import type { Category, Tag } from "@/sanity.types";
import { google } from "@ai-sdk/google";
import { createClient } from "@sanity/client";
import { generateObject, generateText } from "ai";
import dotenv from "dotenv";
import { z } from "zod";
dotenv.config();
// make sure you have set the environment variables in .env file
const client = createClient({
// biome-ignore lint/style/noNonNullAssertion: <explanation>
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
// biome-ignore lint/style/noNonNullAssertion: <explanation>
dataset: process.env.NEXT_PUBLIC_SANITY_DATASET!,
apiVersion: "2024-08-01",
useCdn: false,
perspective: "published",
token: process.env.SANITY_API_TOKEN,
});
/**
* AI SDK API Integration (using Google Gemini)
*
* This module provides functions to interact with the AI SDK,
* allowing you to fetch metadata from a given URL.
*
* Available functions:
* - aisdkFetch: Fetch data from AI SDK for the specified message
*/
// https://sdk.vercel.ai/docs/foundations/overview
// https://sdk.vercel.ai/docs/getting-started/nodejs
// test successfully: pnpm run aisdk:fetch "https://mkdirs.com"
export const aisdkFetch = async (url: string) => {
try {
const response = await fetch(url);
const htmlContent = (await response.text())
.replace(/class="[^"]*"/g, '')
.replace(/<svg[^>]*>.*?<\/svg>/g, '')
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
const prompt = `Analyze the following webpage content and URL: ${url}
Webpage content:
${htmlContent}
Based on the above content, provide the following information in a structured format:
1. Title of the page (extract from content if possible, just return the short name, no description)
2. Brief description (1 sentence summarizing the main content, no more than 160 characters)
3. Detailed introduction (in markdown format, include the key features and prices of the product)
Format your response as follows:
{
"title": "...",
"description": "...",
"introduction": "... (in markdown)"
}`;
const { text } = await generateText({
model: google("gemini-2.0-flash-exp"),
prompt: prompt,
});
console.log("aisdkFetch, url:", url, "response:", text);
return text;
} catch (error) {
console.error(`Error fetching data for URL ${url}:`, error);
return null;
}
};
// https://sdk.vercel.ai/providers/ai-sdk-providers/google-generative-ai#schema-limitations
// test successfully: pnpm run aisdk:structure "https://mkdirs.com"
export const aisdkStructure = async (url: string) => {
try {
// 获取实际的分类和标签数据
const categories = await client.fetch<Category[]>(`*[_type == "category"]`);
const tags = await client.fetch<Tag[]>(`*[_type == "tag"]`);
const schema = z.object({
title: z.string().describe("A short, concise name without description"),
description: z
.string()
.max(160)
.describe("One sentence summary, max 160 characters"),
introduction: z
.string()
.describe("Detailed introduction in markdown format"),
});
const response = await fetch(url);
const htmlContent = (await response.text())
.replace(/class="[^"]*"/g, '')
.replace(/<svg[^>]*>.*?<\/svg>/g, '')
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
const result = await generateObject({
model: google("gemini-2.0-flash-exp", {
structuredOutputs: true,
}),
schema,
prompt: `Analyze the following content and provide structured information:
Content to analyze:
${htmlContent}
Please provide a concise title, brief description, and detailed introduction.
The introduction should be in markdown format, include the key features and prices of the product.`,
});
console.log(
"aisdkStructure, url:",
url,
"structured response:",
result,
);
return result;
} catch (error) {
console.error(`Error processing url for ${url}:`, error);
return null;
}
};
// get operation from command line
const operation = process.argv[2];
// get message from command line (new)
const url = process.argv[3];
// run operation based on command line argument
const runOperation = async () => {
switch (operation) {
case "fetch": {
if (!url) {
console.error("Please provide a url as the second argument");
return;
}
const result = await aisdkFetch(url);
console.log("aisdkFetch, url:", url, "result:", result);
break;
}
case "structure": {
if (!url) {
console.error("Please provide a url as the second argument");
return;
}
const result = await aisdkStructure(url);
console.log("aisdkStructure, url:", url, "result:", result);
break;
}
default:
console.log(`
Available commands:
- fetch <url>: Fetch data for the specified url
- structure <url>: Fetch data for the specified url and return structured data
`);
}
};
// run operation
runOperation().catch(console.error);