Commit 55ea7dcf authored by Kantz's avatar Kantz
Browse files

adden GWDG API

parent 9c04fca1
...@@ -2,11 +2,20 @@ from __future__ import annotations ...@@ -2,11 +2,20 @@ from __future__ import annotations
from typing import List, Optional from typing import List, Optional
import os
from fastapi import APIRouter, HTTPException from fastapi import APIRouter, HTTPException
from dotenv import load_dotenv
import httpx
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
router = APIRouter() router = APIRouter()
load_dotenv()
OPENAI_BASE_URL = os.getenv("OPENAI_BASE_URL")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
class ChatMessage(BaseModel): class ChatMessage(BaseModel):
role: str = Field(..., pattern="^(user|assistant)$") role: str = Field(..., pattern="^(user|assistant)$")
...@@ -28,6 +37,31 @@ def chat(request: ChatRequest) -> ChatResponse: ...@@ -28,6 +37,31 @@ def chat(request: ChatRequest) -> ChatResponse:
if not request.messages: if not request.messages:
raise HTTPException(status_code=400, detail="messages required") raise HTTPException(status_code=400, detail="messages required")
last = request.messages[-1] if not OPENAI_BASE_URL or not OPENAI_API_KEY:
reply = f"Mock reply to: {last.text}" last = request.messages[-1]
return ChatResponse(reply=reply, sources=["doc:example"]) reply = f"Mock reply to: {last.text}"
return ChatResponse(reply=reply, sources=["doc:example"])
messages_payload = [
{"role": message.role, "content": message.text}
for message in request.messages
]
payload = {
"model": OPENAI_MODEL,
"messages": messages_payload,
}
headers = {"Authorization": f"Bearer {OPENAI_API_KEY}"}
url = f"{OPENAI_BASE_URL.rstrip('/')}/v1/chat/completions"
try:
with httpx.Client(timeout=60.0) as client:
response = client.post(url, headers=headers, json=payload)
response.raise_for_status()
except httpx.HTTPError as exc:
raise HTTPException(status_code=502, detail="chat provider failed") from exc
data = response.json()
reply = data["choices"][0]["message"]["content"]
return ChatResponse(reply=reply, sources=["openai-compatible"])
...@@ -2,4 +2,5 @@ fastapi ...@@ -2,4 +2,5 @@ fastapi
uvicorn uvicorn
python-dotenv python-dotenv
mpxpy mpxpy
pillow pillow
\ No newline at end of file httpx
...@@ -33,7 +33,7 @@ export default function App() { ...@@ -33,7 +33,7 @@ export default function App() {
const [draft, setDraft] = useState(""); const [draft, setDraft] = useState("");
const [isCanvasVisible, setIsCanvasVisible] = useState(true); const [isCanvasVisible, setIsCanvasVisible] = useState(true);
const handleSend = () => { const handleSend = async () => {
const trimmed = draft.trim(); const trimmed = draft.trim();
if (!trimmed) { if (!trimmed) {
return; return;
...@@ -45,14 +45,47 @@ export default function App() { ...@@ -45,14 +45,47 @@ export default function App() {
text: trimmed, text: trimmed,
}; };
const assistantMessage: ChatMessage = { setMessages((prev) => [...prev, userMessage]);
id: `m-${Date.now()}-assistant`,
role: "assistant",
text: "Got it. I will solve that step by step.",
};
setMessages((prev) => [...prev, userMessage, assistantMessage]);
setDraft(""); setDraft("");
try {
const response = await fetch("http://localhost:8000/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
messages: [...messages, userMessage].map((message) => ({
role: message.role,
text: message.text,
})),
}),
});
if (!response.ok) {
throw new Error(`Chat failed: ${response.status}`);
}
const payload: { reply?: string } = await response.json();
if (payload.reply) {
setMessages((prev) => [
...prev,
{
id: `m-${Date.now()}-assistant`,
role: "assistant",
text: payload.reply,
},
]);
}
} catch (error) {
setMessages((prev) => [
...prev,
{
id: `m-${Date.now()}-assistant`,
role: "assistant",
text: "Chat request failed. Check the API logs.",
},
]);
void error;
}
}; };
const handleToggleCanvas = () => { const handleToggleCanvas = () => {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment