【OpenAI】私有框架代码生成实践

2023-11-05

作者:京东零售 牛晓光

根据现有调研和实践,由OpenAI提供的ChatGPT/GPT-4模型和CodeX模型能够很好的理解和生成业界大多数编程语言的逻辑和代码,其中尤其擅长Python、JavaScript、TypeScript、Ruby、Go、C# 和 C++等语言。

然而在实际应用中,我们经常会在编码时使用到一些私有框架、包、协议和DSL等。由于相关模型没有学习最新网络数据,且这些私有数据通常也没有发布在公开网络上,OpenAI无法根据这些私有信息生成对应代码。

一、OpenAI知识学习方式

OpenAI提供了几种方式,让OpenAI模型学习私有知识:

1. 微调模型

OpenAI支持基于现有的基础模型,通过提供“prompt - completion”训练数据生成私有的自定义模型。

使用方法

在执行微调工作时,需要执行下列步骤:

1. 准备训练数据:数据需包含prompt/completion,格式支持CSV, TSV, XLSX, JSON等。

  • 格式化训练集:openai tools fine_tunes.prepare_data -f <LOCAL_FILE>
  • LOCAL_FILE:上一步中准备好的训练数据。

2. 训练模型微调:openai api fine_tunes.create -t <LOCAL_FILE> -m <BASE_MODULE> --suffix "<MODEL_SUFFIX>"

  • LOCAL_FILE:上一步中准备好的训练集。
  • BASE_MODULE:基础模型的名称,可选的模型包括adababbagecuriedavinci等。
  • MODEL_SUFFIX:模型名称后缀。

3. 使用自定义模型

使用成本

在微调模型方式中,除了使用自定义模型进行推理时所需支付的费用外,训练模型时所消耗的Tokens也会对应收取费用。根据不同的基础模型,费用如下:

结论

使用微调模型进行私有知识学习,依赖于大量的训练数据,训练数据越多,微调效果越好。
此方法适用于拥有大量数据积累的场景。

2. 聊天补全

GPT模型接收对话形式的输入,而对话按照角色进行整理。对话数据的开始包含系统角色,该消息提供模型的初始说明。可以在系统角色中提供各种信息,如:

  • 助手的简要说明

  • 助手的个性特征

  • 助手需要遵循的指令或规则

  • 模型所需的数据或信息

我们可以在聊天中,通过自定义系统角色为模型提供执行用户指令所必要的私有信息。

使用方法

可以在用户提交的数据前,追加对私有知识的说明内容。

openai.createChatCompletion({
  model: "gpt-3.5-turbo",
  messages: [
    { role: "system", content: "你是一款智能聊天机器人,帮助用户回答有关内容管理系统低代码引擎CCMS的技术问题。智能根据下面的上下文回答问题,如果不确定答案,可以说“我不知道”。\n\n" +
      "上下文:\n" + 
      "- CCMS通过可视化配置方式生成中后台管理系统页面,其通过JSON数据格式描述页面信息,并在运行时渲染页面。\n" + 
      "- CCMS支持普通列表、筛选列表、新增表单、编辑表单、详情展示等多种页面类型。\n" + 
      "- CCMS可以配置页面信息、接口定义、逻辑判断、数据绑定和页面跳转等交互逻辑。"
    },
    { role: "user", content: "CCMS是什么?" }
  ]
}).then((response) => response.data.choices[0].message.content);


使用成本

除了用户所提交的内容外,系统角色所提交的关于私有知识的说明内容,也会按照Tokens消耗量进行计费。

结论

使用聊天补全进行私有知识学习,依赖于系统角色的信息输入,且此部分数据的Tokens消耗会随每次用户请求而重复计算。

此方法适用于私有知识清晰准确,且内容量较少的场景。

二、私有知识学习实践

对于私有框架、包、协议、DSL等,通常具备比较完善的使用文档,而较少拥有海量的用户使用数据,所以在当前场景下,倾向于使用聊天补全的方式让GPT学习私有知识。

而在此基础上,如何为系统角色提供少量而精确的知识信息,则是在保障用户使用情况下,节省使用成本的重要方式。

3. 检索-提问解决方案

我们可以在调用OpenAI提供的Chat服务前,使用用户所提交的信息对私有知识进行检索,筛选出最相关的信息,再进行Chat请求,检索Tokens消耗。

而OpenAI所提供的嵌入(Embedding)服务则可以解决检索阶段的工作。

使用方法

1. 准备搜索数据(一次性)

  • 收集:准备完善的使用文档。如:https://jd-orion.github.io/docs

  • 分块:将文档拆分为简短的、大部分是独立的部分,这通常是文档中的页面或章节。

  • 嵌入:为每一个分块分别调用OpenAI API生成Embedding。

await openai.createEmbedding({
  model: "text-embedding-ada-002",
  input: fs.readFileSync('./document.md', 'utf-8').toString(),
}).then((response) => response.data.data[0].embedding);


  • 存储:保存Embedding数据。(对于大型数据集,可以使用矢量数据库)

2. 检索(每次查询一次)

  • 为用户的提问,调用OpenAI API生成Embedding。(同1.3步骤)

  • 使用提问Embedding,根据与提问的相关性对私有知识的分块Embedding进行排名。

const fs = require('fs');
const { parse } = require('csv-parse/sync');
const distance = require( 'compute-cosine-distance' );

function (input: string, topN: number) {
  const knowledge: { text: string, embedding: string, d?: number }[] = parse(fs.readFileSync('./knowledge.csv').toString());

  for (const row of knowledge) {
    row.d = distance(JSON.parse(row.embedding), input)
  }

  knowledge.sort((a, b) => a.d - b.d);

  return knowledge.slice(0, topN).map((row) => row.text));
}


3. 提问(每次查询一次)

  • 给请求的系统角色插入与问题最相关的信息
async function (knowledge: string[], input: string) {
  const response = await openai.createChatCompletion({
    model: "gpt-3.5-turbo",
    messages: [
      {
        role: 'system',
        content: "你是一款智能聊天机器人,帮助用户回答有关内容管理系        统低代码引擎CCMS的技术问题。\n\n" + knowledge.join("\n")
      },
      {
        role: 'user',
        content: input
      }
    ]
  }).then((response) => response.data.choices[0].message.content);
  return response
}


  • 返回GPT的答案

使用成本

使用此方法,需要一次性的支付用于执行Embedding的费用。

三、低代码自然语言搭建案例

解决了让GPT学习私有知识的问题后,就可以开始使用GPT进行私有框架、库、协议和DSL相关代码的生成了。

本文以低代码自然语言搭建为例,帮助用户使用自然语言对所需搭建或修改的页面进行描述,进而使用GPT对描述页面的配置文件进行修改,并根据返回的内容为用户提供实时预览服务。

使用方法

OpenAI调用组件

const { Configuration, OpenAIApi } = require("openai");
const openai = new OpenAIApi(new Configuration({ /** OpenAI 配置 */ }));
const distance = require('compute-cosine-distance');
const knowledge: { text: string, embedding: string, d?: number }[] = require("./knowledge")

export default function OpenAI (input, schema) {
  return new Promise((resolve, reject) => {
    // 将用户提问信息转换为Embedding
    const embedding = await openai.createEmbedding({
      model: "text-embedding-ada-002",
      input,
    }).then((response) => response.data.data[0].embedding);
    
    // 获取用户提问与知识的相关性并排序
    for (const row of knowledge) {
      row.d = distance(JSON.parse(row.embedding), input)
    }
    knowledge.sort((a, b) => a.d - b.d);
    
    // 将相关性知识、原始代码和用户提问发送给GPT-3.5模型
    const message = await openai.createChatCompletion({
      model: "gpt-3.5-turbo",
      messages: [
        {
          role: 'system',
          content: "你是编程助手,需要阅读协议知识,并按照用户的要求修改代码。\n\n" + 
                  "协议知识:\n\n" +
                  knowledge.slice(0, 10).map((row) => row.text).join("\n\n") + "\n\n" + 
                  "原始代码:\n\n" +
                  "```\n" + schema + "\n```"
        },
        {
          role: 'user',
          content: input
        }
      ]
    }).then((response) => response.data.choices[0].message.content);

      // 检查返回消息中是否包含Markdown语法的代码块标识
    let startIndex = message.indexOf('```');
    if (message.substring(startIndex, startIndex + 4) === 'json') {
      startIndex += 4;
    }

    if (startIndex > -1) {
      // 返回消息为Markdown语法
      let endIndex = message.indexOf('```', startIndex + 3);
      let messageConfig;

      // 需要遍历所有代码块
      while (endIndex > -1) {
        try {
          messageConfig = message.substring(startIndex + 3, endIndex);

          if (
            /** messageConfig正确性校验 */
          ) {
            resolve(messageConfig);
            break;
          }
        } catch (e) {
          /* 本次失败 */
        }

        startIndex = message.indexOf('```', endIndex + 3);

        if (message.substring(startIndex, startIndex + 4) === 'json') {
          startIndex += 4;
        }

        if (startIndex === -1) {
          reject(['OpenAI返回的信息不可识别:', message]);
          break;
        }

        endIndex = message.indexOf('```', startIndex + 3);
      }
    } else {
      // 返回消息可能为代码本身
      try {
        const messageConfig = message;

        if (
          /** messageConfig正确性校验 */
        ) {
          resolve(messageConfig);
        } else {
          reject(['OpenAI返回的信息不可识别:', message]);
        }
      } catch (e) {
        reject(['OpenAI返回的信息不可识别:', message]);
      }
    }
  })
}


低代码渲染

import React, { useState, useEffect } from 'react'
import { CCMS } from 'ccms-antd'
import OpenAI from './OpenAI'

export default function App () {
  const [ ready, setReady ] = useState(true)
  const [ schema, setSchema ] = useState({})

  const handleOpenAI = (input) => {
    OpenAI(input, schema).then((nextSchema) => {
      setReady(false)
      setSchema(nextSchema)
    })
  }

  useEffect(() => {
    setReady(true)
  }, [schema])

  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      {ready && (
        <CCMS
          config={pageSchema}
          /** ... */
        />
      )}
      <div style={{ position: 'fixed', right: 385, bottom: 20, zIndex: 9999 }}>
        <Popover
          placement="topRight"
          trigger="click"
          content={
            <Form.Item label="使用OpenAI助力搭建页面:" labelCol={{ span: 24 }}>
              <Input.TextArea
                placeholder="请在这里输入内容,按下Shift+回车确认。"
                defaultValue={defaultPrompt}
                onPressEnter={(e) => {
                  if (e.shiftKey) {
                    handleOpenAI(e.currentTarget.value)
                  }
                }}
              />
            </Form.Item>
          }
        >
          <Button shape="circle" type="primary" icon={ /** OpenAI icon */ } />
        </Popover>
      </div>
    </div>
  )
}


四、信息安全

根据OpenAI隐私政策说明,使用API方式进行数据访问时:

  1. 除非明确的授权,OpenAI不会使用用户发送的数据进行学习和改进模型。
  2. 用户发送的数据会被OpenAI保留30天,以用于监管和审查。(有限数量的授权OpenAI员工,以及负有保密和安全义务的专业第三方承包商,可以访问这些数据)
  3. 用户上传的文件(包括微调模型是提交的训练数据),除非用户删除,否则会一直保留。

另外,OpenAI不提供模型的私有化部署(包括上述微调模型方式所生成的自定义模型),但可以通过联系销售团队购买私有容器。

文中所使用的训练数据、私有框架知识以及低代码框架均源自本团队开发并已开源的内容。用户使用相关服务时也会进行数据安全提示。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【OpenAI】私有框架代码生成实践 的相关文章

  • 文盘Rust -- 给程序加个日志

    日志是应用程序的重要组成部分 无论是服务端程序还是客户端程序都需要日志做为错误输出或者业务记录 在这篇文章中 我们结合log4rs聊聊rust 程序中如何使用日志 log4rs类似java生态中的log4j 使用方式也很相似 log4rs中
  • ChatGPT介绍世界杯历史与编写足球游戏python程序

    ChatGPT聊天机器人最近非常流行 是由OpenAI于本月发布的 花了一点时间注册了一个账号 如有需要帮助注册的可以随时与我交流 注册过程相对有一些复杂 除了常规的聊天对话功能之外 ChatGPT聊天机器具备强大的文本生成能力 例如博客
  • chatGPT之Python API启用上下文管理

    chatGPT已经爆火一段时间了 我想大多数的开发者都在默默的在开发和测试当中 可能也是因为这个原因所以现在很难找到关于开发中遇到的一些坑或者方法和技巧 为什么别人的机器人能联想之前的语料 而你的却像个每次都只如初见的高冷机器人 我也是参考
  • [OPENAI2021力作][CLIP: Connecting Text and Images]

    本文翻译自OpenAI官方博客 1 于2021年1月5日发布 0 前言 本博客是openAI的大佬们的全新作品 其提出了可以用于从自然语言监督信号中有效提取视觉信息的 名为CLIP的神经网络 CLIP可以被用于任何视觉分类的benchmar
  • 【实践篇】DDD脚手架及编码规范

    一 背景介绍 我们团队一直在持续推进业务系统的体系化治理工作 在这个过程中我们沉淀了自己的DDD脚手架项目 脚手架项目是体系化治理过程中比较重要的一环 它的作用有两点 1 可以对新建的项目进行统一的规范 2 对于指导老项目进行DDD的改造提
  • finetune一个GPT3模型

    过程其实挺简单的 首先得注册一个账号获取token 我是叫在美国的朋友注册了一个 注册好账号后 有18美金的试用额度 基本可以完成好几次模型训练了 除了模型训练需要收费之外 大概1000个token的费用是0 02美金 设置好OPENAI
  • AI绘画调用OpenAI-api接口【人工智能里的未来之城】:4 座未来派塔楼,天桥上覆盖着茂密的树叶,数字艺术

    OpenAI绘画数字艺术是一种利用人工智能算法生成数字艺术的技术 该技术使用了一种称为GAN Generative Adversarial Networks 生成对抗网络 的深度学习模型 这种模型由两个神经网络组成 生成器和判别器 生成器的
  • 文盘Rust -- 生命周期问题引发的 static hashmap 锁

    2021年上半年 撸了个rust cli开发的框架 基本上把交互模式 子命令提示这些cli该有的常用功能做进去了 项目地址 https github com jiashiwen interactcli rs 春节以前看到axum已经0 4
  • “我永远都无法理解人类!” OpenAI “杀”死了那个成功模拟已故未婚妻的 GPT-3 机器人

    逝者已矣 生者如斯 意为死去的人已离我们而去 活着的人要好好生活 可人非圣贤 明知不可拘泥于过去 却总会在深夜不禁回想起过往的美好 并在心里说一句 我真的好想你 但已故之人如何能听到 只能天一亮 便压下心中思念 再次开启新的一天 如此日复一
  • 【OpenAI】ChatGPT函数调用(Function Calling)实践

    6月13日OpenAI在Chat Completions API中添加了新的函数调用 Function Calling 能力 帮助开发者通过API方式实现类似于ChatGPT插件的数据交互能力 本文在作者上一篇文章 私有框架代码生成实践 的
  • 万字长文详述ClickHouse在京喜达实时数据的探索与实践

    1 前言 京喜达技术部在社区团购场景下采用JDQ Flink Elasticsearch架构来打造实时数据报表 随着业务的发展 Elasticsearch开始暴露出一些弊端 不适合大批量的数据查询 高频次深度分页导出导致ES宕机 不能精确去
  • 谁在成为产业经济发展的推车人?

    区域发展的新蓝图中 京东云能做什么 它的角色是什么 这个问题背后 隐藏的不仅是京东云自身的能力和价值 更是其作为中国互联网云厂商的代表之一 对 技术 产业 的新论证 作者 皮爷 出品 产业家 关于云厂商 外界更多的认知是在技术和产品层面 不
  • 撮合前端平台在低代码平台的落地实践

    在京东技术的发展当下 不同的业务线 不同的区域 甚至于很多触达消费者的端 正在被中台架构能力所支撑 大家都很清楚 中台建设能够带来技术的规模化效应 具有提高业务协同 加速创新和交付速度 提高系统稳定性和可靠性 降低成本和支持业务快速发展等优
  • 文盘Rust -- tonic-Rust grpc初体验

    gRPC 是开发中常用的开源高性能远程过程调用 RPC 框架 tonic 是基于 HTTP 2 的 gRPC 实现 专注于高性能 互操作性和灵活性 该库的创建是为了对 async await 提供一流的支持 并充当用 Rust 编写的生产系
  • 弹性数据库连接池探活策略调研(二)——Druid

    前言 在上一篇文章中 我们介绍了弹性数据库连接失效的背景 并探讨了HikariCP连接池探活策略的相关内容 在本文中 我们将会继续探讨另一个线上常用的连接池 Druid 并为您介绍如何在使用Druid时实现最佳实践的弹性数据库连接池探活策略
  • chatglm2-6b在P40上做LORA微调

    背景 目前 大模型的技术应用已经遍地开花 最快的应用方式无非是利用自有垂直领域的数据进行模型微调 chatglm2 6b在国内开源的大模型上 效果比较突出 本文章分享的内容是用chatglm2 6b模型在集团EA的P40机器上进行垂直领域的
  • Velocity不用愁!Velocity系统的前端工程化之路

    Velocity是一个基于Java的Web页面模版引擎 十多年前 Velocity将Java代码从Web页面中分离出来 使得开发者能够并行网页开发和Java开发 随着十年前后端分离的浪潮涌动 回首再面对这些基于Velocity的旧系统 无论
  • 从好玩到好用:程序员用AI提效的那些事儿

    本片内容是 AI思维空间 ChatGPT纵横编程世界 点亮智慧火花的续作 主要记录组内开发小伙伴儿们在开发过程中的实际应用案例 记录典型案例 尽量不要和其他人重复 以解决开发过程中的实际问题为主 设计 方案 编码 测试 集成 部署等等 目的
  • @ControllerAdvice注解使用及原理探究

    最近在新项目的开发过程中 遇到了个问题 需要将一些异常的业务流程返回给前端 需要提供给前端不同的响应码 前端再在次基础上做提示语言的国际化适配 这些异常流程涉及业务层和控制层的各个地方 如果每个地方都写一些重复代码显得很冗余 然后查询解决方
  • 从云到「链」,京东云成为中国第四朵云背后

    在产业加速到数实融合加速的今年 云计算不再是云厂商的唯一考校指标 作者 叶子 出品 产业家 京东云再次破圈 信号来自接连发布的几份报告 在国际权威研究机构Forrester发布的名为 The Forrester Wave Public Cl

随机推荐

  • 在Visual Sutdio 2017中使用boost库

    对C 有一定了解的同学一定听说过boost库 这是C 的一个著名类库 在C 的地位感觉可以和Spring在Java中相比 boost向来有准标准库之称 很多新特性例如智能指针等都是先在boost中实现 后来被吸收到标准库之中 而且boost
  • WDS1期第12课 字符设备驱动 7 async异步通知用户空间 驱动代码的kill_fasync函数通知用户的signal函数 fcntl

    前面的query interrupt poll都需要用户程序去主动去读或查询 async异步通知 可以由驱动程序主动去通知用户程序中断的到来 信号也可以通知TASK INTERRUPTIBLE的进程 SIGKILL可以杀掉任何进程 就是传说
  • javascript之数据遍历

    JavaScript之数据遍历 for循环 var a 沐水莲心 22 男 for var i 0 i
  • WIFI 信道 channel

    5GHz 信道划分 国内室内AP可用36 40 44 48 52 56 60 64 149 153 157 161 165等13个信道 2 4GHz 共有14个信道 国内可用1 13信道 不干扰的仅1 6 11
  • Linux多线程

    全文目录 线程概念 线程缺点 线程的如何看待进程内部的资源 进程vs线程 线程控制 pthread库 pthread t 线程创建 线程等待 线程分离 线程退出 总结 线程互斥 互斥量接口 互斥量实现原理 总结 线程安全与可重入 常见的线程
  • CMake应用:基础篇

    CMake是一个开源 跨平台的编译 测试和打包工具 它使用比较简单的语言描述编译 安装的过程 输出Makefile或者project文件 再去执行构建 在使用IDE开发软件的过程中 代码的编译和构建一般是使用IDE自带的编译工具和环境进行编
  • 什么是面向接口编程、面向过程编程、面向对象编程?

    1 什么是面向接口编程 IOP 面向接口编程 Interface Oriented Programming IOP 是一种编程思想 接口作为实体抽象出来的一种表现形式 用于抽离内部实现进行外部沟通 最终实现内部变动而不影响外部与其他实现交互
  • (毕业设计资料)基于STM32智能窗帘控制系统设计

    096 电路方案 基于STM32智能窗帘控制系统设计 基于STM32单片机的智能窗帘控制系统 该系统集蓝牙遥控 人声识别控制 空调红外遥控 24c02数据储存 433m遥控 热释电红外感应 温湿度检测以及光控为一体 并可根据需求设置窗帘开合
  • Java中的内存泄漏例子以及对应解决方案

    转自How Memory Leaks Happen in a Java Application 英语好的可以去原网站瞅瞅 1 什么是Java中的内存泄漏 内存泄漏的标准定义是当应用程序不再使用对象 但垃圾回收器无法将它们从工作内存中删除时发
  • 【上拉下拉功能】GPIO的上拉下拉功能说明

    GPIO的上拉下拉功能说明 2011 07 11 14 36 394人阅读 评论 0 收藏 举报 The port pull up register controls the pull up resister enable disable
  • 华为校招机试题-查找单入口空闲区域-2023年

    题目描述 给定一个 m x n 的矩阵 由若干字符 X 和 O 构成 X 表示该处已被占据 O 表示该处空闲 请找到最大的单入口空闲区域 解释 空闲区域是由连通的 O 组成的区域 位于边界的 O 可以构成入口 单入口空闲区域即有且只有一个位
  • 【华为OD机试】返回矩阵中非1的元素个数(C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 语言限定 C clang11 C clang 11 Pascal fpc 3 0 2 Java jav
  • UID卡、CUID卡、FUID卡的区别

    UID卡 国外称GEN1 所有区块可被重复读写 卡片ID可改且使用后门指令更改ID ID可被重复修改 响应后门指令 意味着可被使用后门指令检测是否为克隆卡的机器发现 CUID卡 国外称GEN2 所有区块可被重复读写 卡片ID可改且使用普通写
  • stm32 串口发送和接收

    串口发送 include stm32f10x h Device header include
  • HTML+CSS 旋转照片墙!源代码(简易动画干货快收藏!!)

    拿走请三连 并注明出处 新手上路 路过的大佬请多多指教 动画特效为11张照片 环绕着旋转 照片可自改添加 源代码中用到的照片未上传
  • 本地上传文件到FastDFS命令上传报错:ERROR - file: connection_pool.c, line: 142, connect to server 192.168.0.197:221

    root ubuntu etc fdfs usr bin fdfs upload file etc fdfs client conf etc a jpg 2019 12 03 11 38 14 ERROR file connection p
  • MySQL学习(十七):数据类型之文本字符串类型

    文本字符串类型 类型 值的长度 长度范围 占用的存储空间 CHAR M M 0 lt M lt 255 M个字节 VARCHAR M M 0 lt M lt 65535 实际长度 1个字节 TINYTEXT L 0 lt L lt 255
  • 如何使用BBP公式直接计算π的第n位

    使用BBP公式可以直接求得十六进制 的第n位而不需要计算前n位的数 讲道理 我认为是可以计算十进制的第n位的 毕竟其本身就能直接计算出十进制的 但我没试 其优点在于可以进行分布式计算 即将一个耗时的运算拆分成若干个运算单元在不同的机器上进行
  • 芯片可靠性与商规、工规、车规

    在芯片的国产化浪潮下 国产芯片的出货量和替代率近年来迅速飙升 按出货量比率看 消费电子领域 电源管理芯片和射频前端芯片国产替代率已超过70 工控通信领域 电源管理和信号链芯片国产替代率也超过20 汽车电子领域 电源管理和功率器件的国产替代率
  • 【OpenAI】私有框架代码生成实践

    作者 京东零售 牛晓光 根据现有调研和实践 由OpenAI提供的ChatGPT GPT 4模型和CodeX模型能够很好的理解和生成业界大多数编程语言的逻辑和代码 其中尤其擅长Python JavaScript TypeScript Ruby