甴尐 · 3月19日 · 广东

【聆思大模型AI开发套件】调用自己的AIGC 打通stable diffusion 自己lora图片

先上图

微信图片_20240319194156.jpg微信图片_20240319194520.jpg!

如何实现

 title=
1.板子发送post请求。stable diffusion webui 这边图片默认是512\\_512 .板子内存有限。需要flask 接收图片后进行一次缩放到240\\_240.(未填充满,板子资源太紧张了)
ps。都在本地。webui可以部署到云服务器。
2.webui 使用lora 调整图片风格,还有 lcm 加快出图速度。正常是20step 出图,加上lcm 可以4-6step 出图

python webui.py --port 8903 --xformers --share --device-id 1 --api --listen
3.flask 服务器中转调用webui
time curl -X POST http://10.162.88.10:5000/post -H "Content-Type: application/json" -d '{"prompt":"dog"}'

 title=
 title=

单3090显卡 4G 显存占用出图时间0.5s

 title=
聆思大模型AI开发套件
开发环境搭建
安装lisa工具包
wget -qO- https://cdn.iflyos.cn/public/cskTools/lisa-zephyr-install-v2.sh | bash
lisa info zephyr
下载源码
git clone --branch v1.6.0 https://cloud.listenai.com/CSKG962172/duomotai\\\_ap.git
初始化
lisa zep init-app
lisa zep update
编译工程
lisa zep build -b csk6\\\_duomotai\\\_devkit apps\LLM\\\_control -p
板子下载程序
lisa zep exec cskburn -s .\COM54 -C 6 -b 1500000 0x000000 Z:\06\\\_iot\07\\\_lisa\duomotai\\\_ap\build\zephyr\zephyr.bin
 title=
总体评价 简洁,快速,多平台,点赞。。
 title=
使用linux gpu 服务器编译。然后windows samba服务下载。

代码修改

1.使用串口触发post请求
\\\`
static void cmd\\\_aigc\\\_sdwebui(const struct shell shell, size\\\_t argc, char *argv)
{

if(argc != 2 || argv == NULL){
    LOG_ERR("cmd_aigc_sdwebui error, argc = %d, argv = %p", argc, argv);
    return;
}

char *prompt = argv[1];
LOG_INF("YYJJ cmd_aigc_sdwebui = %s", prompt);
int ret = 0;
uint8_t *out_data = NULL;
int out_len = 0;
//char png_download_url[256] = "http://10.162.88.10:5000/output/dog_20240319153542.png";
char png_download_url[256];
int ret = app_aigc_post("http://10.162.88.10:5000/post", prompt, &png_download_url);
if(ret == 0)
{
    uint8_t *out_data = NULL;
    int out_len = 0;
    int ret = app_download(png_download_url, &out_data, &out_len);
    if(ret != 0){
        LOG_ERR("app download failed: %d", ret);    
    }else{
        LOG_INF("app download succeeded: addr: %p, len: %d", (void *)out_data, out_len);
        if((out_len != 0) && (out_data != NULL)){
            ui_set_img(out_data, out_len);
            csk_free(out_data);
        }
    }
}

}

#define AIGC_SD_PROMPT_TEXT     "<wifi> aigc sd prompt text"

SHELL_STATIC_SUBCMD_SET_CREATE(sub_wifi,
                    SHELL_CMD_ARG(connect,         NULL, WIFI_CONNECT_TEXT,     cmd_wifi_connect,     3, 0),
                       SHELL_CMD_ARG(disconnect,     NULL, WIFI_DISCONNECT_TEXT, cmd_wifi_disconnect,1, 0),
                       SHELL_CMD_ARG(add,             NULL, WIFI_ADD_TEXT,         cmd_wifi_add,         3, 0),
                       SHELL_CMD_ARG(delete,         NULL, WIFI_DELETE_TEXT,     cmd_wifi_delete,     2, 0),
                    SHELL_CMD_ARG(list,         NULL, WIFI_LIST_TEXT,         cmd_wifi_list,         1, 0),
                    SHELL_CMD_ARG(aigc,         NULL, AIGC_SD_PROMPT_TEXT,     cmd_aigc_sdwebui,     2, 0),
                       SHELL_SUBCMD_SET_END
);~~~~
`
2.获取下载地址
`int parse_json_response(const char *response_buf, char **aigc_url) {
    // 参数校验
    if (response_buf == NULL || aigc_url == NULL) {
        return -1; // 无效参数
    }

    // 解析JSON
    cJSON *json = cJSON_Parse(response_buf);
    if (json == NULL) {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            fprintf(stderr, "Error before: %s\n", error_ptr);
        }
        return -1; // 解析失败
    }

    cJSON *file_url = cJSON_GetObjectItemCaseSensitive(json, "file_url");
    if (cJSON_IsString(file_url) && (file_url->valuestring != NULL)) {
        *aigc_url = strdup(file_url->valuestring);
        cJSON_Delete(json); 
        return 0; 
    } else {
        cJSON_Delete(json); 
        return -1; 
    }
}

int app_aigc_post(const char *url, char * prompt , uint8_t **aigc_url)
{
    int ret = 0;
    int client_socket = -1;
    if(url == NULL){
        LOG_ERR("%s: %d", __FUNCTION__, __LINE__);
        return -1;
    }

    ret = http_parse_url(&http_client, url);
    if(ret < 0){
        LOG_ERR("%s: %d", __FUNCTION__, __LINE__);
        return ret;
    }

    client_socket = connect_socket(http_client.host, http_client.port);
    if(client_socket < 0){
        LOG_ERR("%s: %d", __FUNCTION__, __LINE__);
        ret = client_socket;
        goto failed;
    }

    char req_buf[128] = "{\"prompt\":\" dog \"}"; // 根据需要修改负载
    scanf(req_buf,"{\"prompt\":\" %s \"}",prompt);
    size_t req_buf_len = strlen(req_buf);
    LOG_INF("Start Post");

    char *response_buf = csk_malloc(MAX_IAMGE_SIZE);
    if(!req_buf){
        LOG_ERR("%s: %d", __FUNCTION__, __LINE__);
        close(client_socket);
        ret = -1;
        goto failed;
    }

    struct http_request req = {
        .method = HTTP_POST,
        .url = "/post", // Flask定义的路径
        .host = "10.162.88.10",
        .protocol = "HTTP/1.1",
        .header_fields = (const char *[]){"Content-Type", "application/json", NULL},
        .response = response_aigc_cb,
        .recv_buf = response_buf,
        .recv_buf_len = MAX_IAMGE_SIZE,
        .payload = req_buf,
        .payload_len = req_buf_len,
    };

    ret = http_client_req(client_socket, &req, 5000, "IPv4 POST");
    if(ret < 0){
        LOG_ERR("%s: %d", __FUNCTION__, __LINE__);    
    }
    close(client_socket);
    
    ret = k_sem_take(&http_rsp_sem, K_SECONDS(10));
    if(ret != 0){
        LOG_ERR("get image timeout: %d", ret);
        goto closed;
    }
    parse_json_response(response_buf, aigc_url);

closed:
    if(response_buf) csk_free(response_buf);
failed:
    if(http_client.scheme) csk_free(http_client.scheme);
    if(http_client.host) csk_free(http_client.host);
    if(http_client.path) csk_free(http_client.path);
    memset(&http_client, 0, sizeof(http_client_handle_t));

    return ret;
}
`
3.下载并且显示
`
        int ret = app_download(png_download_url, &out_data, &out_len);
        if(ret != 0){
            LOG_ERR("app download failed: %d", ret);    
        }else{
            LOG_INF("app download succeeded: addr: %p, len: %d", (void *)out_data, out_len);
            if((out_len != 0) && (out_data != NULL)){
                ui_set_img(out_data, out_len);
                csk_free(out_data);
            }
        }
`

\\`\\`
 title=
\\`

中间框架 flask

stable diffusion webui 接口
 title=
post 和get 方法。
代码较少。直接全部贴源码
\`
from flask import Flask, request, jsonify, url\_for
import datetime
import base64
import os
import requests
import json
from PIL import Image
import io

app = Flask(\_\_name\_\_)
from flask import send\_from\_directory

def save\_encoded\_image(b64\_image: str, output\_path: str):

"""
Save the given image to the given output path.
:param b64_image:  base64 encoded image
:param output_path:  output path
:return:  None
"""

# 判断当前目录下是否存在 output 文件夹,如果不存在则创建
if not os.path.exists("output"):
    os.mkdir("output")
timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
output_path = f"{output_path[0:5]}_{timestamp}" + ".png"
            
# 将文件放入当前目录下的 output 文件夹中
output_path = f"output/{output_path}"
# Decode the base64 image
image_data = base64.b64decode(b64_image)
image = Image.open(io.BytesIO(image_data))

# Resize the image
image = image.resize((240, 240), Image.ANTIALIAS)

# Save the resized image
image.save(output_path)

print(output_path)
return output_path

def webui\_txt2img(prompt='dog'):

txt2img_url = "http://10.162.89.10:8903/sdapi/v1/txt2img" # 服务器地址
prompt_lora_lcm = prompt + r", <lora:PixelStyle:1>,<lora:pytorch_lora_weights:1>"
data = {
    'prompt': prompt_lora_lcm,
    'negative_prompt': '',
    "sampler_index": "LCM",
    'width': 512,
    'height': 512,
    "steps": 6,
    "cfg_scale": 1.5,
}
print(data)
response = requests.post(txt2img_url, data=json.dumps(data))
image_path = save_encoded_image(response.json()['images'][0], prompt) 
return image_path

@app.route('/post', methods=['POST'])
def handle\_post():

data = request.json
print(data)
if not data or 'prompt' not in data:
    return jsonify({"error": "Missing 'prompt' field"}), 400

prompt = data['prompt']
print(f"Received prompt: {prompt}")
image_file_name = webui_txt2img(prompt)
root_url = request.url_root.rstrip('/')  # 移除尾部的斜杠(如果有的话)
file_url = f'{root_url}/{image_file_name}'
return jsonify({"file_url": file_url})

@app.route('/output/<path:filename>')
def custom\_static(filename):

return send_from_directory('output', filename)

if name == '\_\_main\_\_':

app.run(host='0.0.0.0', port=5000, debug=True)

\`

 title=
 title=
 title=!

总结

上手体验快。同级别芯片对比乐鑫只有不好用的chatgpt。总体来说资源太紧了,建议加大psram。
后续弄一下LVGL,添加chagpt,完成lvgl,然后语音转文字,tts。然后开源出来。。

推荐阅读
关注数
1
文章数
7
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息