feat: support openrouter in ai text (not stable for now)

This commit is contained in:
javayhu 2025-08-03 11:17:39 +08:00
parent 3c3dcd5d2a
commit 2b72570784
7 changed files with 36 additions and 4 deletions

View File

@ -183,6 +183,7 @@ OPENAI_API_KEY=""
REPLICATE_API_TOKEN=""
GOOGLE_GENERATIVE_AI_API_KEY=""
DEEPSEEK_API_KEY=""
OPENROUTER_API_KEY=""
# -----------------------------------------------------------------------------
# Web Content Analyzer (Firecrawl)

View File

@ -41,6 +41,7 @@
"@mendable/firecrawl-js": "^1.29.1",
"@next/third-parties": "^15.3.0",
"@openpanel/nextjs": "^1.0.7",
"@openrouter/ai-sdk-provider": "^1.0.0-beta.6",
"@orama/orama": "^3.1.4",
"@orama/tokenizers": "^3.1.4",
"@radix-ui/react-accordion": "^1.2.3",

15
pnpm-lock.yaml generated
View File

@ -59,6 +59,9 @@ importers:
'@openpanel/nextjs':
specifier: ^1.0.7
version: 1.0.7(next@15.2.1(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@openrouter/ai-sdk-provider':
specifier: ^1.0.0-beta.6
version: 1.0.0-beta.6(ai@5.0.0(zod@4.0.14))(zod@4.0.14)
'@orama/orama':
specifier: ^3.1.4
version: 3.1.4
@ -1730,6 +1733,13 @@ packages:
'@openpanel/web@1.0.1':
resolution: {integrity: sha512-cVZ7Kr9SicczJ/RDIfEtZs8+1iGDzwkabVA/j3NqSl8VSucsC8m1+LVbjmCDzCJNnK4yVn6tEcc9PJRi2rtllw==}
'@openrouter/ai-sdk-provider@1.0.0-beta.6':
resolution: {integrity: sha512-1cj8yUek4ib10MqZ+9fw1p1a3SR0Zhx3HH1J3+WQIXXuH/rUhiAkwovgPi1ADuC1QECPSPiwfhK2GecnDm8hGg==}
engines: {node: '>=18'}
peerDependencies:
ai: ^5.0.0-beta.12
zod: ^3.24.1 || ^v4
'@opentelemetry/api-logs@0.57.2':
resolution: {integrity: sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==}
engines: {node: '>=14'}
@ -7527,6 +7537,11 @@ snapshots:
dependencies:
'@openpanel/sdk': 1.0.0
'@openrouter/ai-sdk-provider@1.0.0-beta.6(ai@5.0.0(zod@4.0.14))(zod@4.0.14)':
dependencies:
ai: 5.0.0(zod@4.0.14)
zod: 4.0.14
'@opentelemetry/api-logs@0.57.2':
dependencies:
'@opentelemetry/api': 1.9.0

View File

@ -164,6 +164,7 @@ export function UrlInputForm({
<SelectItem value="openai">OpenAI GPT-4o</SelectItem>
<SelectItem value="gemini">Google Gemini</SelectItem>
<SelectItem value="deepseek">DeepSeek</SelectItem>
<SelectItem value="openrouter">OpenRouter</SelectItem>
</SelectContent>
</Select>
</div>

View File

@ -117,6 +117,13 @@ export const webContentAnalyzerConfig = {
temperature: 0.1,
maxTokens: 2000,
},
openrouter: {
model: 'openrouter/horizon-beta',
// model: 'x-ai/grok-3-beta',
// model: 'openai/gpt-4o-mini',
temperature: 0.1,
maxTokens: 2000,
},
} as const;
/**

View File

@ -97,9 +97,8 @@ export interface LoadingStatesProps {
// URL Validation Schema
export const urlSchema = z
.string()
.url()
.min(1, 'URL is required')
.url('Please enter a valid URL')
.refine(
(url) => url.startsWith('http://') || url.startsWith('https://'),
'URL must start with http:// or https://'
@ -114,13 +113,13 @@ export const analysisResultsSchema = z.object({
pricing: z.string().default('Not specified'),
useCases: z.array(z.string()).default([]),
url: urlSchema,
analyzedAt: z.string().datetime(),
analyzedAt: z.iso.datetime(),
});
// API Request Schema
export const analyzeContentRequestSchema = z.object({
url: urlSchema,
modelProvider: z.enum(['openai', 'gemini', 'deepseek']),
modelProvider: z.enum(['openai', 'gemini', 'deepseek', 'openrouter']),
});
// API Response Schema

View File

@ -23,6 +23,7 @@ import { createDeepSeek } from '@ai-sdk/deepseek';
import { createGoogleGenerativeAI } from '@ai-sdk/google';
import { createOpenAI } from '@ai-sdk/openai';
import FirecrawlApp from '@mendable/firecrawl-js';
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
import { generateObject } from 'ai';
import { type NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
@ -230,6 +231,13 @@ async function analyzeContent(
temperature = webContentAnalyzerConfig.deepseek.temperature;
maxTokens = webContentAnalyzerConfig.deepseek.maxTokens;
break;
case 'openrouter':
model = createOpenRouter({
apiKey: process.env.OPENROUTER_API_KEY,
}).chat(webContentAnalyzerConfig.openrouter.model);
temperature = webContentAnalyzerConfig.openrouter.temperature;
maxTokens = webContentAnalyzerConfig.openrouter.maxTokens;
break;
default:
throw new WebContentAnalyzerError(
ErrorType.VALIDATION,