批改作业小工具(二)-调用大模型接口

部署运行你感兴趣的模型镜像

处理一个报告:用了线程,因为实验报告每部分字比较多,所以 按报告结构分成4个部分提交的,从结果看,一个学生7份报告费时10分钟~~~

import requests
import json
import traceback
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading

# 百度文心一言 API 配置(请替换为实际可用的密钥)
API_KEY = "yo76sSr****g9Tsdz6y"  # 请确认这是有效的API Key
SECRET_KEY = "UawrTm*****6jA6X2AFgXbA"  # 请确认这是有效的Secret Key
API_URL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token="

# 全局变量用于Token管理
token_lock = threading.Lock()
current_token = None
token_expiry_time = 0
TOKEN_REFRESH_THRESHOLD = 300  # 提前5分钟刷新token
MAX_RETRIES = 3  # 最大重试次数
PARALLEL_REPORTS = 3  # 并行处理的报告数量


class TokenManager:
    """Token管理器,负责获取和刷新访问令牌"""

    @staticmethod
    def get_access_token():
        """获取百度文心一言 API 的访问令牌"""
        global current_token, token_expiry_time

        start_time = time.time()
        url = f"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={API_KEY}&client_secret={SECRET_KEY}"
        print(f"正在获取access_token,请求URL: {url}")

        try:
            response = requests.get(url)
            print(f"响应状态码: {response.status_code}")
            print(f"响应内容: {response.text}")
            response.raise_for_status()

            data = response.json()
            print(f"解析后的token数据: {data}")

            # 计算Token过期时间(假设30天后过期,实际应根据返回的expires_in字段)
            expires_in = data.get("expires_in", 2592000)  # 默认30天
            token_expiry_time = start_time + expires_in - TOKEN_REFRESH_THRESHOLD

            current_token = data.get("access_token")

            # 计算并输出耗时
            elapsed_time = time.time() - start_time
            print(f"获取access_token耗时: {elapsed_time:.2f}秒\n")
            return current_token
        except Exception as e:
            elapsed_time = time.time() - start_time
            print(f"获取访问令牌失败(耗时: {elapsed_time:.2f}秒): {e}")
            traceback.print_exc()
            return None

    @staticmethod
    def get_valid_token():
        """获取有效的访问令牌,如果即将过期则自动刷新"""
        global current_token, token_expiry_time

        with token_lock:
            # 如果当前没有token或者token即将过期,则获取新token
            if not current_token or time.time() >= token_expiry_time:
                return TokenManager.get_access_token()
            return current_token


def call_wenxin_api_with_retry(access_token, content, action_name, max_retries=MAX_RETRIES):
    """
    调用百度文心一言API,带有重试机制
    参数:
        access_token: API访问令牌
        content: 请求内容
        action_name: 操作名称(用于日志)
        max_retries: 最大重试次数
    """
    start_time = time.time()
    last_error = None

    for attempt in range(1, max_retries + 1):
        attempt_start = time.time()

        if not access_token:
            print("访问令牌无效,无法调用API")
            return None

        url = API_URL + access_token
        headers = {
            "Content-Type": "application/json"
        }

        payload = {
            "messages": [
                {"role": "user", "content": content}
            ]
        }

        print(f"\n=== {action_name} API调用调试信息 (尝试 {attempt}/{max_retries}) ===")
        print(f"请求URL: {url}")
        print(f"请求头: {headers}")
        print(f"请求体: {json.dumps(payload, indent=2)}")

        try:
            response = requests.post(url, headers=headers, data=json.dumps(payload), timeout=60)
            print(f"响应状态码: {response.status_code}")
            print(f"响应内容: {response.text}")

            response.raise_for_status()
            result = response.json()
            print(f"解析后的响应: {result}")

            # 计算耗时
            elapsed_time = time.time() - start_time
            attempt_elapsed = time.time() - attempt_start
            print(f"{action_name} API调用成功 (总耗时: {elapsed_time:.2f}秒, 本次尝试: {attempt_elapsed:.2f}秒)")

            if isinstance(result, dict) and "result" in result:
                return result["result"]
            else:
                print("警告: 响应中未找到'result'字段")
                return None

        except requests.exceptions.RequestException as e:
            attempt_elapsed = time.time() - attempt_start
            print(f"{action_name} API调用失败 (本次尝试耗时: {attempt_elapsed:.2f}秒): {e}")
            last_error = e

            # 如果是认证错误,尝试刷新token
            if hasattr(e, 'response') and e.response is not None and e.response.status_code == 401:
                print("检测到认证错误,尝试刷新access_token...")
                with token_lock:
                    access_token = TokenManager.get_access_token()
                continue

            # 如果是最后一次尝试,不再重试
            if attempt == max_retries:
                break

            # 指数退避等待
            wait_time = min(2 ** attempt, 10)  # 最大等待10秒
            print(f"等待 {wait_time} 秒后重试...")
            time.sleep(wait_time)

    elapsed_time = time.time() - start_time
    print(f"{action_name} API调用最终失败 (总耗时: {elapsed_time:.2f}秒): {last_error}")
    return None


def process_report(report, report_index):
    """
    处理单个实验报告
    参数:
        report - 实验报告字典对象
        report_index - 报告索引(用于日志)
    """
    # 记录单份报告处理开始时间
    report_start_time = time.time()
    print(f"\n===== 开始处理第 {report_index} 份报告 =====")

    # 获取有效token
    access_token = TokenManager.get_valid_token()
    if not access_token:
        print("访问令牌无效,无法处理报告")
        return report, 0

    # 获取报告前4个条目的键(排除最后一个评阅意见条目)
    report_items = list(report.keys())[:4]
    feedbacks = []

    # 遍历处理前4个条目
    for item in report_items:
        item_start_time = time.time()
        print(f"正在处理报告的:{item}")

        # 构建提示词
        prompt = f"请评价以下实验报告中的'{item}'部分,并给出专业的改进建议,供后续综合评分使用:{report[item]}"
        # 调用API,传入操作名称
        feedback = call_wenxin_api_with_retry(access_token, prompt, f"处理{item}")

        if feedback:
            feedbacks.append(f"【{item}评价】{feedback}")
            print("处理完成")
        else:
            print("处理失败")

        # 计算条目处理耗时
        item_elapsed = time.time() - item_start_time
        print(f"{item}处理总耗时: {item_elapsed:.2f}秒")
        print("-" * 80)

    # 生成指导教师评阅意见和评分
    final_feedback = None
    if feedbacks:
        final_start_time = time.time()
        print("正在生成指导教师评阅意见和评分...")
        prompt = f"基于以下对实验报告各部分的评价,请综合给出指导教师评阅意见和评分(满分100分):\n{chr(10).join(feedbacks)}"
        final_feedback = call_wenxin_api_with_retry(access_token, prompt, "生成评阅意见")

        final_elapsed = time.time() - final_start_time
        print(f"评阅意见生成总耗时: {final_elapsed:.2f}秒")

        if final_feedback:
            report["指导教师评阅意见和评分"] = final_feedback
            print("评阅意见生成完成")
        else:
            print("评阅意见生成失败")
    else:
        print("没有足够的评价信息,无法生成评阅意见")

    # 计算单份报告总耗时
    report_elapsed = time.time() - report_start_time
    print(f"\n===== 第 {report_index} 份报告处理完成,耗时: {report_elapsed:.2f}秒 =====")

    return report, report_elapsed


def process_all_reports(reports):
    """
    并行处理所有实验报告
    参数: reports - 实验报告列表
    """
    # 记录总开始时间
    total_start_time = time.time()
    total_reports = len(reports)
    processed_reports = []
    report_times = []

    if total_reports == 0:
        print("没有需要处理的报告")
        return [], 0

    # 获取初始访问令牌
    TokenManager.get_valid_token()

    # 使用线程池并行处理报告
    with ThreadPoolExecutor(max_workers=PARALLEL_REPORTS) as executor:
        futures = []
        for i, report in enumerate(reports, 1):
            futures.append(executor.submit(process_report, report, i))

        # 等待所有任务完成并收集结果
        for future in as_completed(futures):
            try:
                processed_report, report_time = future.result()
                processed_reports.append(processed_report)
                report_times.append(report_time)
            except Exception as e:
                print(f"处理报告时发生错误: {e}")
                traceback.print_exc()

    # 计算总耗时
    total_elapsed = time.time() - total_start_time
    print(f"\n===== 所有报告处理完成!共处理 {total_reports} 份报告 =====")
    if report_times:
        print(f"单份报告平均处理时间: {sum(report_times) / len(report_times):.2f}秒")
    print(f"批量处理总耗时: {total_elapsed:.2f}秒")

    return processed_reports, total_elapsed


def main():
    # 记录主程序开始时间
    main_start_time = time.time()

    # 示例:创建包含多个实验报告的集合
    reports = [
        {
            "实验目的及要求": "使学生在环境下学会创建角色、为角色授权、将角色授予用户和其他角色、回收角色权限以及删除角色,深入理解角色在数据库权限管理中的作用和优势",
            "实验使用的主要设备及要求": "安装有Gaussdb(for mysql)数据库的计算机,并已安装Navicat数据库管理工具;学生已掌握基本的Gaussdb(for mysql)语句,熟悉实验5的操作内容。",
            "实验操作内容及步骤": "创建角色:打开Navicat连接到Gaussdb(for mysql)数据库;在查询窗口中,使用`CREATE ROLE`语句",
            "实验结果与分析总结": "通过本次实验我学会了在环境下学会创建角色、为角色授权、将角色授予用户和其他角色、回收角色权限以及删除角色,深入理解角色在数据库权限管理中的作用和优势。",
            "指导教师评阅意见和评分": ""
        },
        {
            "实验目的及要求": "掌握数据库用户管理基本操作,包括创建用户、修改用户权限、删除用户等,理解用户权限控制在数据库安全中的重要性",
            "实验使用的主要设备及要求": "安装有Gaussdb(for mysql)数据库的计算机,Navicat数据库管理工具;学生需掌握SQL基本语法,了解数据库安全基础知识。",
            "实验操作内容及步骤": "创建用户:使用CREATE USER语句创建新用户;授权操作:使用GRANT语句为用户分配权限;查看权限:使用SHOW GRANTS语句验证权限分配结果",
            "实验结果与分析总结": "通过实验成功完成了用户创建与权限分配操作,验证了不同权限对数据库操作的影响,理解了最小权限原则在数据库安全管理中的应用。",
            "指导教师评阅意见和评分": ""
        },
        {
            "实验目的及要求": "学习数据库索引的创建和使用,理解索引对查询性能的影响",
            "实验使用的主要设备及要求": "安装有Gaussdb(for mysql)数据库的计算机,Navicat数据库管理工具;学生需掌握SQL基本语法,了解基本的数据库性能概念。",
            "实验操作内容及步骤": "创建索引:使用CREATE INDEX语句创建不同类型索引;性能测试:对比使用索引和不使用索引的查询性能",
            "实验结果与分析总结": "通过实验理解了索引的工作原理,掌握了索引创建方法,并验证了索引对查询性能的显著提升。",
            "指导教师评阅意见和评分": ""
        }
    ]

    # 调用批量处理方法
    processed_reports, total_time = process_all_reports(reports)

    # 打印所有处理后的报告
    print("\n===== 所有处理完成的实验报告 =====")
    for i, report in enumerate(processed_reports, 1):
        print(f"\n----- 第 {i} 份报告 -----")
        for key, value in report.items():
            print(f"{key}:{value}")

    # 打印总耗时
    print(f"\n程序运行总耗时: {time.time() - main_start_time:.2f}秒")
    print(f"批量处理核心耗时: {total_time:.2f}秒")


if __name__ == "__main__":
    main()

 

 我们通过reports = [] # 存储所有实验报告,

 

import time
from showContent import extract_experiment_reports
from report_processor import process_all_reports

def main():
    # 记录整个程序的开始时间
    start_time = time.time()
    
    # 设置文档路径(根据实际情况修改)
    doc_path = "report/华为HCIA-GaussDB应用开发22计科本六21106080900204纪容超.docx"  # 可以是docx、pdf等支持的格式
    print(f"开始处理文档: {doc_path}")
    
    try:
        # 从文档中提取实验报告数据
        reports = extract_experiment_reports(doc_path)
        
        if not reports:
            print("未从文档中提取到任何实验报告数据")
            return
        
        print(f"成功提取 {len(reports)} 份实验报告")
        
        # 批量处理所有实验报告
        processed_reports, total_time = process_all_reports(reports)
        
        # 处理完成后的操作(可根据需要扩展)
        print("\n===== 实验报告处理流程全部完成 =====")
        print(f"总共处理 {len(processed_reports)} 份报告")
        print(f"整个程序运行总耗时: {time.time() - start_time:.2f}秒")
        
        # 这里可以添加保存处理结果到文件的代码
        # 例如保存为JSON文件
        # import json
        # with open("处理完成的实验报告.json", "w", encoding="utf-8") as f:
        #     json.dump(processed_reports, f, ensure_ascii=False, indent=2)
        # print("处理结果已保存到 JSON 文件")
        
    except Exception as e:
        print(f"程序执行过程中发生错误: {str(e)}")
        # 打印详细错误信息便于调试
        import traceback
        traceback.print_exc()

if __name__ == "__main__":
    main()

运行结果:

.....
===== 第 7 份报告处理完成,耗时: 210.81秒 =====

===== 所有报告处理完成!共处理 7 份报告 =====
单份报告平均处理时间: 192.77秒
批量处理总耗时: 557.93秒

....

 

 

 

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值