File size: 4,468 Bytes
55a034a
 
 
 
 
 
 
 
831f7e7
 
 
 
81e6964
831f7e7
 
 
 
81e6964
831f7e7
 
 
81e6964
 
831f7e7
 
 
 
 
 
 
 
 
 
 
 
 
55a034a
 
 
 
 
 
831f7e7
 
55a034a
0ce34cb
831f7e7
0ce34cb
55a034a
 
 
 
8725cc4
 
 
 
 
 
 
 
 
 
 
831f7e7
8725cc4
 
ac04e03
13a00bb
8725cc4
 
 
 
 
 
0ce34cb
8725cc4
 
831f7e7
8725cc4
 
 
 
 
 
 
 
 
 
 
 
831f7e7
8725cc4
 
 
 
55a034a
8725cc4
 
 
 
55a034a
8725cc4
55a034a
 
 
8725cc4
 
 
 
 
55a034a
8725cc4
 
 
 
55a034a
8725cc4
55a034a
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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 game. The secret word is",
    task: "Your task is to find a sentence to describe this word without using it directly.",
    instruction: "Answer with a description for this word. Start your answer with"
  },
  fr: {
    systemPrompt: "Vous aidez dans un jeu de mots. Le mot secret est",
    task: "Votre tâche est de trouver une phrase pour décrire ce mot sans l'utiliser directement.",
    instruction: "Répondez avec une phrase qui commence par"
  },
  de: {
    systemPrompt: "Sie helfen bei einem Wortspiel. Das geheime Wort ist",
    task: "Ihre Aufgabe ist es, eine Beschreibung zu finden, der dieses Wort beschreibt, ohne es direkt zu verwenden.",
    instruction: "Beginnen sie ihre Antwort mit"
  },
  it: {
    systemPrompt: "Stai aiutando in un gioco di parole. La parola segreta è",
    task: "Il tuo compito è trovare una frase per descrivere questa parola senza usarla direttamente.",
    instruction: "Rispondi con una frase completa e grammaticalmente corretta che inizia con"
  },
  es: {
    systemPrompt: "Estás ayudando en un juego de palabras. La palabra secreta es",
    task: "Tu tarea es encontrar una frase para describir esta palabra sin usarla directamente.",
    instruction: "Responde con una frase completa y gramaticalmente correcta que comience con"
  }
};

serve(async (req) => {
  if (req.method === 'OPTIONS') {
    return new Response(null, { headers: corsHeaders });
  }

  try {
    const { currentWord, currentSentence, language = 'en' } = await req.json();
    console.log('Generating word for:', { currentWord, currentSentence, language });

    const existingSentence = currentSentence || '';
    const prompts = languagePrompts[language as keyof typeof languagePrompts] || languagePrompts.en;

    const client = new Mistral({
      apiKey: Deno.env.get('MISTRAL_API_KEY'),
    });

    const maxRetries = 3;
    let retryCount = 0;
    let lastError = null;

    while (retryCount < maxRetries) {
      try {
        const response = await client.chat.complete({
          model: "mistral-large-latest",
          messages: [
            {
              role: "system",
              content: `${prompts.systemPrompt} "${currentWord}". ${prompts.task} ${prompts.instruction} "${existingSentence}". Do not add quotes or backticks. Just answer with the sentence.`
            }
          ],
          maxTokens: 300,
          temperature: 0.5
        });

        const aiResponse = response.choices[0].message.content.trim();
        console.log('AI full response:', aiResponse);
        
        const newWord = aiResponse
          .slice(existingSentence.length)
          .trim()
          .split(' ')[0]
          .replace(/[.,!?]$/, '');
        
        console.log('Extracted new word:', newWord);

        return new Response(
          JSON.stringify({ word: newWord }),
          { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
        );
      } catch (error) {
        console.error(`Attempt ${retryCount + 1} failed:`, error);
        lastError = error;
        
        if (error.message?.includes('rate limit') || error.status === 429) {
          const waitTime = Math.pow(2, retryCount) * 1000;
          console.log(`Rate limit hit, waiting ${waitTime}ms before retry`);
          await new Promise(resolve => setTimeout(resolve, waitTime));
          retryCount++;
          continue;
        }
        
        throw error;
      }
    }

    throw new Error(`Failed after ${maxRetries} attempts. Last error: ${lastError?.message}`);

  } catch (error) {
    console.error('Error generating word:', error);
    
    const errorMessage = error.message?.includes('rate limit') 
      ? "The AI service is currently busy. Please try again in a few moments."
      : "Sorry, there was an error generating the word. Please try again.";

    return new Response(
      JSON.stringify({ 
        error: errorMessage,
        details: error.message 
      }),
      { 
        status: error.message?.includes('rate limit') ? 429 : 500,
        headers: { ...corsHeaders, 'Content-Type': 'application/json' }
      }
    );
  }
});