Triển Khai Lưu Trữ Lịch Sử Hội Thoại Bền Vững Với SQLite Cho Qwen3-4B Instruct

Khi triển khai mô hình Qwen3-4B Instruct, dữ liệu hội thoại thường bị mất sau khi đóng trình duyệt hoặc khởi động lại dịch vụ. Giải pháp này sử dụng SQLite để lưu trữ lịch sử hội thoại một cách bền vững, đảm bảo dữ liệu có thể truy xuất lại sau khi restart.

Trước khi bắt đầu, hãy đảm bảo môi trường đã được cấu hình đúng. Mô hình Qwen3-4B Instruct cần được triển khai và chạy thành công. Các thư viện cần thiết bao gồm Streamlit và SQLite. Trong terminal, chạy lệnh sau để kiểm tra:

pip install streamlit transformers accelerate torch

SQLite đã được tích hợp sẵn trong Python, không cần cài đặt thêm.

Phần chính của giải pháp là tạo một lớp quản lý cơ sở dữ liệu. Dưới đây là ví dụ về cấu trúc bảng và phương thức:

import sqlite3
import json
from typing import List, Dict, Optional

class DataPersistence:
    def __init__(self, db_path: str = "chat_storage.db"):
        self.db_path = db_path
        self._setup_tables()
    
    def _setup_tables(self):
        connection = sqlite3.connect(self.db_path)
        cursor = connection.cursor()
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS session_records (
                record_id INTEGER PRIMARY KEY AUTOINCREMENT,
                session_key TEXT NOT NULL,
                speaker_role TEXT NOT NULL,
                message_content TEXT NOT NULL,
                event_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                context_data TEXT
            )
        ''')
        cursor.execute('CREATE INDEX IF NOT EXISTS idx_session_key ON session_records(session_key)')
        cursor.execute('CREATE INDEX IF NOT EXISTS idx_event_time ON session_records(event_time)')
        connection.commit()
        connection.close()
    
    def log_entry(self, session_id: str, role: str, text: str, extra: Optional[Dict] = None):
        connection = sqlite3.connect(self.db_path)
        cursor = connection.cursor()
        context_json = json.dumps(extra) if extra else None
        cursor.execute('''
            INSERT INTO session_records (session_key, speaker_role, message_content, context_data)
            VALUES (?, ?, ?, ?)
        ''', (session_id, role, text, context_json))
        connection.commit()
        connection.close()
    
    def retrieve_session(self, session_id: str, max_items: Optional[int] = None) -> List[Dict]:
        connection = sqlite3.connect(self.db_path)
        connection.row_factory = sqlite3.Row
        cursor = connection.cursor()
        query = '''
            SELECT speaker_role, message_content, event_time, context_data
            FROM session_records
            WHERE session_key = ?
            ORDER BY event_time ASC
        '''
        params = [session_id]
        if max_items:
            query += ' LIMIT ?'
            params.append(max_items)
        cursor.execute(query, params)
        history = []
        for row in cursor.fetchall():
            item = {
                'role': row['speaker_role'],
                'text': row['message_content'],
                'timestamp': row['event_time']
            }
            if row['context_data']:
                item['metadata'] = json.loads(row['context_data'])
            history.append(item)
        connection.close()
        return history
    
    def clear_session(self, session_id: str) -> int:
        connection = sqlite3.connect(self.db_path)
        cursor = connection.cursor()
        cursor.execute('DELETE FROM session_records WHERE session_key = ?', (session_id,))
        count = cursor.rowcount
        connection.commit()
        connection.close()
        return count
    
    def list_all_sessions(self) -> List[str]:
        connection = sqlite3.connect(self.db_path)
        cursor = connection.cursor()
        cursor.execute('SELECT DISTINCT session_key FROM session_records ORDER BY MIN(event_time) DESC')
        sessions = [row[0] for row in cursor.fetchall()]
        connection.close()
        return sessions

Trong ứng dụng Streamlit chính (app.py), cần tích hợp lớp này:

import streamlit as st
from transformers import AutoModelForCausalLM, AutoTokenizer
from persistence import DataPersistence

storage = DataPersistence()
CURRENT_SESSION = "main_session"

if "chat_history" not in st.session_state:
    st.session_state.chat_history = storage.retrieve_session(CURRENT_SESSION) or []

if user_input := st.chat_input("Nhập câu hỏi..."):
    st.session_state.chat_history.append({"role": "user", "text": user_input})
    storage.log_entry(CURRENT_SESSION, "user", user_input, {"source": "web"})
    
    with st.chat_message("assistant"):
        # ... code xử lý AI response ...
        ai_response = "Kết quả trả về"
    st.session_state.chat_history.append({"role": "assistant", "text": ai_response})
    storage.log_entry(CURRENT_SESSION, "assistant", ai_response, {"model": "Qwen3-4B-Instruct-2507"})

with st.sidebar:
    if st.button("Xóa dữ liệu hiện tại"):
        st.session_state.chat_history = []
        deleted = storage.clear_session(CURRENT_SESSION)
        st.success(f"Đã xóa {deleted} bản ghi từ cơ sở dữ liệu")
        st.rerun()
    
    if st.button("Xem danh sách hội thoại"):
        sessions = storage.list_all_sessions()
        if sessions:
            st.write("Các phiên làm việc hiện có:")
            for sid in sessions:
                records = storage.retrieve_session(sid)
                st.write(f"- `{sid}`: {len(records)} bản ghi")
        else:
            st.info("Không có dữ liệu nào trong cơ sở dữ liệu")

Để kiểm tra, khởi động lại ứng dụng, thực hiện một số cuộc hội thoại, đóng trình duyệt và mở lại. Dữ liệu sẽ được khôi phục từ SQLite. Sử dụng nút "Xóa dữ liệu hiện tại" để xóa dữ liệu khỏi cả bộ nhớ và cơ sở dữ liệu.

Chức năngTrước khi tích hợpSau khi tích hợp
Lưu trữ lịch sửChỉ tồn tại trong bộ nhớ trình duyệtLưu trữ bền vững trong SQLite
Khôi phục sau restartKhông thểCó thể
Quản lý dữ liệuKhông hỗ trợHỗ trợ xóa và xem danh sách hội thoại

Các cải tiến có thể thực hiện bao gồm: hỗ trợ nhiều hội thoại đồng thời, giao diện tìm kiếm lịch sử, xuất dữ liệu sang định dạng khác, hoặc tích hợp với cơ sở dữ liệu lớn hơn như PostgreSQL.

Thẻ: SQLite streamlit qwen data-persistence python

Đăng vào ngày 29 tháng 6 lúc 22:46