Gemini commited on
Commit
88df89c
·
1 Parent(s): c62dca7

feat: Implement streaming response for chat

Browse files
Files changed (2) hide show
  1. main.py +16 -12
  2. static/script.js +43 -4
main.py CHANGED
@@ -1,6 +1,6 @@
1
  import requests
2
  from fastapi import FastAPI, Request, HTTPException
3
- from fastapi.responses import FileResponse, RedirectResponse
4
  from fastapi.staticfiles import StaticFiles
5
 
6
  OLLAMA_API_URL = "http://localhost:11434"
@@ -19,16 +19,20 @@ async def chat_endpoint(request: Request):
19
  raise HTTPException(status_code=400, detail="Prompt is required")
20
 
21
  url = f"{OLLAMA_API_URL}/api/generate"
22
-
23
- try:
24
- response = requests.post(
25
- url=url,
26
- json={"model": model, "prompt": prompt, "stream": False}
27
- )
28
-
29
- return response.json()
30
- except Exception as e:
31
- raise HTTPException(status_code=500, detail=str(e))
 
 
 
 
32
 
33
  @app.get("/")
34
  async def root():
@@ -36,4 +40,4 @@ async def root():
36
 
37
  @app.get("/chat")
38
  async def chat_page():
39
- return FileResponse('chat.html')
 
1
  import requests
2
  from fastapi import FastAPI, Request, HTTPException
3
+ from fastapi.responses import FileResponse, RedirectResponse, StreamingResponse
4
  from fastapi.staticfiles import StaticFiles
5
 
6
  OLLAMA_API_URL = "http://localhost:11434"
 
19
  raise HTTPException(status_code=400, detail="Prompt is required")
20
 
21
  url = f"{OLLAMA_API_URL}/api/generate"
22
+
23
+ async def stream_response():
24
+ try:
25
+ response = requests.post(
26
+ url=url,
27
+ json={"model": model, "prompt": prompt, "stream": True},
28
+ stream=True
29
+ )
30
+ for chunk in response.iter_content(chunk_size=None):
31
+ yield chunk
32
+ except Exception as e:
33
+ print(f"Error during streaming: {e}")
34
+
35
+ return StreamingResponse(stream_response(), media_type="application/x-ndjson")
36
 
37
  @app.get("/")
38
  async def root():
 
40
 
41
  @app.get("/chat")
42
  async def chat_page():
43
+ return FileResponse('chat.html')
static/script.js CHANGED
@@ -18,6 +18,8 @@ function sendMessage() {
18
  appendMessage(message, 'user-message');
19
  messageInput.value = '';
20
 
 
 
21
  fetch('/chat_api', {
22
  method: 'POST',
23
  headers: {
@@ -28,13 +30,42 @@ function sendMessage() {
28
  prompt: message
29
  })
30
  })
31
- .then(response => response.json())
32
- .then(data => {
33
- appendMessage(data.response, 'bot-message');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  })
35
  .catch(error => {
36
  console.error('Error:', error);
37
- appendMessage('Sorry, something went wrong.', 'bot-message');
 
 
 
38
  });
39
  }
40
 
@@ -45,3 +76,11 @@ function appendMessage(message, className) {
45
  messageList.appendChild(li);
46
  messageList.scrollTop = messageList.scrollHeight;
47
  }
 
 
 
 
 
 
 
 
 
18
  appendMessage(message, 'user-message');
19
  messageInput.value = '';
20
 
21
+ appendMessage('', 'bot-message'); // Create an empty message element for the bot's response
22
+
23
  fetch('/chat_api', {
24
  method: 'POST',
25
  headers: {
 
30
  prompt: message
31
  })
32
  })
33
+ .then(response => {
34
+ const reader = response.body.getReader();
35
+ const decoder = new TextDecoder();
36
+ let partialResponse = '';
37
+
38
+ function read() {
39
+ reader.read().then(({ done, value }) => {
40
+ if (done) {
41
+ return;
42
+ }
43
+ partialResponse += decoder.decode(value, { stream: true });
44
+ try {
45
+ const jsonObjects = partialResponse.split('\n');
46
+ partialResponse = jsonObjects.pop(); // Keep the last partial object
47
+ for (const jsonObjStr of jsonObjects) {
48
+ if (jsonObjStr) {
49
+ const jsonObj = JSON.parse(jsonObjStr);
50
+ if (jsonObj.response) {
51
+ appendToLastMessage(jsonObj.response);
52
+ }
53
+ }
54
+ }
55
+ } catch (e) {
56
+ // JSON parsing error, wait for more chunks
57
+ }
58
+ read();
59
+ });
60
+ }
61
+ read();
62
  })
63
  .catch(error => {
64
  console.error('Error:', error);
65
+ const lastMessage = messageList.lastChild;
66
+ if (lastMessage && lastMessage.classList.contains('bot-message')) {
67
+ lastMessage.textContent = 'Sorry, something went wrong.';
68
+ }
69
  });
70
  }
71
 
 
76
  messageList.appendChild(li);
77
  messageList.scrollTop = messageList.scrollHeight;
78
  }
79
+
80
+ function appendToLastMessage(text) {
81
+ const lastMessage = messageList.lastChild;
82
+ if (lastMessage && lastMessage.classList.contains('bot-message')) {
83
+ lastMessage.textContent += text;
84
+ messageList.scrollTop = messageList.scrollHeight;
85
+ }
86
+ }