我现在的chat_server.pu是这样的# chat_server.py import os from flask import Flask, request, jsonify, render_template import subprocess app = Flask(__name__, template_folder="templates") @app.route("/") def index(): return render_template("index.html") @app.route("/chat", methods=["POST"]) def chat(): user_input = request.json.get("message") model_path = os.path.join("models", "DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf") # 调用 main.exe 推理 process = subprocess.Popen( ["main.exe", "-m", model_path, "-p", user_input, "-n", "256"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True, encoding='utf-8' ) output, _ = process.communicate() return jsonify({"response": output.strip()}) if __name__ == "__main__": app.run(host="127.0.0.1", port=5000) 在哪里添加你的多轮对话 上下文支持 ?或者你结合我现在的内容融合你的内容 在不影响原来内容的的情况重新写一个chat_server.py
时间: 2025-07-19 11:27:24 浏览: 11
<think>我们现有的chat_server.py只支持单轮对话,现在要添加多轮对话上下文支持。我们需要做以下改动:
1. 在服务器端维护一个对话历史记录(使用字典,以session_id为键,每个会话的对话历史列表为值)
2. 每次请求时,将历史对话拼接成上下文,然后加上当前问题,发送给模型
3. 前端需要发送一个session_id来标识当前会话(如果没有,则使用默认会话或创建新会话)
4. 为了支持多轮对话,我们需要调整调用main.exe的方式,因为main.exe可能不支持直接传入多轮历史。因此,我们需要在调用之前将历史对话拼接成一个字符串。
注意:由于我们使用的是main.exe(可能是llama.cpp的示例程序),它接受一个-p参数作为提示。我们可以将历史对话拼接成一个字符串,作为提示传入。
但是,需要注意的是,模型本身有最大上下文长度限制(比如4096个token),所以我们需要限制历史对话的轮数或总token数。
修改计划:
1. 在服务器端,我们将为每个会话保存一个对话历史列表(包括用户和助手的对话)。
2. 当收到请求时,我们将从请求中获取session_id(如果没有,则生成一个新的,或者使用默认的"default")。
3. 将当前用户的问题添加到该会话的历史中(先不添加助手的回复,因为还未生成)。
4. 然后,我们将整个对话历史(包括当前问题)拼接成适合模型的格式(例如:User: ...\nAssistant: ...\nUser: ...)。
5. 调用main.exe,传入拼接后的整个提示。
6. 获取模型的输出,将模型的输出添加到该会话的历史中(作为当前问题的回答)。
7. 返回响应,同时可以将会话ID返回给前端(如果是新会话)。
同时,为了避免历史对话过长,我们可以限制保存的历史轮数(比如最近5轮)或者根据token数截断。
由于我们无法直接知道token数量(除非调用tokenizer),这里我们简单使用轮数限制。
另外,我们还需要考虑新建会话的端点,以便前端可以开始一个新的对话。
修改后的chat_server.py代码:</think>我将基于你现有的 `chat_server.py` 文件,集成多轮对话上下文支持功能,同时保持原有功能不变。以下是完整的实现方案:
```python
# chat_server.py
import os
import json
import threading
from datetime import datetime
from flask import Flask, request, jsonify, render_template
import subprocess
app = Flask(__name__, template_folder="templates")
# 全局变量存储对话历史(线程安全)
conversation_lock = threading.Lock()
conversation_history = {}
def get_session_history(session_id):
"""获取或创建会话历史"""
with conversation_lock:
if session_id not in conversation_history:
conversation_history[session_id] = []
return conversation_history[session_id]
def build_prompt(history, new_message):
"""构建包含历史对话的完整提示"""
# 拼接历史对话(最多保留5轮对话)
context = ""
for entry in history[-5:]:
context += f"用户: {entry['user']}\n助手: {entry['assistant']}\n"
# 添加新消息
context += f"用户: {new_message}\n助手:"
return context
@app.route("/")
def index():
return render_template("index.html")
@app.route("/new_session", methods=["POST"])
def new_session():
"""创建新会话端点"""
session_id = f"session_{datetime.now().timestamp()}"
get_session_history(session_id) # 初始化历史记录
return jsonify({"session_id": session_id})
@app.route("/chat", methods=["POST"])
def chat():
"""处理聊天请求"""
# 获取请求数据
user_input = request.json.get("message")
session_id = request.json.get("session_id", "default")
# 获取会话历史
history = get_session_history(session_id)
# 构建包含上下文的提示
full_prompt = build_prompt(history, user_input)
# 调用模型推理
model_path = os.path.join("models", "DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf")
process = subprocess.Popen(
["main.exe", "-m", model_path, "-p", full_prompt, "-n", "256"],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
text=True,
encoding='utf-8'
)
output, _ = process.communicate()
model_response = output.strip()
# 更新对话历史
history.append({
"user": user_input,
"assistant": model_response,
"timestamp": datetime.now().isoformat()
})
return jsonify({
"response": model_response,
"session_id": session_id
})
if __name__ == "__main__":
app.run(host="127.0.0.1", port=5000)
```
### 代码解释:
1. **多线程安全设计**:
- 添加了 `threading.Lock()` 确保在多用户访问时对话历史的线程安全
- `conversation_lock` 控制对全局 `conversation_history` 字典的访问
2. **会话管理功能**:
- `get_session_history()` 函数:获取或创建指定会话的历史记录
- `/new_session` 端点:创建新的会话ID并初始化历史记录
- 每个会话独立存储对话历史,互不干扰
3. **上下文构建**:
- `build_prompt()` 函数:将历史对话拼接成模型可理解的格式
- 保留最近5轮对话作为上下文(可根据需要调整)
- 格式:`用户: {问题}\n助手: {回答}\n用户: {新问题}\n助手:`
4. **历史记录存储**:
- 每个对话条目包含用户输入、模型回复和时间戳
- 数据结构示例:
```json
[
{
"user": "你好",
"assistant": "你好!有什么可以帮您?",
"timestamp": "2024-05-15T10:30:45.123456"
},
{
"user": "Python是什么?",
"assistant": "Python是一种高级编程语言...",
"timestamp": "2024-05-15T10:31:20.789012"
}
]
```
5. **API响应扩展**:
- 返回数据中新增 `session_id` 字段,前端可用此标识会话
- 保持原有 `response` 字段兼容性
### 前端修改方案:
```html
<!-- templates/index.html 修改部分 -->
<script>
// 添加会话管理变量
let currentSession = 'default';
// 新建会话功能
document.getElementById('newSessionBtn').addEventListener('click', () => {
fetch('/new_session', {
method: 'POST'
})
.then(res => res.json())
.then(data => {
currentSession = data.session_id;
document.getElementById('chat').innerHTML = '';
updateSessionList();
});
});
// 更新会话列表显示
function updateSessionList() {
const select = document.getElementById('sessionSelect');
select.innerHTML = `<option value="${currentSession}">当前会话</option>`;
// 实际应用中可添加更多会话管理功能
}
// 修改send函数
function send() {
const input = document.getElementById("input");
const msg = input.value.trim();
if (!msg) return;
appendMessage("你", msg, "user");
// 发送请求时包含会话ID
fetch("/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
message: msg,
session_id: currentSession
})
}).then(res => res.json()).then(data => {
appendMessage("助手", data.response, "bot");
});
input.value = "";
}
// 页面加载时初始化会话
window.onload = () => {
updateSessionList();
};
</script>
```
### 前端界面增强(添加到HTML中):
```html
<!-- 在标题下方添加会话控制栏 -->
<div class="session-control">
<button id="newSessionBtn">新建会话</button>
<select id="sessionSelect"></select>
</div>
<!-- 添加CSS样式 -->
<style>
.session-control {
margin-bottom: 15px;
display: flex;
gap: 10px;
}
.session-control button {
background-color: #27ae60;
}
.session-control select {
padding: 8px;
border-radius: 4px;
border: 1px solid #ddd;
}
</style>
```
### 使用说明:
1. **基本功能**:
- 用户首次访问使用默认会话(session_id = "default")
- 点击"新建会话"按钮创建独立对话环境
- 系统自动维护每个会话的对话历史
2. **上下文工作流程**:
```
用户: 什么是Python?
助手: Python是一种高级编程语言...
用户: 它有什么特点?
(系统构建的完整提示)
用户: 什么是Python?
助手: Python是一种高级编程语言...
用户: 它有什么特点?
助手:
```
3. **扩展性考虑**:
- 可添加会话切换功能
- 可增加历史对话持久化存储
- 可添加上下文长度控制参数
这个实现方案完全兼容你现有的代码结构,添加了多轮对话支持,同时保持了API的向后兼容性。前端用户可以通过"新建会话"按钮创建独立的对话环境,每个环境都有独立的上下文记忆。
阅读全文
相关推荐
















