搜尋結果

×

利用LLM、Flask、LangChain實作聊天機器人chat bot網站

利用 Ollama LLM 和 Flask,結合 LangChain 架構,打造一個響應式的聊天機器人網站,實現即時對話功能。

我們將介紹如何使用Ollama LLM結合Flask來構建一個聊天機器人chat bot網站。本教學將會使用Llama3作為我們的LLM,並且採用LangChain, , JavaScript, Jinja2和Tailwind CSS框架,確保你在任何設備上都能獲得最佳的響應式設計(RWD)體驗。

會用到的資料集為 GitHub Repository - llama flask langchain ChatbotWeb

技術介紹

  • Ollama LLM:提供強大的自然語言處理能力。
  • Flask:輕量級的 Python 網頁框架,適合快速開發應用。
  • LangChain:用於構建和操作語言模型應用的框架。
  • Tailwind CSS:實現高度可定制和響應式設計的 CSS 框架。
  • Jinja2:在 Flask 中預設的模板引擎,用於渲染 HTML 模板。
  • Server-Sent Events:一種 Web 技術,用於從伺服器向客戶端推送即f時數據。

此文章也有發表在Medium上 >>

網站功能概覽

主頁

在主頁上,你可以看到一個我設計的漂亮Logo,因為我們使用的是Llama3作為LLM,所以在Logo中間放置了一隻可愛的羊駝。

導航欄

你可以通過導航欄連接到我的所有資源連結,包括LinkedIn - WeibersonMedium - WeibersonGitHub - weitsung50110

輸入區域

這裡是你與Llama3對話的地方。你可以問它各種問題,例如:

  • 你是誰?

  • 你愛我嗎?

Loading字樣

即時時間

使用Docker設置環境

1:下載 Docker 映像

首先,下載我們已經配置好的 Docker 映像:

docker pull weitsung50110/ollama_flask

2:運行Image以生成容器

將主機的~/trans_project目錄掛載到容器內的/app資料夾下:

docker run -d \
-v ollama:/root/.ollama \
-v ~/trans_project:/app \
-p 5066:5000 \
-p 11466:11434 \
--name ollama_flask \
weitsung50110/ollama_flask:1.0

端口映射講解

  • -p 5066:5000:將主機的5066端口映射到容器內部的5000端口,用於Flask。
  • -p 11466:11434:將主機的11466端口映射到容器內部的11434端口,用於Ollama。

3:進入容器

進入剛剛創建的ollama_flask容器:

docker exec -it ollama_flask /bin/bash

4:啟動Llama3

進入容器後,先運行以下指令啟動Llama3:

ollama run llama3

這一步確保Llama3已經安裝並運行,否則Flask將無法打開。

5:啟動Flask應用

進入/app目錄:

cd app/

運行Flask應用:

python3 app.py

確保指定了port,這樣你才能通過127.0.0.1:xxxx訪問Flask應用:

docker run -d -v ollama:/root/.ollama -v ~/trans_project:/app -p 5066:5000 -p 11466:11434 --name ollama_flask weitsung50110/ollama_flask:1.0

6:確認成功運行

如果一切順利,你應該會看到如下輸出:

Running on http://127.0.0.1:5000

根據你在docker run時指定的port來訪問應用,例如:

  • 如果port指定為5066:5000,則訪問127.0.0.1:5066

重點程式講解

Server

你在資料集中的app.py,也就是server看到render_template代表要渲染網頁了,這時我有把一些傳到index.html網頁當中。

return render_template('index.html', query_input=query_input, output=output)
  • query_input : 使用者詢問LLM所輸入的問題
  • output : LLM的回應

Web

Jinja2 提供了一些強大的模板語法,讓我們可以在 HTML 文件中使用 Python 風格的控制結構。

可以看到我在html藉由jinja2使用條件判斷。

<div class="mt-6">
    {% if query_input %}
        

{{ query_input }}

{% endif %} {% if output %}

{{ output }}

{% endif %} </div>

接下來我們將探討 Jinja2 模板語法中的控制結構,特別是條件判斷和迴圈語法,我舉幾個簡單的例子給大家,。

Jinja2 模板語法

Jinja2 提供了一些強大的模板語法,讓我們可以在 HTML 文件中使用 Python 風格的控制結構。以下是一些常用的控制結構:

  1. 條件判斷 if
    1
    {% if %}
  • 條件判斷允許我們根據變數的值來決定是否渲染某些內容。
    1
    2
    3
    4
    5
    6
    7
    {% if condition %}
    <!-- 當條件為真時渲染這段內容 -->
    {% elif other_condition %}
    <!-- 當另一個條件為真時渲染這段內容 -->
    {% else %}
    <!-- 當所有條件都不成立時渲染這段內容 -->
    {% endif %}
  1. 迴圈 for
    1
    {% for %}
  • 迴圈允許我們遍歷列表或其他可迭代對象,並渲染每個元素。
    1
    2
    3
    4
    5
    6
    7
    {% for item in items %}
    <!-- 渲染每個 item 的內容 -->
    {% endfor %}
    ```
    3. 範圍迴圈 `for i in range`
    ```jinja
    {% for i in range(start, end) %}
  • 我們也可以使用範圍迴圈來遍歷一個數字範圍:
    1
    2
    3
    {% for i in range(1, 11) %}
    <p>數字:{{ i }}</p>
    {% endfor %}

在 Jinja2 模板語法中,所有的控制結構(如條件判斷和迴圈)都必須以相應的 {% end %} 語句來結束。這是為了明確定義控制結構的範圍,避免代碼混淆。

我們可以看到,if 條件判斷用 {% endif %} 結束,for 迴圈用 {% endfor %} 結束。這些結束標記是必不可少的,否則模板引擎會無法正確解析模板,並且會拋出錯誤。

Server-Sent Events (SSE)

是一種 Web 技術,用於從伺服器向客戶端推送即時數據

生成器函數 generate() 詳解:

def generate():
    while True:
        current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')  # 取得當前時間並格式化
        data = f"data: {current_time}\n\n"  # 根據SSE格式要求構建數據字符串
        yield data  # 通過生成器返回數據給調用者(客戶端)
        time.sleep(1)  # 每秒推送一次數據
  • generate() 函數使用了一個無窮循環 (while True),每次循環都取得當前時間 (datetime.now()),並將其格式化為 %Y-%m-%d %H:%M:%S 的字串形式。

  • 使用 f-string 將格式化後的時間插入到 data 字串中,並按照 SSE 的規範構建數據。

  • 通過 yield 返回 data 給調用者(客戶端),使得生成器可以被迭代並逐步返回新的數據。

  • time.sleep(1) 使生成器每秒鐘推送一次數據,實現即時更新效果。

使用 \n\n 來結束事件

在 Server-Sent Events (SSE,伺服器推送事件) 中,事件的數據部分使用 \n\n 來標記每個事件的結束。

  • 第一個 \n 表示數據的結束。
  • 第二個 \n 表示兩個事件之間的分隔。

在 SSE 中,每個事件的數據應當以 data: ... 開頭,然後使用 \n\n 來結束這個事件。

data: 2024-06-13 15:30:00\n\n

SSE 路由 (/stream) 的設置:

在 Flask 應用中設置 /stream 路由,當客戶端訪問該路由時,會返回一個 Response 對象,其內容由 generate() 函數生成,並設置 mimetype='text/event-stream' 以指定這是一個 SSE 流。

@app.route('/stream')
def stream():
    return Response(generate(), mimetype='text/event-stream')

當客戶端通過訪問 /stream 路由來訂閱事件流時,伺服器會每秒鐘推送一次當前時間,並由客戶端進行處理和顯示。這樣的應用場景包括即時股票價格更新、即時聊天消息等需要即時更新的應用。

mimetype='text/event-stream' 是在使用 Server-Sent Events (SSE,伺服器推送事件) 時用來指定 HTTP 響應的內容類型(Content-Type)。

  • text/event-stream 是一種特殊的 MIME 類型,它指示了服務器將通過此響應傳送一系列事件給客戶端。這些事件是使用 SSE 標準格式傳送的,每個事件以 data: 開頭,並以兩個連續的新行 \n\n 結束。

  • Content-Type 是 HTTP 標頭的一部分,用來描述 HTTP 響應的內容類型。在這種情況下,mimetype='text/event-stream' 告訴瀏覽器或客戶端,這個響應包含了 SSE 格式的數據流,它應該按照 SSE 的規範來處理和解析這些數據。

使用 mimetype='text/event-stream' 是確保伺服器正確地傳送 SSE 數據流到客戶端的關鍵。

JavaScript 說明:

JavaScript 代碼中,使用了 EventSource 對象來實現 Server-Sent Events (SSE,伺服器推送事件) 的客戶端訂閱和接收。

<script>
    const eventSource = new EventSource('/stream');
            
    eventSource.onmessage = function(event) {
        document.getElementById('datetime').innerHTML = event.data;
    };
</script>
  1. const eventSource = new EventSource(‘/stream’);
  • EventSource 是 HTML5 中引入的一種 API,它允許網頁從服務器端接收推送的事件。

  • new EventSource('/stream') 創建了一個新的 EventSource 對象,並指定了要訂閱的服務器端端點 /stream。這意味著客戶端將會向 /stream 發起 HTTP GET 請求來訂閱事件流。

  1. eventSource.onmessage = function(event) { … };
  • 一旦客戶端訂閱成功,當服務器端向 /stream 發送一條新的事件消息時,JavaScript 會自動觸發 onmessage 事件處理器函數。

  • event 參數包含了從服務器端發送來的事件消息的相關信息,包括數據內容。

  1. document.getElementById(‘datetime’).innerHTML = event.data;
  • onmessage 事件處理器函數內部,這行代碼將服務器端發送來的數據 event.data 更新到 HTML 文檔中具有 id="datetime" 的元素內。

  • 通常情況下,event.data 是一段文本數據,它包含了服務器端發送的即時信息,例如時間戳、消息內容等。

工作流程

  1. 頁面加載
    當頁面加載時,JavaScript 代碼會創建一個 EventSource 對象,並發起對 /stream 的 HTTP GET 請求。

  2. 服務器端推送事件
    一旦服務器端有新的事件消息到來,它會將該消息推送到所有訂閱了 /stream 的客戶端(即這裡的網頁)。

  3. 更新 HTML 元素
    客戶端接收到來自服務器端的事件消息後,透過 onmessage 事件處理器函數將消息內容更新到 HTML 中的指定元素(這裡是 id="datetime" 的元素)。

這樣就實現了一個基本的 SSE 客戶端,用於接收服務器端推送的事件消息並即時更新到網頁上。

結語

通過這篇教學文章,我們學習了如何使用Ollama NLP LLM結合Flask來構建智能對話機器人網站。希望你能成功搭建並享受與Llama3的互動過程!

未來會把記憶性的聊天機器人, RAG取得PDF和DOC, 等等的應用結合到Flask的Web介面中,敬請期待!!🥰

LangChain RAG 打造個人化 LLaMA3 Flask Chatbot 網站

    喜歡 Weiberson 的文章嗎?在這裡留下你的評論!本留言區支援 Markdown 語法