本帖最后由 kylinpoet 于 2024-4-15 19:00 编辑
一、前言
各位大佬的评测文章陆续上传,屏幕显示、传感器、执行件等陆续上阵,满目琳琅,但好像没有看到声音处理的相关帖子(或者是我没发现?)本来想接个麦克风,用API搞个网络语音识别。但翻遍家里仓库,没有找到可用设备,只好作罢。还是按照原思路,把esp32和现在流行的AIGC做个联结。
笔者在 前文 最后的内容中提到的ESP32 Web Server,就是为本文准备的。
二、AIGC平台和智谱清言
现在市面上的AIGC平台很多,有开源也有商用的。由清华智谱研发的 ChatGLM 效果是较理性的。正好这几天在本地搭建了白嫖glm4的API服务,正好拿来试手,当然大家有兴趣也可以使用 ChatGLM智谱清言 的网络端进行试用(选择glm4效果更佳,可绘图)。
确定好平台后,就可以使用现成的工具来生成板子的python代码了,我们可以看到,生成的代码逻辑比较准确,基本上可以无损使用:
配置好,相关参数,就可以愉快玩耍了。
在thonny选择主板执行,访问打印的IP地址:
当然,怎么能只有文字呢,要图片也是可以可以顺手捏来的。
三、几个坑点
1. 万恶的Python 2过去了,以为在Python 3里不会有编码问题了,很不幸,因为在mpy里用socket创建Web服务的时候,是用字节字符串进行数据传输的,因此在处理 html 的 form post 传过来的数据时,需要进行编码处理:
当然这个函数,是用GLM4 在线生成的,毕竟mpy 自带的 url 处理函数还不是很完整:
2. 在进行数据post时,要进行data的字节化处理,这里被耽搁了下,主要是要使用:data.encode()这个方法。
3. 当然,还有生成图片时,返回数据的解析处理等,必须使用AIGC来完成,使用起来相当丝滑:
四、完整代码
- import socket
- import urequests
- import json
-
- # WiFi设置
- SSID = 'ssid'
- PASSWORD = 'pass'
-
- # OpenAI API设置
- API_URL = 'http://*.*.*.*:8000/v1/chat/completions'
- API_KEY = 'eyJhbG......'
-
- def connect_wifi(ssid, password):
- import network
- sta_if = network.WLAN(network.STA_IF)
- if not sta_if.isconnected():
- print('Connecting to WiFi...')
- sta_if.active(True)
- sta_if.connect(ssid, password)
- while not sta_if.isconnected():
- pass
- print('WiFi connected')
- print('ip:{}'.format(sta_if.ifconfig()[0]))
-
-
- def decode_html_entities(encoded_str):
- import re
- # 正则表达式用于找到形式为 %26%23<数字>%3B 的编码实体
- pattern = re.compile(r'%26%23(\d+)%3B')
- # 函数用于替换每个匹配的实体
- def replace_entity(match):
- # 提取数字部分,并转换为整数
- code_point = int(match.group(1))
- # 将整数转换为对应的Unicode字符
- return chr(code_point)
- # 使用正则表达式的sub方法替换所有匹配的实体
- return pattern.sub(replace_entity, encoded_str)
-
-
- def start_server():
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.bind(('', 80))
- s.listen(5)
- while True:
- conn, addr = s.accept()
- request = str(conn.recv(1024))
- print(request)
-
- # 检查是否是POST请求
- if 'POST /' in request:
- # 解析用户输入
- # request = request.decode()
- start_index = request.find('prompt=') + len('prompt=')
- input_text = request[start_index:-1].replace('%20', ' ')
- input_text = decode_html_entities(input_text)
- print(input_text)
- # 使用OpenAI API获取结果
- response = use_openai_api(input_text)
-
- # 发送HTTP响应
- conn.send('HTTP/1.1 200 OK\n')
- conn.send('Content-Type: text/html\n')
- conn.send('Connection: close\n\n')
- conn.sendall(html_page(response))
- else:
- # 发送HTML表单
- conn.send('HTTP/1.1 200 OK\n')
- conn.send('Content-Type: text/html\n')
- conn.send('Connection: close\n\n')
- conn.sendall(html_page(None))
-
- conn.close()
-
- def use_openai_api(prompt):
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': 'Bearer ' + API_KEY
- }
- data = json.dumps(
- {
- "model": "glm4",
- "messages": [{
- "role": "user",
- "content": prompt}],
- "stream": False}
- )
- # try:
- print(data)
- response = urequests.post(API_URL, headers=headers, data=data.encode())
- response = response.json()
- print(response)
- return response['choices'][0]['message']['content']
- # except Exception as e:
- # print(str(e))
-
- def extract_image_url(text):
- # 使用正则表达式匹配图片链接
- import re
- image_url_match = re.search(r'!\[.*?\]\((https://.*?\.(png|jpg|jpeg|gif))\)', text)
- if image_url_match:
- return image_url_match.group(1)
- return None
-
- def html_page(result):
- # image_url = extract_image_url(result)
- if result:
- image_url = extract_image_url(result)
- if image_url:
- response_html = f"<p><img src='{image_url}' alt='OpenAI Response' width='500px'></br >{result}</p>"
- else:
- response_html = f"<p>{result}</p>"
- else:
- response_html = ""
- return f"""
- <html>
- <head>
- <meta charset="UTF-8">
- </head>
- <body>
- <h2>OpenAI Input:</h2>
- <form action="/" method="post">
- <textarea style="width: 500px; height: 100px;" name="prompt" rows="4" cols="50"></textarea>
- <br>
- <input type="submit" value="Submit">
- </form>
- <h2>OpenAI Response:</h2>
- {response_html}
- </body>
- </html>
- """
-
-
- # 连接到WiFi
- connect_wifi(SSID, PASSWORD)
-
- # 启动服务器
- start_server()
-
-
复制代码
以上!
|