程序调用大模型返回结构化输出(JSON)

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
性能测试 PTS,5000VUM额度
应用实时监控服务-可观测链路OpenTelemetry版,每月50GB免费额度
简介: 本文介绍了如何使用讯飞星火大模型API,并通过Python封装实现结构化数据输出。首先,通过封装SparkAI类,实现了与讯飞星火API的交互,确保了调用的安全性和便捷性。接着,利用Pydantic库定义了数据模型`CalendarEvent`,确保从大模型获取的回答能够被正确解析成预设的结构化JSON格式,从而解决了大模型回答不规范的问题。示例代码展示了如何构造请求、接收并解析响应,最终输出结构化的活动信息。

程序调用大模型返回结构化输出(JSON)

大家很多时候使用langchain、llamaindex等大模型框架的时候,一直很头疼的就是大模型的answer不一定就按照约定的结构化数据返回,那么下面就以讯飞的spark为例解决这个问题

星火模型调用类

按照OpenAI的sdk的格式,封装了讯飞星火的调用类如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
@File    :   SparkApi.py
@Time    :   2024/08/08 15:30:54
@Author  :   CrissChan 
@Version :   1.0
@Site    :   https://blog.csdn.net/crisschan
@Desc    :   按照OpenAI的SDK格式封装的讯飞星火大模型的调用类
'''

import _thread as thread
import base64
import datetime
import hashlib
import hmac
import json
from urllib.parse import urlparse, urlencode
import ssl
from datetime import datetime
from time import mktime
from wsgiref.handlers import format_date_time
import websocket

class SparkAI:
    def __init__(self, appid, api_key, api_secret, spark_url, domain):
        self.appid = appid
        self.api_key = api_key
        self.api_secret = api_secret
        self.spark_url = spark_url
        self.domain = domain
        self.answer = ""

    def _create_url(self):
        # 生成URL的逻辑保持不变
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))

        host = urlparse(self.spark_url).netloc
        path = urlparse(self.spark_url).path

        signature_origin = f"host: {host}\ndate: {date}\nGET {path} HTTP/1.1"
        signature_sha = hmac.new(self.api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
                                 digestmod=hashlib.sha256).digest()
        signature_sha_base64 = base64.b64encode(signature_sha).decode(encoding='utf-8')

        authorization_origin = f'api_key="{self.api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha_base64}"'
        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')

        v = {
            "authorization": authorization,
            "date": date,
            "host": host
        }
        return self.spark_url + '?' + urlencode(v)

    def _on_message(self, ws, message):
        data = json.loads(message)
        code = data['header']['code']
        if code != 0:
            print(f'请求错误: {code}, {data}')
            ws.close()
        else:
            choices = data["payload"]["choices"]
            status = choices["status"]
            content = choices["text"][0]["content"]
            print(content, end="")
            self.answer += content
            if status == 2:
                ws.close()

    def _gen_params(self, question):
        return {
            "header": {"app_id": self.appid, "uid": "1234"},
            "parameter": {
                "chat": {
                    "domain": self.domain,
                    "random_threshold": 0.5,
                    "max_tokens": 2048,
                    "auditing": "default"
                }
            },
            "payload": {
                "message": {
                    "text": [
                        {"role": "user", "content": question}
                    ]
                }
            }
        }

    def chat(self, question):
        self.answer = ""  # 重置答案
        ws_url = self._create_url()
        ws = websocket.WebSocketApp(
            ws_url,
            on_message=self._on_message,
            on_error=lambda ws, error: print("### error:", error),
            on_close=lambda ws, close_status_code, close_msg: print(" "),
            on_open=lambda ws: ws.send(json.dumps(self._gen_params(question)))
        )
        ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
        return self.answer

调用SparkAI返回结构数据

将星火大模型的appid、api_secret、apikey都存放在.env配置文件中,通过dotenv将内容读出来存入变量中(_变量的介绍可以再次文章中参考https://blog.csdn.net/crisschan/article/details/133277855)

from dotenv import load_dotenv, find_dotenv
_=load_dotenv(find_dotenv())
appid = os.getenv("SPARK_APP_ID")
api_secret=os.getenv("SPARK_APP_SECRET")
api_key=os.getenv("SPARK_APP_KEY")

#用于配置大模型版本,默认"general/generalv2"
# domain = "general"   # v1.5版本
domain = "generalv2"    # v2.0版本
#云端环境的服务地址
spark_url = "ws://spark-api.xf-yun.com/v2.1/chat"  # v2.0环境的地址ws(s)://spark-api.xf-yun.com/v2.1/chat
    client = SparkAI(appid=appid, api_key=api_key, api_secret=api_secret, spark_url=spark_url, domain=domain)

下面设计结构化返回的内容如下代码。

import os
from pydantic import BaseModel

# 这个定义创建了一个数据模型,其中:
#name 必须是字符串
#date 必须是字符串
#participants 必须是字符串列表
class CalendarEvent(BaseModel):
        name: str
        date: str
        participants: list[str]

Pydantic是一个用于数据验证和设置管理的 Python 库,BaseModel 是 Pydantic 中的一个核心类,用于创建数据模型。通过继承 BaseModel,可以轻松定义具有类型提示的数据结构,这些模型可以自动验证数据,确保数据符合预期的格式和类型。使用 Pydantic 的 BaseModel 可以更容易地处理和验证从 AI 响应中提取的结构化数据,提高代码的可靠性和可读性。在通过如下代码的约束,就可以收获一个按照格式化好的json。

prompt = """
    系统:提取事件信息。
    用户:Alice和Bob将在周五参加科学展览会。
    请以JSON格式提供以下信息:
    {
        "name": "事件名称",
        "date": "事件日期",
        "participants": ["参与者列表"]
    }
    """

    response = client.chat(prompt)

    try:
        event_dict = json.loads(response)
        event = CalendarEvent(**event_dict)
        print(f"活动名称: {event.name}")
        print(f"日期: {event.date}")
        print(f"参与者: {', '.join(event.participants)}")
    except json.JSONDecodeError:
        print("无法解析响应为JSON格式")
    except Exception as e:
        print(f"处理响应时出错: {str(e)}")

运行后得到如下结果:

 {
  "name": "科学展览会",
  "date": "周五",
  "participants": ["Alice", "Bob"]
}  
活动名称: 科学展览会
日期: 周五
参与者: Alice, Bob
目录
相关文章
|
8天前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
|
11天前
|
存储 人工智能 调度
阿里云吴结生:高性能计算持续创新,响应数据+AI时代的多元化负载需求
在数字化转型的大潮中,每家公司都在积极探索如何利用数据驱动业务增长,而AI技术的快速发展更是加速了这一进程。
|
3天前
|
并行计算 前端开发 物联网
全网首发!真·从0到1!万字长文带你入门Qwen2.5-Coder——介绍、体验、本地部署及简单微调
2024年11月12日,阿里云通义大模型团队正式开源通义千问代码模型全系列,包括6款Qwen2.5-Coder模型,每个规模包含Base和Instruct两个版本。其中32B尺寸的旗舰代码模型在多项基准评测中取得开源最佳成绩,成为全球最强开源代码模型,多项关键能力超越GPT-4o。Qwen2.5-Coder具备强大、多样和实用等优点,通过持续训练,结合源代码、文本代码混合数据及合成数据,显著提升了代码生成、推理和修复等核心任务的性能。此外,该模型还支持多种编程语言,并在人类偏好对齐方面表现出色。本文为周周的奇妙编程原创,阿里云社区首发,未经同意不得转载。
|
8天前
|
人工智能 运维 双11
2024阿里云双十一云资源购买指南(纯客观,无广)
2024年双十一,阿里云推出多项重磅优惠,特别针对新迁入云的企业和初创公司提供丰厚补贴。其中,36元一年的轻量应用服务器、1.95元/小时的16核60GB A10卡以及1元购域名等产品尤为值得关注。这些产品不仅价格亲民,还提供了丰富的功能和服务,非常适合个人开发者、学生及中小企业快速上手和部署应用。
|
18天前
|
自然语言处理 数据可视化 前端开发
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
合合信息的智能文档处理“百宝箱”涵盖文档解析、向量化模型、测评工具等,解决了复杂文档解析、大模型问答幻觉、文档解析效果评估、知识库搭建、多语言文档翻译等问题。通过可视化解析工具 TextIn ParseX、向量化模型 acge-embedding 和文档解析测评工具 markdown_tester,百宝箱提升了文档处理的效率和精确度,适用于多种文档格式和语言环境,助力企业实现高效的信息管理和业务支持。
3939 3
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
|
8天前
|
算法 安全 网络安全
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
2024阿里云11.11金秋云创季活动火热进行中,活动月期间(2024年11月01日至11月30日)通过折扣、叠加优惠券等多种方式,阿里云WoSign SSL证书实现优惠价格新低,DV SSL证书220元/年起,助力中小企业轻松实现HTTPS加密,保障数据传输安全。
518 3
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
|
14天前
|
安全 数据建模 网络安全
2024阿里云双11,WoSign SSL证书优惠券使用攻略
2024阿里云“11.11金秋云创季”活动主会场,阿里云用户通过完成个人或企业实名认证,可以领取不同额度的满减优惠券,叠加折扣优惠。用户购买WoSign SSL证书,如何叠加才能更加优惠呢?
989 3
|
7天前
|
数据采集 人工智能 API
Qwen2.5-Coder深夜开源炸场,Prompt编程的时代来了!
通义千问团队开源「强大」、「多样」、「实用」的 Qwen2.5-Coder 全系列,致力于持续推动 Open Code LLMs 的发展。
|
12天前
|
机器学习/深度学习 存储 人工智能
白话文讲解大模型| Attention is all you need
本文档旨在详细阐述当前主流的大模型技术架构如Transformer架构。我们将从技术概述、架构介绍到具体模型实现等多个角度进行讲解。通过本文档,我们期望为读者提供一个全面的理解,帮助大家掌握大模型的工作原理,增强与客户沟通的技术基础。本文档适合对大模型感兴趣的人员阅读。
441 18
白话文讲解大模型| Attention is all you need
|
12天前
|
存储 分布式计算 流计算
实时计算 Flash – 兼容 Flink 的新一代向量化流计算引擎
本文介绍了阿里云开源大数据团队在实时计算领域的最新成果——向量化流计算引擎Flash。文章主要内容包括:Apache Flink 成为业界流计算标准、Flash 核心技术解读、性能测试数据以及在阿里巴巴集团的落地效果。Flash 是一款完全兼容 Apache Flink 的新一代流计算引擎,通过向量化技术和 C++ 实现,大幅提升了性能和成本效益。
658 10
实时计算 Flash – 兼容 Flink 的新一代向量化流计算引擎