还在为调用大模型API接口返回数据的处理问题烦恼???来看看这篇文章,解决你的烦恼!!!

大家好!我是学徒小z,今天给大家分享一下我做项目过程中遇到的一个问题。

问题

不知道大家有没有遇到这样一个问题。在调用大模型接口的时,返回的数据总是一大坨,然后再将数据展示再UI界面上,就会显得数据加载很迟钝,用户体验会很不好。那么该如何实现返回的数据可以迅速进行加载并且如同打字一样再UI界面上显示呢?答案就是使用流式返回回调函数来解决这个问题。

在这里插入图片描述

大模型接口

  • 模型:使用的是星火认知大模型
    在这里插入图片描述

  • 使用HTTP协议来进行API接口的访问

  • 大模型接口请求参数举例

    3.2. 请求参数
    {
        "model": "generalv3.5",
        "user": "用户唯一id",
        "messages": [
            {
                "role": "system",
                "content": "你是知识渊博的助理"
            },
            {
                "role": "user",
                "content": "你好,讯飞星火"
            }
        ],
        // 下面是可选参数
        "temperature": 0.5,
        "top_k": 4,
        "stream": false,
        "max_tokens": 1024,
        "presence_penalty": 1,
        "frequency_penalty": 1,
        "tools": [
            {
                "type": "function",
                "function": {
                    "name": "str2int",
                    "description": "将字符串类型转为 int 类型",
                    "parameters": {...} // 需要符合 json schema 格式
                }
            },
            {
                "type": "web_search",
                "web_search": {
                    "enable": true
                }
            }
        ],
        "response_format": {
            "type": "json_object"
        },
        "suppress_plugin": [
            "knowledge"
        ]
    }
    
    参数名称类型是否必传取值范围描述
    modelstringlite generalv3 pro-128k generalv3.5 max-32k 4.0Ultra指定访问的模型版本: lite指向Lite版本; generalv3指向Pro版本; pro-128k指向Pro-128K版本; generalv3.5指向Max版本; max-32k指向Max-32K版本; 4.0Ultra指向4.0 Ultra版本;
    userstring自定义用户的唯一id,表示一个用户,user_123456
    messagesarray输入数组
    messages.rolestringuser assistant system tool角色,user表示用户,assistant表示大模型,system表示命令,tool代表function call执行结果
    messages.contentstring角色对应的文本内容
    temperaturefloat取值范围[0, 2] 默认值1.0核采样阈值
    top_pint取值范围(0, 1] 默认值1生成过程中核采样方法概率阈值,例如,取值为0.8时,仅保留概率加起来大于等于0.8的最可能token的最小集合作为候选集。取值越大,生成的随机性越高;取值越低,生成的确定性越高。
    top_kint取值范围[1, 6] 默认值4从k个中随机选择一个(非等概率)
    presence_penaltyfloat取值范围[-2.0,2.0] 默认0重复词的惩罚值
    frequency_penaltyfloat取值范围[-2.0,2.0] 默认0频率惩罚值
    streambooltrue false是否流式返回结果。默认是false 表示非流式。 如果使用流式,服务端使用SSE的方式推送结果,客户端自己适配处理结果。
    max_tokensintPro、Max、Max-32K、4.0 Ultra 取值为[1,8192],默认为4096; Lite、Pro-128K 取值为[1,4096],默认为4096。模型回答的tokens的最大长度
    response_formatobject指定模型的输出格式
    response_format.typestringtext json_object{ “type”: “json_object” } 指定模型输出json格式 使用 JSON 模式时,请始终指示模型通过对话中的某些消息(例如通过系统或用户消息)生成 JSON
    toolsarray Optionalopenai 新版本参数
    tools.functionobject{“type”:“function”, “function”:{“name”: “my_function”, “description”: “xxx”, “parameters”: {…}}} parameters要符合json schema 描述
    tools.web_searchobject否,默认表示开启{“type”: “web_search”, “web_search”: {“enable”: true}} enable 开关表示是否开启搜索功能,禁用时不会联网搜索, tokens 使用量低
    tool_choicestring or object Optionalauto none required {“type”: “function”, “function”: {“name”: “my_function”}}设置模型自动选择调用的函数: auto:传了tool时默认为auto,模型自动选择调用的函数 none:模型禁用函数调用 required:模型始终选择一个或多个函数进行调用 {“type”: “function”, “function”: {“name”: “my_function”}} :模型强制调用指定函数

解决方案

流式返回和回调函数

  • 调用鸿蒙开发中HTTP中的一个流式返回数据的函数

    on(“dataReceive”)10+

    on(type: “dataReceive”, callback: Callback): void

    订阅HTTP流式响应数据接收事件。

    系统能力:SystemCapability.Communication.NetStack

    参数:

    参数名类型必填说明
    typestring订阅的事件类型,‘dataReceive’。
    callbackAsyncCallback回调函数。
  • 在我的项目中的调用示范代码

  • 基本步骤

    • 初始化了一个空字符串fullContent,用于存储接收到的内容,以及一个httpRequest对象,用于发送HTTP请求。
    • httpRequest对象接收到数据时,会触发dataReceive事件,这里定义了一个事件处理函数,用于处理接收到的数据。
    • 这里创建了一个TextDecoder对象,用于将接收到的ArrayBuffer数据解码为字符串。decodeToStringOptions中的stream: true表示数据是流式传输的。(这里使用的是util工具类中的函数,需要进行导入 import util from ‘@ohos.util’; )
    • 这里将接收到的字符串数据按行分割,然后处理以data:开头的行,这些行包含了服务器发送的JSON数据。解析JSON数据后,如果包含choices字段且不为空,则将其中的内容添加到fullContent中,并调用onUpdate回调函数更新UI(这样就可以实现UI界面数据展示的实时更新)。
    • 这里使用httpRequest对象发送一个POST请求到HttpGet.travelUrl,请求头包含Content-TypeAuthorization,请求体包含一些额外的数据,如modelmax_tokenstop_ktemperaturemessagesmessages是一个包含系统角色和用户内容的数组,用于向服务器请求旅行细节信息。
    • 在请求完成后,无论成功还是失败,都会移除dataReceive事件监听器,并销毁httpRequest对象,释放资源。
    //使用流式请求传输方式
      static async travelDetailGet(context:string, onUpdate: (chunk: string) => void): Promise<string>{
        let fullContent = '';
        let httpRequest = http.createHttp();
        httpRequest.on("dataReceive", (data:ArrayBuffer) => {
          let textDecoderOptions: util.TextDecoderOptions = {
            fatal: false,
            ignoreBOM : true
          }
          let decodeToStringOptions: util.DecodeToStringOptions = {
            stream: true
          }
          let textDecoder = util.TextDecoder.create('utf-8', textDecoderOptions);
          let retStr = textDecoder.decodeToString(new Uint8Array(data), decodeToStringOptions);
    
          const lines = retStr.split('\n');
    
          for (const line of lines)
          {
            if (line.trim().startsWith('data: '))
            {
              const jsonData = line.trim().substring(5);
    
              try {
                const parsedData: StreamResponse2 = JSON.parse(jsonData);
                if (parsedData.choices && parsedData.choices.length > 0)
                {
                  const content = parsedData.choices[0].delta.content;
                  if (content)
                  {
                    fullContent += content;
                    console.log('Received content:', content);
                    onUpdate(content);//调用回调函数,更新UI
                  }
                }
              }catch (e)
              {
                console.log("HttpGet error " + e)
              }
    
            }
          }
        });
    
        try {
          let response = await httpRequest.requestInStream(
            HttpGet.travelUrl,
    
            {
              method: http.RequestMethod.POST,
              header: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${HttpGet.travelPassword}`
              },
              extraData:{
                "model": HttpGet.useTravelModel,
    
                "max_tokens": 1024,
                "top_k": 4,
                "temperature": 0.5,
                "messages": [
                  {
                    "role": "system",
                    "content": "你是一个专业的旅游家。"
                  },
                  {
                    "role": "user",
                    "content": `${context};${this.travelTemplate}`
                  }
                ],
                "stream": true
              }
            }
          );
          console.log("TagTest ", response.toString())
          if (response.toString() === '200') {
            return fullContent;
          } else {
            throw new Error(`HTTP request failed with status ${response.toString()}`);
          }
        }catch (error){
          console.log(error)
        } finally {
          httpRequest.off("dataReceive");
          httpRequest.destroy();
        }
        return "error"
      }
    

另一个问题

  • 在这里不知道大家有没有遇到另一个问题,那就是调用api返回的数据是markdown格式的。那么应该如何处理markdown格式的数据呢

1. 使用web组件

  • 鸿蒙开发支持使用Web组件来展示和处理Markdown格式的数据。Web组件可以嵌入到鸿蒙应用中,通过加载h5页面来解析和渲染Markdown内容。

2. 使用第三方库

  • 鸿蒙开发也可以利用第三方库来处理Markdown格式的数据。
    比如,我是用的就是处理markdown的第三方库lv-markdown-in。
<think>好的,我现在需要帮助用户解决如何使用Airflow实现定时任务来自动拉取数据库的更新数据,并调用大型模型进行数据处理问题。首先,我需要回顾用户提供的参考引用,看看有没有相关的信息可以利用。 用户提供的三个引用中,引用[1]提到Airflow通过Operator构建ETL管道,引用[2]说明Airflow使用Python文件生成DAG,引用[3]提到Airflow可以调度远程脚本和HTTP请求。这些信息都相关,特别是ETL流程和DAG的创建。 接下来,我需要考虑用户的具体需求:定时任务、拉取数据库更新、调用大型模型处理数据。可能的步骤包括: 1. **创建DAG**:用户需要定义一个DAG来安排任务流程,设置定时参数如schedule_interval。 2. **数据库连接**:使用Airflow的数据库钩子(如DbApiHook)或特定数据库的Operator(如PostgresOperator)来连接并查询数据。 3. **检测更新**:可能需要一个PythonOperator来检查数据库中的最新更新时间戳或增量数据。 4. **数据处理**:使用PythonOperator调用大型模型处理数据,这里需要确保模型可以被集成到Airflow任务中,比如通过API调用或直接运行模型脚本。 5. **任务依赖**:设置任务之间的依赖关系,比如先拉取数据,再处理,最后存储结果。 还需要考虑如何安全地管理数据库凭据,使用Airflow的Connections功能会比较合适。另外,大型模型的调用可能需要一定的计算资源,可能需要使用DockerOperator或KubernetesPodOperator来隔离环境。 用户可能需要一个具体的示例代码来参考,所以需要编写一个包含上述步骤的DAG文件。同时,应该提到如何配置连接、安装必要的依赖库,以及可能的性能优化点,比如任务并行化或错误重试机制。 最后,根据用户的要求,生成相关问题,例如如何优化数据处理性能,如何监控任务,或者如何处理模型调用的失败情况。这些问题需要与用户的需求紧密相关,帮助用户进一步深入了解。</think>### 分步教程:使用 Airflow 实现定时拉取数据数据调用大型模型处理 #### 1. **环境准备** - 安装 Airflow 并初始化数据库: ```bash pip install apache-airflow airflow db init airflow users create --username admin --password admin --role Admin --email admin@example.com ``` #### 2. **定义 DAG 结构** 在 `dags/` 目录下创建 Python 文件(如 `etl_with_ml.py`),定义 DAG 及其任务: ```python from datetime import datetime, timedelta from airflow import DAG from airflow.operators.python import PythonOperator from airflow.providers.postgres.hooks.postgres import PostgresHook from airflow.models import Variable # 定义大型模型调用函数(示例) def call_large_model(data): # 这里替换为实际模型调用逻辑(如调用API或本地模型) processed_data = data.upper() # 示例:简单转换 return processed_data # 任务1:从数据库拉取增量数据 def extract_incremental_data(**kwargs): hook = PostgresHook(postgres_conn_id='my_db_conn') # 使用配置好的PostgreSQL连接 sql = "SELECT * FROM source_table WHERE updated_at > '{{ prev_ds }}';" # 基于上次执行时间获取增量 connection = hook.get_conn() cursor = connection.cursor() cursor.execute(sql) data = cursor.fetchall() kwargs['ti'].xcom_push(key='raw_data', value=data) # 将数据传递给下游任务 # 任务2:调用模型处理数据 def process_with_model(**kwargs): raw_data = kwargs['ti'].xcom_pull(key='raw_data') processed_data = call_large_model(raw_data) kwargs['ti'].xcom_push(key='processed_data', value=processed_data) # 任务3:保存处理结果 def load_processed_data(**kwargs): processed_data = kwargs['ti'].xcom_pull(key='processed_data') hook = PostgresHook(postgres_conn_id='my_db_conn') hook.insert_rows(table='result_table', rows=processed_data) # 定义DAG default_args = { 'owner': 'airflow', 'retries': 3, 'retry_delay': timedelta(minutes=5) } with DAG( dag_id='etl_ml_pipeline', default_args=default_args, description='每小时拉取增量数据并通过模型处理', schedule_interval='@hourly', # 每小时执行一次 start_date=datetime(2024, 1, 1), catchup=False ) as dag: extract = PythonOperator( task_id='extract_data', python_callable=extract_incremental_data, provide_context=True ) process = PythonOperator( task_id='process_data', python_callable=process_with_model, provide_context=True ) load = PythonOperator( task_id='load_data', python_callable=load_processed_data, provide_context=True ) extract >> process >> load ``` #### 3. **配置数据库连接** 在 Airflow Web UI 中配置连接: 1. 进入 **Admin > Connections** 2. 添加新连接: - Connection ID: `my_db_conn` - Connection Type: `Postgres` - Host: 数据库IP - Schema: 数据库名称 - Login: 用户名 - Password: 密码 - Port: 5432 #### 4. **扩展优化点** - **增量识别优化**:使用数据库的`last_updated`字段或日志表跟踪增量[^1] - **模型部署集成**: - 若模型为 API 服务,改用 `SimpleHttpOperator` 调用: ```python from airflow.providers.http.operators.http import SimpleHttpOperator process = SimpleHttpOperator( task_id='call_ml_api', endpoint='/predict', method='POST', data="{{ ti.xcom_pull(key='raw_data') }}", response_check=lambda response: response.status_code == 200 ) ``` - 若需 GPU 资源,使用 `KubernetesPodOperator` 在独立容器运行模型 - **错误处理**: - 在 DAG 参数中添加 `on_failure_callback` 实现失败通知 - 使用 `retries` 和 `retry_delay` 自动重试 #### 5. **运行与监控** - 命令行触发测试: ```bash airflow dags test etl_ml_pipeline 2024-01-01 ``` - 在 Web UI 的 **DAGs** 页面查看运行状态和任务日志[^3] ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值