|
import { serve } from "https://deno.land/[email protected]/http/server.ts"; |
|
import { Mistral } from "npm:@mistralai/mistralai"; |
|
|
|
const corsHeaders = { |
|
'Access-Control-Allow-Origin': '*', |
|
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', |
|
}; |
|
|
|
const languagePrompts = { |
|
en: { |
|
systemPrompt: "You are helping in a word guessing game. Given a description, guess what single word is being described.", |
|
instruction: "Based on this description" |
|
}, |
|
fr: { |
|
systemPrompt: "Vous aidez dans un jeu de devinettes. À partir d'une description, devinez le mot unique qui est décrit.", |
|
instruction: "D'après cette description" |
|
}, |
|
de: { |
|
systemPrompt: "Sie helfen bei einem Worträtsel. Erraten Sie anhand einer Beschreibung, welches einzelne Wort beschrieben wird.", |
|
instruction: "Basierend auf dieser Beschreibung" |
|
}, |
|
it: { |
|
systemPrompt: "Stai aiutando in un gioco di indovinelli. Data una descrizione, indovina quale singola parola viene descritta.", |
|
instruction: "Basandoti su questa descrizione" |
|
}, |
|
es: { |
|
systemPrompt: "Estás ayudando en un juego de adivinanzas. Dada una descripción, adivina qué palabra única se está describiendo.", |
|
instruction: "Basándote en esta descripción" |
|
} |
|
}; |
|
|
|
const openRouterModels = [ |
|
'sophosympatheia/rogue-rose-103b-v0.2:free', |
|
'google/gemini-2.0-flash-exp:free', |
|
'meta-llama/llama-3.1-70b-instruct:free', |
|
'microsoft/phi-3-medium-128k-instruct:free' |
|
]; |
|
|
|
async function tryMistral(sentence: string, language: string) { |
|
const client = new Mistral({ |
|
apiKey: Deno.env.get('MISTRAL_API_KEY'), |
|
}); |
|
|
|
const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en; |
|
|
|
const response = await client.chat.complete({ |
|
model: "mistral-large-latest", |
|
messages: [ |
|
{ |
|
role: "system", |
|
content: `${prompts.systemPrompt} Respond with ONLY the word you think is being described, in uppercase letters. Do not add any explanation or punctuation.` |
|
}, |
|
{ |
|
role: "user", |
|
content: `${prompts.instruction} "${sentence}"` |
|
} |
|
], |
|
maxTokens: 50, |
|
temperature: 0.1 |
|
}); |
|
|
|
return response.choices[0].message.content.trim().toUpperCase(); |
|
} |
|
|
|
async function tryOpenRouter(sentence: string, language: string) { |
|
const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en; |
|
const randomModel = openRouterModels[Math.floor(Math.random() * openRouterModels.length)]; |
|
|
|
console.log('Trying OpenRouter with model:', randomModel); |
|
|
|
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", { |
|
method: "POST", |
|
headers: { |
|
"Authorization": `Bearer ${Deno.env.get('OPENROUTER_API_KEY')}`, |
|
"HTTP-Referer": "https://think-in-sync.com", |
|
"X-Title": "Think in Sync", |
|
"Content-Type": "application/json" |
|
}, |
|
body: JSON.stringify({ |
|
model: randomModel, |
|
messages: [ |
|
{ |
|
role: "system", |
|
content: `${prompts.systemPrompt} Respond with ONLY the word you think is being described, in uppercase letters. Do not add any explanation or punctuation.` |
|
}, |
|
{ |
|
role: "user", |
|
content: `${prompts.instruction} "${sentence}"` |
|
} |
|
] |
|
}) |
|
}); |
|
|
|
if (!response.ok) { |
|
throw new Error(`OpenRouter API error: ${response.status}`); |
|
} |
|
|
|
const data = await response.json(); |
|
return data.choices[0].message.content.trim().toUpperCase(); |
|
} |
|
|
|
serve(async (req) => { |
|
if (req.method === 'OPTIONS') { |
|
return new Response(null, { headers: corsHeaders }); |
|
} |
|
|
|
try { |
|
const { sentence, language = 'en' } = await req.json(); |
|
console.log('Trying to guess word from sentence:', sentence, 'language:', language); |
|
|
|
try { |
|
console.log('Attempting with Mistral...'); |
|
const guess = await tryMistral(sentence, language); |
|
console.log('Successfully generated guess with Mistral:', guess); |
|
return new Response( |
|
JSON.stringify({ guess }), |
|
{ headers: { ...corsHeaders, 'Content-Type': 'application/json' } } |
|
); |
|
} catch (mistralError) { |
|
console.error('Mistral error:', mistralError); |
|
console.log('Falling back to OpenRouter...'); |
|
|
|
const guess = await tryOpenRouter(sentence, language); |
|
console.log('Successfully generated guess with OpenRouter:', guess); |
|
return new Response( |
|
JSON.stringify({ guess }), |
|
{ headers: { ...corsHeaders, 'Content-Type': 'application/json' } } |
|
); |
|
} |
|
} catch (error) { |
|
console.error('Error generating guess:', error); |
|
return new Response( |
|
JSON.stringify({ error: error.message }), |
|
{ |
|
status: 500, |
|
headers: { ...corsHeaders, 'Content-Type': 'application/json' } |
|
} |
|
); |
|
} |
|
}); |
|
|