当前位置: 首页 > article >正文

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

在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) 发送数据,结果还是报错:

用这段测试:

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, Form

app = 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机测试通过:

python3 tp1.py 
200

micropython报buff有问题

再次测试micropython下request

import requests as urequests
# import urequests

def 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文件内容:

cat app.py 
from typing import Annotated
import json
from fastapi import FastAPI, Path, Query
from pydantic import BaseModel
from openai import OpenAI
 
import os
import time
from typing import Union, Optional
 
app = FastAPI()
API_KEY = "xxxx"
model="ernie-speed-8k"
 
 
class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None
 
class ChatItem(BaseModel):
    messages: list
    model: str | None = None
 
def 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.messages
    print(f"==== messages=chatitem.msg:{messages}")
    y = ChatCompletions(messages=messages, model=model, api_key=API_KEY)
    print("="*10, y)
    z = y.choices[0].message.content
    return 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.tax
        item_dict.update({"price_with_tax": price_with_tax})
    return item_dict

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

客户端curl连通测试

curl测试代码:

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的中转服务器,连接成功:

import requests
 
response = 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)
print(response.text)
"你好!有什么我可以帮助你的吗?"

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


http://www.kler.cn/a/420571.html

相关文章:

  • CAD 二次开发入门与实践:以 C# 为例
  • Figma入门-自动布局
  • 如何预防服务器后台爆破攻击
  • 嵌入式蓝桥杯学习1 电量LED
  • 护航开源大赛,赋能数字未来
  • IDEA使用HotSwapHelper进行热部署
  • 负载均衡指南:Nginx与HAProxy的配置与优化
  • mysql 查询所有的触发器
  • vmware linux centos7 网络配置
  • 大数据-238 离线数仓 - 广告业务 点击次数 ADS层、广告效果分析 ADS 层 需求分析与加载
  • 2024-11-29 学习人工智能的Day33 BP算法和神经网络小实验
  • Python字符串对齐的几种方法、Python填充与对齐、Python中英文对齐
  • 软件测试常问面试问题及项目流程相关概念
  • 深入实践:从零开始掌握GPT的应用开发
  • 错误信息 Uncaught (in promise) TypeError: extender is not a function
  • spark中将json数据转成dataset
  • Ubuntu 20.04 程序运行导致“段错误 (核心已转储)”的原因分析及解决方案 ubuntu
  • droppath
  • Qt的定时器应用案例 || Qt的图片添加显示
  • 2017 NHOI小学(C++)
  • MySQL 单表练习
  • C#中的集合初始化器
  • TongRDS分布式内存数据缓存中间件
  • 《数据结构》学习系列——图(下)
  • flink学习(14)—— 双流join
  • Redis开发05:使用stackexchange.redis库对redis进行增删改查