Add Ollama configuration for English coach

This commit is contained in:
Ismail Ali
2026-04-28 15:15:30 +02:00
parent a7caa22386
commit f288135378
5 changed files with 76 additions and 5 deletions

2
.env.example Normal file
View File

@@ -0,0 +1,2 @@
EXPO_PUBLIC_OLLAMA_BASE_URL=http://localhost:11434
EXPO_PUBLIC_OLLAMA_MODEL=llama3.2

View File

@@ -78,6 +78,26 @@ Abhaengigkeiten installieren:
npm install npm install
``` ```
Optionale lokale KI-Konfiguration anlegen:
```bash
cp .env.example .env
```
In `.env` kannst du dein Ollama-Modell eintragen:
```text
EXPO_PUBLIC_OLLAMA_BASE_URL=http://localhost:11434
EXPO_PUBLIC_OLLAMA_MODEL=llama3.2
```
Wenn du die App auf einem echten Smartphone mit Expo Go testest, ist `localhost` das Smartphone selbst. Nutze dann die IP deines PCs, zum Beispiel:
```text
EXPO_PUBLIC_OLLAMA_BASE_URL=http://192.168.10.102:11434
EXPO_PUBLIC_OLLAMA_MODEL=qwen2.5:7b
```
App starten: App starten:
```bash ```bash
@@ -98,9 +118,9 @@ npm run web
Hinweis: Fuer lokale iOS-Simulator-Builds wird macOS mit Xcode benoetigt. Mit Expo Go kann die App auf einem echten Geraet getestet werden. Hinweis: Fuer lokale iOS-Simulator-Builds wird macOS mit Xcode benoetigt. Mit Expo Go kann die App auf einem echten Geraet getestet werden.
## Ollama Integration Geplant ## Ollama Integration
Der aktuelle Chat nutzt `src/services/mockAiCoach.ts`. Dieser Service ist die vorgesehene Stelle, um spaeter einen echten KI-Client zu integrieren. Der Chat nutzt `src/services/ollamaClient.ts` fuer echte lokale KI-Antworten. Falls Ollama nicht erreichbar ist, faellt `src/services/mockAiCoach.ts` automatisch auf Beispielantworten zurueck. Die Modell-Konfiguration liegt in `src/config/ai.ts` und liest Werte aus `.env`.
Moeglicher lokaler Ablauf: Moeglicher lokaler Ablauf:

4
src/config/ai.ts Normal file
View File

@@ -0,0 +1,4 @@
export const aiConfig = {
ollamaBaseUrl: process.env.EXPO_PUBLIC_OLLAMA_BASE_URL ?? 'http://localhost:11434',
ollamaModel: process.env.EXPO_PUBLIC_OLLAMA_MODEL ?? 'llama3.2',
};

View File

@@ -1,4 +1,6 @@
import type { EnglishLevel } from '../navigation/types'; import type { EnglishLevel } from '../navigation/types';
import { aiConfig } from '../config/ai';
import { askOllama } from './ollamaClient';
const examples: Record<EnglishLevel, string> = { const examples: Record<EnglishLevel, string> = {
A1: 'Fast richtig! Correct: "I am learning English." Warum? Bei "I" nutzt du "am".', A1: 'Fast richtig! Correct: "I am learning English." Warum? Bei "I" nutzt du "am".',
@@ -8,11 +10,15 @@ const examples: Record<EnglishLevel, string> = {
}; };
export async function getMockAiReply(input: string, level: EnglishLevel) { export async function getMockAiReply(input: string, level: EnglishLevel) {
await new Promise((resolve) => setTimeout(resolve, 350));
if (!input.trim()) { if (!input.trim()) {
return 'Schreib einen kurzen englischen Satz, dann korrigiere ich ihn fuer dein Level.'; return 'Schreib einen kurzen englischen Satz, dann korrigiere ich ihn fuer dein Level.';
} }
return `${examples[level]}\n\nDein Satz: "${input.trim()}"`; try {
return await askOllama(input.trim(), level);
} catch {
await new Promise((resolve) => setTimeout(resolve, 350));
}
return `${examples[level]}\n\nDein Satz: "${input.trim()}"\n\nKI Backend vorbereitet: ${aiConfig.ollamaModel}`;
} }

View File

@@ -0,0 +1,39 @@
import { aiConfig } from '../config/ai';
import type { EnglishLevel } from '../navigation/types';
type OllamaGenerateResponse = {
response?: string;
};
export async function askOllama(input: string, level: EnglishLevel) {
const response = await fetch(`${aiConfig.ollamaBaseUrl}/api/generate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: aiConfig.ollamaModel,
stream: false,
prompt: buildPrompt(input, level),
}),
});
if (!response.ok) {
throw new Error(`Ollama request failed with ${response.status}`);
}
const data = (await response.json()) as OllamaGenerateResponse;
return data.response?.trim() || 'Ich konnte keine Antwort erzeugen.';
}
function buildPrompt(input: string, level: EnglishLevel) {
return `Du bist ein freundlicher Englisch-Coach fuer deutsche Lernende.
Level: ${level}
Aufgabe:
1. Korrigiere den englischen Satz.
2. Erklaere den wichtigsten Fehler kurz auf Deutsch.
3. Gib eine bessere natuerliche Variante.
4. Antworte kurz und motivierend.
Satz des Nutzers: ${input}`;
}