android集成百度文心一言实现对话功能,实战项目讲解,人人都能拥有一款ai应用

news2024/11/26 4:54:14

大家好,今天给大家讲解下如何实现一个基于百度文心一言的app功能,app内部同时集成了讯飞的语音识别。本文适用于有android基础的小伙伴阅读,文章末尾放上本项目用到的全部实例代码,在使用前请务必看完本文章。

先来给大家看看效果。

百度文心一言API权限申请及创建应用

第一步:打开百度文心一言的api开发者平台-千帆

百度智能云千帆大模型平台ModelBuilder

第二步:创建应用

第三步:打开android studio创建一个app

这个步骤相信大家都会,不会的就说明不适合本篇文章,可以退出阅读了。

第四步:文心一言api封装实例(从项目中提取出来的)

下面代码封装了整个文心一言的对话请求,此处用的基类,为了方便如果有不同的请求需要。

AiExample.java

/**
**封装文心一言请求
**/
public abstract class AiExample {
    Context mContext;
    static List<ChatWxyyRequestBean> chatWxyyRequestBeanList = new ArrayList<>();//用于存储文心一言的对话list

    public AiExample(Context context) {
        this.mContext = context;
    }

    private static final String API_URL_35 = Const.OpenAi.url35;
    private static final String API_URL_40 = Const.OpenAi.url40;

    private List<String> dialogHistory = new ArrayList<>();


    //定义个OkHttpClient对象
    static OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(1, TimeUnit.DAYS)
            .readTimeout(1, TimeUnit.DAYS)
            .callTimeout(1, TimeUnit.DAYS)
            .build();

    private String context = ""; // 当前的对话上下文

    /**
     * 将当前的上下文清空,开启新对话时用到
     *
     * @param chatGptExample
     */
    public void clearContext(AiExample chatGptExample) {
        if (chatGptExample != null) {
            chatGptExample.context = "";
            chatWxyyRequestBeanList.clear();
        }
    }


    //第一次请求回调
    public interface FirstCallback {
        public void callback(String msg);
    }

    /**
     * 请求文心一言
     *
     * @param message 请求的文字
     * @param tag
     */
    public void startChatWithWxyy(String message, int tag, String API_KEY, String SECRET_KEY) {

        //开始第一次请求
        try {
            getAccessToken(API_KEY, SECRET_KEY, new FirstCallback() {
                @Override
                public void callback(String msg) {
                    //第一次请求成功后,获取的msg为access_token
                    Log.e("tag", "文心一言的access_token=" + msg);
                    if (!StringUtils.isBlank(msg)) {
                        //开始进行第二次请求
                        try {
                            Log.e("tag", "第二次请求的messsge:" + message);
                            requestSecond(msg, message);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 从用户的AK,SK生成鉴权签名(Access Token)
     *
     * @param API_KEY
     * @param SECRET_KEY
     * @return 鉴权签名(Access Token)
     * @throws IOException IO异常
     */
    public void getAccessToken(String API_KEY, String SECRET_KEY, FirstCallback firstCallback) throws IOException {
        final String[] access_token = {""};
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create("grant_type=client_credentials&client_id=" + API_KEY
                + "&client_secret=" + SECRET_KEY, mediaType);
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/oauth/2.0/token")
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                Log.e("tag", "获取access token 失败");
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                JSONObject jsonObject = JSONObject.parseObject(response.body().string());
                String access_token1 = jsonObject.getString("access_token");
                if (!StringUtils.isBlank(access_token1)) {
                    access_token[0] = access_token1;
                    firstCallback.callback(access_token[0]);
                    Log.e("tag", "获取access token==" + access_token[0]);
                }
            }
        });

    }

    public void requestSecond(String access_token, String message) throws IOException {
        Gson gson = new Gson();
        ChatWxyyRequestBean chatWxyyRequestBean = new ChatWxyyRequestBean();
        chatWxyyRequestBean.setRole("user");
        chatWxyyRequestBean.setContent(message);
        ChatWxyyBodyBean chatWxyyBodyBean = new ChatWxyyBodyBean();
        chatWxyyRequestBeanList.add(chatWxyyRequestBean);
        chatWxyyBodyBean.setMessages(chatWxyyRequestBeanList);
        chatWxyyBodyBean.setTemperature(0.95);
        chatWxyyBodyBean.setTop_p(0.8);
        chatWxyyBodyBean.setPenalty_score(1);
        chatWxyyBodyBean.setDisable_search(false);
        chatWxyyBodyBean.setEnable_citation(false);
        chatWxyyBodyBean.setResponse_format("text");
        chatWxyyBodyBean.setStream(true);//支持流式输出
        String jsonStr = gson.toJson(chatWxyyBodyBean);//比如将对话对话打包{\"messages\":[{\"role\":\"user\",\"content\":\"你好\"}]}
        Log.e("tag", "构造的json数据:" + jsonStr);
//        设置请求头
        MediaType mediaType = MediaType.parse("application/json;charset=utf-8");
        RequestBody requestBody = RequestBody.create(jsonStr, mediaType);
        Request request = null;
        Log.e("tag", "这里是getAccessToken(API_KEY,SECRET_KEY)==" + access_token);

        request = new Request.Builder()
                .url("https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-8k-0205?access_token=" + access_token)
                .method("POST", requestBody)
                .addHeader("Content-Type", "application/json")
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                //Failed callback
                callback.onFailed("请求失败的原因:" + e.getMessage());
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                if (!response.isSuccessful()) {
                    throw new IOException("Unexpected code " + response);
                } else {
                    StringBuffer sb = new StringBuffer();
                    BufferedReader bf = new BufferedReader(response.body().charStream());
                    String line;
                    while ((line = bf.readLine()) != null) {
                        if (line.equals("")) {
                            continue;
                        }
                        // 提取JSON字符串(去掉"data: "前缀)
                        String jsonString = line.substring(line.indexOf(':') + 1).trim();//直接提取后面的{}内的字符串,data: {"id":"as-vdb8b44zzu","object":"chat.completion","created":1717511275,"sentence_id":0,"is_end":false,"is_truncated":false,"result":"你好,","need_clear_history":false,"finish_reason":"normal","usage":{"prompt_tokens":1,"completion_tokens":0,"total_tokens":1}}
                        JSONObject jsonObject = JSON.parseObject(jsonString);
                        // 获取result字段的值
                        String ret = jsonObject.getString("result");
                        sb.append(ret);
                        handleUI(callback,sb.toString());
//                        callback.onSuccess(sb.toString());//将获取到result字符串回调给homefragment中

                    }
                    handleContent(callback,sb.toString());
                }
            }
        });


    }

    /**
     * 处理获取到ai结果的后续
     * @param callback
     * @param result
     */
    public abstract void handleContent(AiExample.ICallback callback,String result);//

    /**
     * 处理获取到ai结果后的UI更新
     * @param callback
     * @param result
     */
    public abstract void handleUI(AiExample.ICallback callback,String result);


    //----------------------------------------------------分割线---------------------------------------------------------

    /**
     *回调接口,向外暴露回调信息,比如让activity,或者fragment继承此接口,然后设置接口就可以
     */
    public interface ICallback {
        public void onSuccess(String s);

        public void onFailed(String errMsg);
    }

    ICallback callback;

    public void setListener(ICallback callback) {
        this.callback = callback;
    }



}

第五步:如何调用封装类方法实现文心一言请求。

5.1.继承父类AiExample。

如下所示:

WXYYService.java

public class WXYYService extends AiExample{
    public WXYYService(Context context) {
        super(context);
    }

    @Override
    public void handleContent(ICallback callback,String result) {
        if(callback!=null){
            callback.onSuccess(TextReplaceUtils.replaceText(result));//将获取到result字符串回调给homefragment中
            //将回复的内容作为下次请求的参数
            ChatWxyyRequestBean chatWxyyRequestBean1 = new ChatWxyyRequestBean();
            chatWxyyRequestBean1.setRole("assistant");
            chatWxyyRequestBean1.setContent(result.toString());
            chatWxyyRequestBeanList.add(chatWxyyRequestBean1);
            //这里直接把生成的文章存储到数据库中,如果不是用于展示对话的记录,下面这段可以不需要
            String title = ArticleUtils.convertArticleTitle(TextReplaceUtils.replaceText(result));//获取文章标题
            String content = ArticleUtils.convertArticleContent(TextReplaceUtils.replaceText(result));//获取文章内容
            ArticleHistoryBean articleHistoryBean = new ArticleHistoryBean();
            articleHistoryBean.setArticle_title(title);
            articleHistoryBean.setArticle_content(content);
            new ArticleHistoryDao().insert(articleHistoryBean);
        }
    }

    @Override
    public void handleUI(ICallback callback, String result) {
        if(callback!=null){
            callback.onSuccess(result);
        }
    }


}

5.2如何使用调用请求

关键代码:创建一个封装好的业务对象

 chatGptExample = new WXYYService(getActivity());//new 一个WXYYService对象

继承回调接口:

public class HomeFragment extends Fragment implements View.OnClickListener, View.OnTouchListener, AiExample.ICallback {

回调设置好了以后设置监听对象,用于文心一言的返回文本供UI显示

        chatGptExample.setListener(this);//设置监听器,为了回调显示UI

在回调接口中更新你的UI信息,需要在UI线程中:

 @Override
    public void onSuccess(String data) {
        Log.e("tag", "进入回调监听成功");
        chatMsgList.get(chatMsgList.size() - 1).setContent(data);//将流对象拼接字符串到显示框中
        try {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (chatMsgList != null && data != null) {
//                        chatAdapter.notifyItemInserted(chatMsgList.size() - 1);
//                        chatAdapter.notifyItemChanged(chatMsgList.size() - 1);//当有新消息时,刷新RecyclerView中的显示
                        chatAdapter.notifyDataSetChanged();
                        chatAdapter.notifyItemRangeChanged(0, chatMsgList.size());
                        linearLayoutManagerWrap.setStackFromEnd(true);
                        recyclerView.setLayoutManager(linearLayoutManagerWrap);
                        recyclerView.scrollToPosition(chatMsgList.size() - 1);//将RecyclerView定位到最后一行
                        editText.setText("");
                        showContent(data);//显示界面
                    }

                }
            });
        } catch (Exception e) {

        }

    }

文章最后打包本实例中的代码,需要的朋友自行下载:

项目参考代码打包点击下载:项目下载

如果遇到开发问题需要解答的,请看我的主页个性签名,先跟大家说声道歉,私信或者留言我基本没怎么留意看。

好了,写到这里就结束了,希望大家都能开发属于自己的文心一言对话app。假如大家不想做成太麻烦的对话形式的话,那也很简单,做一个简单的界面,包括一个点击发送的button,一个接受对话结果的textview,一个对话输出框EditText就可以了。把请求得到的数据显示在textview上就可以了。

网创有方论坛icon-default.png?t=N7T8http://www.wcyf520.cn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1805737.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鲜为人知的英伟达创始人:早早退出,身价不如黄仁勋零头

内容提要 普里姆因为婚姻纠纷等个人生活的干扰无法专注在工作上&#xff0c;在成立公司的10年后&#xff0c;也就是2003年宣布退休离开英伟达&#xff0c;并在2006年出售剩余的所有英伟达股份&#xff0c;过上不与外界联系、离群索居的生活&#xff0c;在家中鼓捣着如何“拯救…

【深度学习】深度学习之巅:在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境

【深度学习】深度学习之巅&#xff1a;在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境 大家好 我是寸铁&#x1f44a; 总结了一篇【深度学习】深度学习之巅&#xff1a;在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境✨ 喜欢的小伙伴可以点点关注 &#…

【MySQL】(基础篇三) —— 创建数据库和表

管理数据库和表 管理数据库 创建数据库 在MySQL中&#xff0c;创建数据库的SQL命令相对简单&#xff0c;基本语法如下&#xff1a; CREATE DATABASE 数据库名;如果你想避免在尝试创建已经存在的数据库时出现错误&#xff0c;可以添加 IF NOT EXISTS 子句&#xff0c;这样如…

transformer - 注意力机制

Transformer 的注意力机制 Transformer 是一种用于自然语言处理任务的模型架构&#xff0c;依赖于注意力机制来实现高效的序列建模。注意力机制允许模型在处理一个位置的表示时&#xff0c;考虑输入序列中所有其他位置的信息&#xff0c;而不仅仅是前面的几个位置。这种机制能…

学会python——九九乘法表+斐波那契数列(python实例一)

目录 1、认识Python 2、环境与工具 2.1 python环境 2.2 pycharm编译 2、九九乘法表 2.1 代码构思 2.2 代码示例 2.3 运行结果 3、斐波那契数列 3.1 代码构思 3.2 代码示例 3.3 运行结果 1、认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对…

Mac清洁神器CleanMyMac2024一键轻松解决电脑垃圾问题

【CleanMyMac】苹果mac电脑垃圾清理软件 大家好&#xff01;今天我要给大家种草一个超级好用的苹果mac电脑垃圾清理软件&#xff0c;那就是 CleanMyMac。相信很多人都遇到过电脑运行速度变慢、存储空间不足的问题&#xff0c;而这款软件就是解决这些问题的救星&#xff01;让我…

UML交互图-协作图

概述 协作图和序列图都表示出了对象间的交互作用&#xff0c;但是它们侧重点不同。序列图清楚地表示了交互作用中的时间顺序&#xff0c;但没有明确表示对象间的关系。协作图则清楚地表示了对象间的关系&#xff0c;但时间顺序必须从顺序号获得。序列图常常用于表示方案&#…

物理机宕机后,虚拟机出现(无响应),虚拟机无法开机

物理机宕机后&#xff0c;虚拟机出现&#xff08;无响应&#xff09;&#xff0c;虚拟机无法开机 解决方案&#xff1b;看存储池中&#xff0c;文件是否还存在&#xff1b;如果存在&#xff0c;新建虚拟机&#xff0c;加载存储池中的磁盘&#xff0c;重启虚拟机就可以了 重新创…

matlab---app

一 基础 标签和信号灯没有回调函数 clc,clear,close all %清理命令区、工作区&#xff0c;关闭显示图形 warning off %消除警告 feature jit off %加速代码运行 ysw{i}i %循环赋值 celldisp(ysw) %显示元胞数组ysw.y1{1}[1,2] …

【机器学习300问】108、什么是多项式回归模型?

一、多项式回归是什么 &#xff08;1&#xff09;举例说明 假设你经营着一家农场&#xff0c;想要根据土地面积来预测作物的产量。如果你只用线性模型&#xff08;即&#xff09;&#xff0c;你可能会发现它并不足以描述实际的产量情况&#xff0c;因为实际产量可能会随着土地…

美国演员工会SAG-AFTRA 要求人工智能在广告中使用演员声音需征得同意并付费

SAG-AFTRA 的新豁免允许在人工智能生成的广告中使用演员的声音&#xff0c;但需要同意、补偿和安全措施 美国演员工会&#xff08;SAG-AFTRA&#xff09;推出了一项新的豁免&#xff0c;以保护会员免受未经授权的人工智能在广告中使用其声音的影响。动态人工智能音频广告豁免定…

添加Microsoft.VisualStudio.TestTools.UnitTesting命名空间

创建“单元测试项目”&#xff0c;则自动添加 Microsoft.VisualStudio.TestTools.UnitTesting 命名空间

《Brave New Words 》2.1 学生为什么要写作

Part II: Giving Voice to the Social Sciences 第二部分&#xff1a;为社会科学发声 Art is a collaboration between God and the artist, and the less the artist does the better. —Andr Gide 艺术是上帝与艺术家的合作&#xff0c;艺术家做得越少越好。 —安德烈纪德 A …

Docker 常用命令以及镜像选择

目录 1.Docker基本组成 2.镜像选择 2.1、镜像推荐选择方案 2.2版本选择 3.Docker 命令 3.1镜像管理 拉取镜像&#xff1a; 列出镜像&#xff1a; 删除镜像&#xff1a; 构建镜像&#xff1a; 3.2容器管理 运行容器 列出运行中的容器和所有容器 停止容器 启动重启…

微服务开发与实战Day04

一、网关路由 网关&#xff1a;就是网络的关口&#xff0c;负责请求的路由、转发、身份校验。 在SpringCloud中网关的实现包括两种&#xff1a; 1. 快速入门 Spring Cloud Gateway 步骤&#xff1a; ①新建hm-gateway模块 ②引入依赖pom.xml(hm-gateway) <?xml version…

(2024,自监督 ViT,全监督 ViT,损失可视化,MAE,RC-MAE,自蒸馏,EMA)可视化自监督 ViT 的损失景观

Visualizing the loss landscape of Self-supervised Vision Transformer 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0 摘要 2 基础&#xff1a;MAE 和 RC-MAE 3 损失景观 3.1 分…

matlab GUI界面设计

【实验内容】 用MATLAB的GUI程序设计一个具备图像边缘检测功能的用户界面&#xff0c;该设计程序有以下基本功能&#xff1a; &#xff08;1&#xff09;图像的读取和保存。 &#xff08;2&#xff09;设计图形用户界面&#xff0c;让用户对图像进行彩色图像到灰度图像的转换…

【java、lucene、python】互联网搜索引擎课程报告二:建立搜索引擎

一、项目要求 建立并实现文本搜索功能 对经过预处理后的500个英文和中文文档/网页建立搜索并实现搜索功能对文档建立索引&#xff0c;然后通过前台界面或者已提供的界面&#xff0c;输入关键字&#xff0c;展示搜索结果前台可通过网页形式、应用程序形式、或者利用已有的界面…

SQLserver通过CLR调用TCP接口

一、SQLserver启用CLR 查看是否开启CRL&#xff0c;如果run_value1&#xff0c;则表示开启 EXEC sp_configure clr enabled; GO RECONFIGURE; GO如果未启用&#xff0c;则执行如下命令启用CLR sp_configure clr enabled, 1; GO RECONFIGURE; GO二、创建 CLR 程序集 创建新项…

【Java】单例设计模式

单例设计模式简介 目录 1.单例设计模式是什么&#xff1f;2.单例设计模式设计方法饿汉式懒汉式 3.单例设计模式的应用任务管理器(仅有一个页面&#xff0c;不可多开)Runtime运行环境 1.单例设计模式是什么&#xff1f; 设计模式 是解决 特定问题的优秀设计方式之一。 单例设计…