【前言】
搭建好本地deepseek服务器后,可以使用http post到服务器,获取反馈数据。从服务器返回的是一块一块的数据,比如如下:
在STM32F769处理这些数据时,有时会由于返回数据太大,导致缓冲区溢出。所以需要在本地再搭建一个转发服务,我们只需要提出有用的信息转发给客户端即可。
【实现步聚】
1、首先引入需要的模块:
import http.server import socketserver import http.client import json import re
2、定义好host 端口为11434 模型名称
OLLAMA_HOST = 'localhost' OLLAMA_PORT = 11434 MODEL_NAME = "deepseek-r1:1.5b"
3、编写转发服务
在POST路由中,首先获取客户端转发过来的post_data,然后再把model添加进post_data中,再组装进行转发给ollama服务器
def do_POST(self): content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length) try: request_json = json.loads(post_data) request_json["model"] = MODEL_NAME modified_post_data = json.dumps(request_json).encode('utf-8') # 只保留必要的请求头 necessary_headers = { 'Content-Type': 'application/json', 'Content-Length': str(len(modified_post_data)) } conn = http.client.HTTPConnection(OLLAMA_HOST, OLLAMA_PORT) print(f"Forwarding request: {self.path}, {necessary_headers}, {modified_post_data}") conn.request('POST', self.path, modified_post_data, necessary_headers) response = conn.getresponse()
4、在拿到ollama返回的装诚码和头信息时,把他返回请求客户端:
# 打印响应状态码和头信息 print(f"Response status: {response.status}") print(f"Response headers: {response.getheaders()}") self.send_response(response.status)
5、由于服务器返回的是分块编码,我把他去掉掉:
# 去掉分块传输编码头 headers_to_send = [ (header, value) for header, value in response.getheaders() if header.lower() != 'transfer-encoding' ] for header, value in headers_to_send: self.send_header(header, value)
6、接着把非需要的字符去掉,比如think标签,以及其他不需要的数据,只保留response的内容,并重新拼接:
# 收集所有 response 字段的内容 response_content = "" while True: line = response.readline() if not line: break try: json_obj = json.loads(line) print(f"Parsed JSON: {json_obj}") # 去除 <think> 和 </think> 标签 response_text = json_obj.get('response', "") response_text = re.sub(r'<think>|</think>', '', response_text) # 将 \n 或 \n\n 替换为 \r\n response_text = re.sub(r'\n+', '\r\n', response_text) response_content += response_text except json.JSONDecodeError: print(f"Invalid JSON line: {line.decode('utf-8').strip()}") continue # 忽略非 JSON 行,继续处理后续数据
7、重新计算返回内容的长度,并发送回客户端:
# 计算内容长度 response_content_bytes = response_content.encode('utf-8') content_length = len(response_content_bytes) self.send_header('Content-Length', str(content_length)) self.end_headers() # 一次性发送 response 内容给客户端 self.wfile.write(response_content_bytes) conn.close()
8、最后定义端口为8000,开启服务器转发:
PORT = 8000 with socketserver.TCPServer(("", PORT), OllamaProxyHandler) as httpd: print(f"Serving at port {PORT}") httpd.serve_forever()
【编写测试代码】
import requests import json LOCAL_SERVER_HOST = 'localhost' LOCAL_SERVER_PORT = 8000 url = f'http://{LOCAL_SERVER_HOST}:{LOCAL_SERVER_PORT}/api/generate' data = { "prompt": "你好" } json_data = json.dumps(data).encode('utf-8') headers = { 'Content-Type': 'application/json' } try: response = requests.post(url, data=json_data, headers=headers) if response.status_code == 200: print("Response from server:") print(response.text) else: print(f"Request failed with status code {response.status_code}: {response.text}") except requests.RequestException as e: print(f"An error occurred while making the request: {e}")
执行后,我们回收到的内容就简单许多了:
【总结】
在直接与ollama服务器进行请求时,会返回许多信息,我只关心需要的字段,经过如此处理后,在单片机中处理就简单许多了。
附代码: