day16-Trae开发换脸微信小程序03

今日内容

0 Python调用Coze换脸工作流

# 1 在coze平台创建一个 工作流【开始--介绍】---》不仅仅在浏览器中用
	-为什么要把coze工作流包装成功软件
    	-我们制作的软件【编写的软件】--》可以扩展--》加入自己的功能
        
# 2 使用代码调用它【工作流】
	-可以用各种语言:python。。。。go,java

image-20260426201149013

image-20260426203718949

# 1 导入包,后续代码中会使用
import requests   # pip install requests
import json
import time
import os
from typing import Optional, Dict, Any
'''
个人访问令牌:https://www.coze.cn/open/oauth/pats
'''

# 2 写另一个类:CozeAPI,类中有很多方法
class CozeAPI:
    """Coze API客户端,用于调用Coze的换脸工作流"""

    # 2.1 __init__ 类实例化时,会调用  coze_api = CozeAPI()--->完成初始化
    def __init__(self, api_key: str = None, workflow_id: str = None):
        self.api_key = api_key or 'pat_1gKm8Lk3UKGEH9qLUqdHPg1b6eQalw0jmYzeQVJ1BbpoSJCoXJMhI9YXAfGZDrV4'  # 你们的token
        self.workflow_id = workflow_id or '7631948968259469339' # 用我的id号
        self.base_url = 'https://api.coze.cn'
        self.upload_url = f"{self.base_url}/v1/files/upload"
        self.run_url = f"{self.base_url}/v1/workflow/run"
        self.headers = {'Authorization': f'Bearer {self.api_key}', 'Content-Type': 'application/json'}

    # 2.2 获取本地保存路径:换脸成功后,会把换脸的图片,保存到本地
    # 当前目录下的:face_swap文件夹下的coze_results 文件夹下 result_任务id号_当前时间.jpg
    def _get_save_path(self, task_id: str) -> str:
        """内部方法:生成图片保存路径(精简路径处理逻辑)"""
        result_dir = os.path.join('face_swap', 'coze_results')
        os.makedirs(result_dir, exist_ok=True)
        filename = f"result_{task_id}_{int(time.time())}.jpg"
        return os.path.join(result_dir, filename)

    # 2.3 把换脸图片图片下载到本地
    def download_image(self, image_url: str, task_id: str) -> Optional[str]:
        """下载图片到本地,返回跨平台路径"""
        try:
            save_path = self._get_save_path(task_id)
            resp = requests.get(image_url, stream=True)
            resp.raise_for_status()

            with open(save_path, 'wb') as f:
                for chunk in resp.iter_content(chunk_size=8192):
                    f.write(chunk)

            print(f"图片下载成功: {save_path}")
            return save_path.replace('\\', '/')
        except Exception as e:
            print(f"图片下载失败: {str(e)}")
            return None

    # 2.4 上传文件:上传Coze服务器 待换脸的两张图片--》功能是一次上传一张,只是我们调用了两次
    def upload_file(self, file_path: str) -> str:
        """上传文件到Coze并获取文件ID"""
        if not os.path.exists(file_path):
            raise FileNotFoundError(f"文件不存在: {file_path}")

        try:
            print(f"开始上传文件: {file_path}")
            with open(file_path, 'rb') as f:
                files = {'file': (os.path.basename(file_path), f)}
                resp = requests.post(self.upload_url, headers={'Authorization': f'Bearer {self.api_key}'}, files=files)

            print(f"上传响应: {resp.status_code} | {resp.text}")
            result = resp.json()

            if resp.status_code == 200 and result.get('code') == 0 and 'data' in result:
                file_id = result['data'].get('id')
                if not file_id:
                    raise Exception(f"未提取到文件ID: {result}")
                print(f"文件上传成功,ID: {file_id}")
                return file_id
            raise Exception(f"文件上传失败: {result}")
        except Exception as e:
            print(f"文件上传异常: {str(e)}")
            raise

    # 2.5 执行工作流
    def run_workflow(self, source_image: str, target_image: str) -> Dict[str, Any]:
        """运行Coze换脸工作流,返回任务信息"""
        try:
            # 3.5.1 调用两次,把两张图片传上去--》拿到图片的id
            source_id, target_id = self.upload_file(source_image), self.upload_file(target_image)
            # 3.5.2 组装成 调用工作流的数据格式
            payload = {
                "workflow_id": self.workflow_id, # 工作流ID号
                "parameters": {
                    "face": json.dumps({"file_id": source_id}),   # face
                    "backed": json.dumps({"file_id": target_id}), # backed入参
                    "text": "执行换脸操作"                          # 可以带可以不带
                },
                "app_id": "",                                     # 放空
                "is_async": True                                  # 是否异步
            }

            print(f"调用工作流 {self.workflow_id}...")
            resp = requests.post(self.run_url, headers=self.headers, json=payload)

            if resp.status_code != 200:
                raise Exception(f"工作流调用失败: {resp.status_code} | {resp.text}")

            result = resp.json()
            if (result.get('code') == 0 or result.get('msg') == '') and (task_id := result.get('execute_id')):
                print(f"工作流调用成功,任务ID: {task_id}")
                # 调用coze工作流成功--》返回 一堆数据,这对数据中有 :task_id:任务id,后续根据这个id查询是否执行完了  workflow_id
                return {'code': 0, 'msg': 'success',
                        'data': {'task_id': task_id, 'workflow_id': self.workflow_id, 'status': 'pending'}}

            raise Exception(f"工作流调用失败: {result.get('msg')} | {result}")
        except Exception as e:
            print(f"工作流调用异常: {str(e)}")
            raise

    # 2.6 获取工作结果---》任务id号
    def get_workflow_result(self, task_id: str) -> Dict[str, Any]:
        """查询工作流执行结果"""
        try:
            print(f"查询任务 {task_id} 结果...")
            # 简化URL拼接(移除模板字符串,直接格式化)
            query_url = f"{self.base_url}/v1/workflows/{self.workflow_id}/run_histories/{task_id}"
            resp = requests.get(query_url, headers=self.headers)

            if resp.status_code != 200:
                raise Exception(f"查询失败: {resp.status_code} | {resp.text}")

            result = resp.json()
            if result.get('code') != 0:
                raise Exception(f"查询结果失败: {result.get('msg')} | {result}")

            # 提取核心数据
            data = result.get('data', [{}])[0]
            exec_status = data.get('execute_status', '')

            if exec_status == 'Success':
                #  #####正常拿到结果---》查到任务执行完了---》解析返回结果
                return self._parse_success_result(data, task_id)
            elif exec_status == 'Fail':
                # 查询任务失败--》返回
                return {'status': 'failed', 'error_message': '任务执行失败', 'task_id': task_id}
            return {'status': 'processing', 'task_id': task_id}

        except Exception as e:
            print(f"查询结果异常: {str(e)}")
            raise
    # 2.7 解析查询任务的结果
    def _parse_success_result(self, data: Dict[str, Any], task_id: str) -> Dict[str, Any]:
        """内部方法:解析成功的任务结果(拆分复杂的解析逻辑)"""
        try:
            output = json.loads(data.get('output', '{}'))
            result_data = json.loads(output.get('Output', '{}'))
            image_url = result_data.get('output')

            if not image_url:
                return {'status': 'success', 'message': '任务成功但未返回图片', 'task_id': task_id}
            # 2.7.1 任务正常执行成功,图片也有了---》下载图片--》保存到本地
            local_path = self.download_image(image_url, task_id)
            return {
                'status': 'success',
                'result_image_url': image_url,
                'local_image_path': local_path,
                'processing_time': data.get('processing_time', 0),
                'task_id': task_id
            }
        except (json.JSONDecodeError, KeyError) as e:
            print(f"解析输出失败: {str(e)}")
            return {'status': 'success', 'message': '任务成功但解析输出失败', 'task_id': task_id}


# 3 程序的主入口:右键运行,从里面开始执行
if __name__ == '__main__':
    try:
        # 3.1 类实例化的到对象
        coze_api = CozeAPI()
        # 3.2 定义两个变量:存放两张图片
        source_path, target_path = './test_source.jpg', './test_target.jpg'
        print("开始测试Coze换脸工作流...")

        # 3.3 运行工作流并获取任务ID:运行工作流--》异步操作
        # 工作流提交上去---》拿到一个ID号---》Coze后台就在换脸---》我们的程序可以干其他事
        run_result = coze_api.run_workflow(source_path, target_path)
        print(f"工作流提交结果: {run_result}")

        if run_result.get('code') == 0:
            # 3.4 拿到任务id
            task_id = run_result['data']['task_id']
            print(f"任务ID: {task_id}")
            # 3.5 睡了20s
            time.sleep(20)  # 等待任务处理

            # 3.6 查询结果
            result = coze_api.get_workflow_result(task_id)
            print(f"任务结果: {result}")

            # 3.7 有结果,精简结果判断逻辑,把换脸的结果保存到本地
            status_map = {
                'success': f"✅ 测试成功!\nURL: {result.get('result_image_url')}\n本地路径: {result.get('local_image_path')}",
                'processing': "⏳ 任务仍在处理中",
                'failed': f"❌ 任务失败: {result.get('error_message')}"
            }
            print(status_map.get(result.get('status'), "❌ 未知状态"))
    except Exception as e:
        print(f"❌ 测试失败: {str(e)}")

0.1 如果让AI写,提示词如何写

# 1 纯让AI写 Python调用Coze换脸工作流  写完是有问题的

# 2 我们可以让它写完,我们调---》但是需要大家会python,会网络才行


# 3 因为我们不会代码,所有代码,我们都要让Trae写
	-1 写完会有错误
    	-会代码的人,可以自己改--》代码能力越强,改的越快,越好
        -不会代码的人,继续让Trae改---》可能需要花费几天时间,才改好
        	-这个过程中,你不断学习
            
            
            
            
            
            
            
# 4 提示词【写完后,可能能有,可能不能用,如果不能用,会报错,把错误给他,让他继续改】:
	我编写好了一个Coze的一键换脸工作流,上传两张图片:face和backed,调用工作流就可以完成换脸,调用的API接口参照:https://www.coze.cn/open/playground/workflow_stream_run?workflow_id=7631948968259469339,帮我使用Python完成对该工作流的调用
    1 工作流ID是:7631948968259469339
    2 API_key是:【你们的】

1 后端环境搭建

后端使用Python+Django+mysql架构--》要在本地运行---》搭建本地的运行环境

  1. python的解释器环境
  2. python解释器中要装Django模块:Trae可以帮我们做
  3. 本地安装mysql:存数据

1.1 Python环境【没讲具体】

# 1 只要学过python的,都知道,我们开发python或者运行python代码,必须要有这个环境
# 2 去python官网,下载python解释器,安装上:使用的版本:  python3.11
# 3 安装完成后:打开cmd,输入python

image-20260426205522617

1.3 Trae安装python插件

# 1 本地安装好了python解释器环境,就可以运行python代码了
# 2 我们之前使用Pycharm软件,运行python代码
# 3 现在我们通过配置,让Trae也能运行Python代码:前几次课讲过

1.2 Mysql8.4 安装

# 1 我们的一键换脸小程序:需要存用户的用户名密码,换脸历史登数据---》这些数据都是要存到mysql数据库中的

# 2 mysql数据库 有很多版本:目前企业中,使用 8.x 是最多的,所以我们也使用8.x 版本

# 3 本地开发:代码在本地,所以数据库目前也放在本地【win机器】
	-后期上线Linux:代码放到服务器上,数据库也安装在服务器上
    
    
# 4 Mysql 数据库管理软件--》有个库【你家】---》有很多表【一个个房间】---》表中有很多数据【房间中放了很多货物】
	-库:change_face  # 需要我们创建
    -表:用户表,换脸历史表。。 # 不需要我们创建,Trae帮我们做
    -数据:用户表中:张三,李四,王五的数据 # 在使用软件过程中,产生的,不需要我们插入
    
# 5 具体例子
# 用户表:User
id        name            password   age
1         zhangsan         123456    18
2         lisi             555555    18
3         wanwu            666666    18

# 换脸历史表 History
id      换脸时间           换脸用户    图片地址
1       2026年4月26号       1          ./a.jpg
2       2026年4月26号       1          ./b.jpg
3       2026年4月26号       2          ./c.jpg


# 6 使用程序操作数据库:安全,可靠,效率高

1.2.1 win 安装

# 1 我很早之前写一了一篇文章:安装mysql :https://zhuanlan.zhihu.com/p/571585588

################## 具体步骤################
# 1 下载mysql8.4.4
	-https://downloads.mysql.com/archives/community/
# 2 解压到某个路径下--》不要带中文
	-D:\software\mysql-8.4.4-winx64\mysql-8.4.4-winx64
# 3 在 bin所在目录创建 my.ini   # 后缀名注意,不要带 .txt

# 4 创建 data文件夹:D:\software\mysql-8.4.4-winx64\mysql-8.4.4-winx64\data\
########## 在 my.ini 中写入

[mysqld]
# 设置3309端口--->如果装过老版本,占了3306,你就会装不上
port=3309
# 设置mysql的安装目录 ---这里输入你安装的文件路径----
basedir=D:\software\mysql-8.4.4-winx64\mysql-8.4.4-winx64\
# 设置mysql数据库的数据的存放目录
datadir=D:\\software\\mysql-8.4.4-winx64\\mysql-8.4.4-winx64\\data\
# 允许最大连接数
max_connections=200
# 允许连接失败的次数。
max_connect_errors=10
# 服务端使用的字符集默认为utf8
character-set-server=utf8mb4
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8mb4
[client]
# 设置mysql客户端连接服务端时默认使用的端口
port=3309
default-character-set=utf8mb4





# 5 来到mysql解压后的bin路径下(以管理员身份运行)
以管理员打开cmd
D:   # 回车
cd D:\software\mysql-8.4.4-winx64\mysql-8.4.4-winx64\bin
    
    
# 6 安装mysql  安装完成后Mysql会有一个随机密码(记住这个密码)--》这里可能会出错  dll文件缺失
mysqld --initialize --console

# 密码:9efF/cgks8rh


# 7 把mysql创建成系统服务 
mysqld --install mysql844

# 8 启动mysql服务
net start mysql844



# 9 做成服务后,没有开启自启动--》win关机了,再开启,mysql没启动
命令行中执行:net start mysql844
在服务上点右键启动
如果做成了  自动  --》以后重启后,都是自动开启

# 10 做成开机自启动
	如下图

image-20260426212634781

image-20260426213622753

image-20260426214110075

1.2.2 修改密码

# 1 打开cmd
# 2 来到这个路径下输入:D:\software\mysql-8.4.4-winx64\mysql-8.4.4-winx64\bin  输入 
mysql -uroot -p -P 3309  # 回车后,输入密码,进入后
# 3 改密码
ALTER USER 'root'@'localhost' IDENTIFIED BY 'lqz123?';
FLUSH PRIVILEGES;
quit

# 4 后续命令不讲了--》因为要学很久

# 5 如果密码忘了:粗暴方式
	-删data文件夹
    -mysqld --initialize --console  

image-20260426214406090

1.2.3 navicat可视化操作【收费-破解用】

# 1 在黑色命令下操作数据库,需要会很多命令--》很难记---》使用图形化界面连接操作--》点点的即可
# 2 mysql官方没有提供可视化,只能用命令,有很多第三方,用谁都行
### DBeaver
优点:DBeaver功能比较强大,使用也较便利。缺点:对于系统资源要求较高,运行速度相对较慢,特别是导入大文件时比较明显。官方主页:https://dbeaver.io/
    
#### Navicat--收费的--》破解--》好用
# 个人没事
# 不要在公司内部使用破解--》这个公司能根据你的ip--》定位到你公司--》发律师函--》告你
优点:Navicat使用普及率较高,功能非常完整,包括比较强大的SQL补全、导入导出、结果集编辑、E-R模型、数据对比、结构对比、数据迁移等,但有部分功能仅企业版才具备。缺点:需要注册为Navicat用户才能够使用,而且定期会失效,需要重新下载和登录申请为免费使用。官方主页:https://navicat.com/
    
####SQLyog
SQLyog更多的是专注于数据库的管理,包括性能、监控、优化等方面,也提供基础SQL编辑功能,所以在早期,其在DBA群体中比较受欢迎,但是在整体的开发者中,使用比率并不高。缺点:在云时代对于监控与实例管理方面的诉求在降低,在SQL开发与云适配上需求更强,但这方面发展缓慢,而且产品以商业收费版为主。官方主页:https://webyog.com/product/sqlyog/
    
    

image-20260426215430389

image-20260426215456617

image-20260426215611885

image-20260426215646046

1.2.4 Trae可视化操作【免费】

# 1 点扩展--》安装mysql插件
# 2 链接即可

image-20260426215827363

image-20260426215851433

image-20260426220002620

image-20260426220157974

image-20260426220216170

2 Trae编写后端

2.1 提示词

根据项目需求: 和项目后端架构文档:  和前端设计图: ,生成智能换脸微信小程序后台Django的项目和代码
要求:
1.项目写入到目录change_face_api中。
2.生成相关表模型,写入到每个app的models中。
3.生成所有接口,并能正常调用。
4.链接数据库地址为:
    -host:127.0.0.1
    -port:3309
    -database:change_face
    -user:root
    -password:lqz123?
5.Django 后台admin使用django-simpleui美化,项目做好本地化和时区设置。
6.换脸功能对接Coze一键换脸工作流,对接方案参照代码:
	-API_KEY:pat_1gKm8Lk3UKGEH9qLUqdHPg1b6eQalw0jmYzeQVJ1BbpoSJCoXJMhI9YXAfGZDrV4
    -工作流ID:7631948968259469339

2.2 模型思考超长

# 1 因为Trae从0,开始写一个完成的后端项目--》代码量很大--》代码大模型,会出现思考超长
# 2 做到一半:如果超长了,点继续--》让它继续做即可

2.3 浏览器访问:

# http://localhost:8000/admin/

# 后端有没有bug? 肯定有,我们先不着急改

image-20260426222622881

3 小程序概述

视频:
	https://www.bilibili.com/video/BV1WgQdYNERe/
笔记:
 	https://pan.baidu.com/s/1VTd6S3rJKQ42MRFPsFwaZQ 提取码: bpxa
            
            
使用微信用户,一键登录小程序
	- 发送短信微信绑定的手机号---》收费
    - 企业用户:营业执照
posted @ 2026-04-27 19:02  凫弥  阅读(3)  评论(0)    收藏  举报