Add Ollama configuration for English coach
This commit is contained in:
2
.env.example
Normal file
2
.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
EXPO_PUBLIC_OLLAMA_BASE_URL=http://localhost:11434
|
||||
EXPO_PUBLIC_OLLAMA_MODEL=llama3.2
|
||||
24
README.md
24
README.md
@@ -78,6 +78,26 @@ Abhaengigkeiten installieren:
|
||||
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:
|
||||
|
||||
```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.
|
||||
|
||||
## 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:
|
||||
|
||||
|
||||
4
src/config/ai.ts
Normal file
4
src/config/ai.ts
Normal 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',
|
||||
};
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { EnglishLevel } from '../navigation/types';
|
||||
import { aiConfig } from '../config/ai';
|
||||
import { askOllama } from './ollamaClient';
|
||||
|
||||
const examples: Record<EnglishLevel, string> = {
|
||||
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) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 350));
|
||||
|
||||
if (!input.trim()) {
|
||||
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}`;
|
||||
}
|
||||
|
||||
39
src/services/ollamaClient.ts
Normal file
39
src/services/ollamaClient.ts
Normal 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}`;
|
||||
}
|
||||
Reference in New Issue
Block a user