ESP32开发板在micropython里直接用requests向web服务器发送请求:ESP32S3开发板通过fastapi中转成功连接星河大模型

devtools/2024/11/30 20:44:15/

在micropython里用requests连web服务器

本来想在ESP32开发板里直接连百度星河大模型,但是一直有报错,没调通,于是转而用fastapi进行中转,也就是先用ESP32连fastapi的中转服务器,该中转服务器再去连百度星河大模型。

WEB服务器是自己用fastapi启动的,地址:http://192.168.0.99:8000/login/

这台WE服务器测试了很久,其WEB服务代码也修改了多次,最终代码没有login部分,而是openai模型接入的链接:"/v1/chat/completions/" ,中间测试代码就不提供了,最终WEB服务器代码见后面。 

测试requests

这里一开始不懂,所以直接把字典当数据使用data参数传给web服务器,引起后面的报错:

import requests
data ={"model": "ernie-speed-8k","username": "testusername","password": "passtestusername"}
response = requests.post('http://192.168.0.99:8000/login/',headers = {'accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded', },data = data
)
print(response.status_code)

Traceback (most recent call last):
  File "<stdin>", line 5, in <module>
  File "requests/__init__.py", line 205, in post
  File "requests/__init__.py", line 144, in request
TypeError: object with buffer protocol required
有报错,看来直接用requests有点问题,需要再看看文档。

错误提示表明requests.post方法在尝试发送数据时遇到了问题。在标准的requests库中,这通常是因为传递给datajson参数的对象不是字符串、字节序列或类似的可缓冲对象。

因为看到报错里有“buffer”字样,刚开始还以为是板子出了问题,中间还换了开发板,从ESP32C3换成ESP32S3。现在回过头来看,应该是传输的数据有问题,data后面应该跟的是字符串(后来知道是application/x-www-form-urlencoded类型),json参数后面才带json数据。 

看micropython的文档

里面讲了urequests.request

urequests.request(functionurldata=Nonejson=Nonefiles=Noneheaders={}auth=None

服务器发送 HTTP 请求。

  • function - 要使用的 HTTP 方法

  • url - 要发送的 URL

  • data - 要附加到请求主体的数据。如果提供了字典或元组列表,则将对其进行编码。

  • json - 用于附加到请求主体的 json 数据。

  • files - 用于文件上传,类型为 2 元组,定义了文件名、文件路径和内容类型。如下,{‘name’,(文件路径,内容类型)}

  • headers - 要发送的标头字典。

  • auth - 启用 Basic/Digest/自定义 HTTP Auth 的 Auth 元组。

学着用urequests.request(functionurldata=data) 发送数据,结果还是报错:

用这段测试:

python">cat tp1.py 
import requests
data ={"model": "ernie-speed-8k","username": "testusername","password": "passtestusername"}
response = requests.post('http://192.168.0.99:8000/login/',headers = {'accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded', },data = data
)
print(response.status_code)

服务器端用这个:

cat testpost.py 
from fastapi import FastAPI, Formapp = FastAPI()@app.post("/login/")
async def login(username: str = Form(), password: str = Form()):
#    print(username, model)print(username, )return {"username": username}
(py311) skywalk@rbpi:~/work/fastapi $ uvicorn testpost:app --reload --host 0.0.0.0
INFO:     Will watch for changes in these directories: ['/home/skywalk/work/fastapi']
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [1617] using WatchFiles
INFO:     Started server process [1619]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

pc机测试通过:

python">python3 tp1.py 
200

micropython报buff有问题

再次测试micropython下request

python">import requests as urequests
# import urequestsdef sendGetRequest(url):try:response = urequests.get(url)print("Response Status Code:", response.status_code)print("Response Text:", response.text)response.close()except Exception as e:print("An error occurred:", e)# Main function
def main():ssid = 'your_wifi_name'password = 'your_wifi_password'# connectWiFi(ssid, password)url = 'http://192.168.0.99:8000/login/'sendGetRequest(url)if __name__ == "__main__" :main()

这次连上了:

main()
Response Status Code: 422
Response Text: {"detail":[{"type":"missing","loc":["body","username"],"msg":"Field required"
,"input":null},{"type":"missing","loc":["body","password"],"msg":"Field required","input":nu
ll}]}
 

尽管有报错422,但证明报文送到了服务器服务器返回了信息。

尝试解决422报错问题

查找422故障原因:422状态码是属于客户端错误的一种,表示服务器能够理解请求,但是请求格式正确,却无法处理

最终经过艰苦卓绝的战斗,成功解决了422报错问题,原来是json格式不对,需要把数据用json格式化好才行,解决问题过程见:走进科学json版:在 JSON 格式中,字符串值必须使用双引号 “ 来界定,而不能使用单引号 ‘-CSDN博客

最终测试成功!下面为成功后的代码和配置:

在树莓派里启动fastapi服务

启动服务

服务器app.py文件放置在~/work/fastapiagent目录,进入该目录,然后使用uvicorn启动服务:

uvicorn app:app --host 0.0.0.0 --reload

服务器代码,app.py文件内容:

python">cat app.py 
from typing import Annotated
import json
from fastapi import FastAPI, Path, Query
from pydantic import BaseModel
from openai import OpenAIimport os
import time
from typing import Union, Optionalapp = FastAPI()
API_KEY = "xxxx"
model="ernie-speed-8k"class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Noneclass ChatItem(BaseModel):messages: listmodel: str | None = Nonedef ChatCompletions(messages: list,model: str,# provider: Optional[ProviderType] = None,stream: Optional[bool] = False,# proxy: Optional[str] = None,response_format: Optional[dict] = None,max_tokens: Optional[int] = None,stop: Optional[Union[list[str], str]] = None,api_key: Optional[str] = None,# ignored: Optional[list[str]] = None,# ignore_working: Optional[bool] = False,ignore_stream: Optional[bool] = False,**kwargs):client = OpenAI(api_key=api_key,  # 含有 AI Studio 访问令牌的环境变量,https://aistudio.baidu.com/account/accessToken,base_url="https://aistudio.baidu.com/llm/lmapi/v3",  # aistudio 大模型 api 服务域名
)chat_completion = client.chat.completions.create(messages=messages,model=model,
)print(f"==log for app chat_completion:{chat_completion} ")# response = chat_completion.result# print(f"==log for app  response:{response}")return chat_completion@app.get("/items/{item_id}")
async def read_items(item_id: Annotated[int, Path(title="The ID of the item to get")],q: Annotated[str | None, Query(alias="item-query")] = None,
):results = {"item_id": item_id}if q:results.update({"q": q})return results@app.post("/v1/chat/completions/")
async def chat_completions(chatitem: ChatItem):print(chatitem)chatitemdict = chatitem.dict()print(f"==== items:{chatitemdict}")#print ("=" * 20 , messages, type(messages))#yjson = json.loads(messages)#print("="*10, yjson, type(yjson))#zmessages = yjson["messages"]#print("="*10, zmessages, typr(zmessages))model="ernie-speed-8k"messages = chatitem.messagesprint(f"==== messages=chatitem.msg:{messages}")y = ChatCompletions(messages=messages, model=model, api_key=API_KEY)print("="*10, y)z = y.choices[0].message.contentreturn z@app.post("/items/")
async def create_item(item: Item):print(f"==== get the Item type:{type(item)}, item:{item}")item_dict = item.dict()print(f"==== item_dict{item_dict}")if item.tax:price_with_tax = item.price + item.taxitem_dict.update({"price_with_tax": price_with_tax})return item_dict

服务器启动后,服务器侦听192.168.0.99地址的8000端口。

客户端curl连通测试

curl测试代码:

python">curl -X 'POST' \'http://192.168.0.99:8000/v1/chat/completions/' \-H 'Content-Type: application/json' \-d '{"messages":[{"role": "user", "content": "hello"}]}'

测试通过!

ESP32S3开发板通过中转连星河大模型成功


在ESP32S3开发板的MicroPython环境下,使用requests来连fastapi的中转服务器,连接成功:

python">import requestsresponse = requests.post('http://192.168.0.99:8000/v1/chat/completions/',headers = {'Content-Type': 'application/json',},json = {'model': "ernie-speed-8k","messages": [{"role": "user", "content": "hello"}]}
)print(response.status_code, response.reason)
print(response.text)
python">print(response.text)
"你好!有什么我可以帮助你的吗?"

自此,ESP32开发板在micropython里直接用requests向web服务器发送请求,测试成功!


http://www.ppmy.cn/devtools/138287.html

相关文章

05—如何设计和仿真阻抗匹配网络

如何设计和仿真阻抗匹配网络 1. 介绍 在设计电路时,大部分同学只是想把布局布置的更专业,可能没有考虑串扰、电源完整性或阻抗匹配等问题。当了解天线和其他射频设备的匹配网络后,才会意识到阻抗匹配在高速和高频电路中的重要性。 但是,什么时候应该使用阻抗匹配网络?哪…

vulnhub靶场之hackableⅢ

hackable3 前言 这里使用virtual box加载靶机 靶机&#xff1a;hackable3 攻击&#xff1a;kali 主机发现 使用arp-scan -l扫描 信息收集 使用nmap扫描 这里明显&#xff1a; 22端口ssh服务可能过滤了80端口开启apache的http服务 网站目录扫描 使用dirsearch扫描&…

中国前首富胡志标亮相创客匠人盛会,点燃创始人 IP 新思维火花

创客匠人正式官宣&#xff01;原爱多VCD创始人、中国前首富胡志标受邀出席创客匠人5000人“全球创始人IP领袖高峰论坛”&#xff0c;将与我们携手共赴这场商业巅峰盛宴。 由创客匠人打造的“全球创始人IP领袖高峰论坛”将在2024年12月26日-28日在厦门市国际博览会议中心如期举…

wangEditor富文本插入自定义应用

文章目录 前言Modal插入富文本应用注册新菜单在自定义Modal操作Editor实例 前言 最近在业务中被要求用到了富文本的需求&#xff0c;经过调研最终决定使用国产的 wangeditor &#xff0c;需要在富文本菜单里插入自己的外部应用&#xff0c;本文旨在记录。 Modal插入富文本应用…

深度学习模型:门控循环单元(GRU)详解

本文深入探讨了门控循环单元&#xff08;GRU&#xff09;&#xff0c;它是一种简化版的长短期记忆网络&#xff08;LSTM&#xff09;&#xff0c;在处理序列数据方面表现出色。文章详细介绍了 GRU 的基本原理、与 LSTM 的对比、在不同领域的应用以及相关的代码实现&#xff0c;…

qt QStyle详解

1、概述 QStyle是Qt框架中用于自定义和绘制控件样式的一个核心类。它提供了一套丰富的API&#xff0c;允许开发者根据应用程序的需求和平台的视觉风格&#xff0c;自定义控件的外观和行为。QStyle的主要职责是处理控件的绘制&#xff08;painting&#xff09;和布局&#xff0…

图论入门编程

卡码网刷题链接&#xff1a;98. 所有可达路径 一、题目简述 二、编程demo 方法①邻接矩阵 from collections import defaultdict #简历邻接矩阵 def build_graph(): n, m map(int,input().split()) graph [[0 for _ in range(n1)] for _ in range(n1)]for _ in range(m): …

软件工程——期末复习(适用于sdut)

名词解释&#xff1a; 名词解释--人月 答案&#xff1a;人月是软件开发工作量的单位&#xff0c;1人月表示1个程序员1个月的工作时间所开发的代码量。 请解释软件缺陷、错误和失败&#xff0c;并简单举例说明。 答案&#xff1a;缺陷&#xff08;defect&#xff09;指系统代…