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

大家好,今天给大家讲解下如何实现一个基于百度文心一言的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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring的Controller是单例还是多例,如何保证线程安全的。

目录 验证是否单例&#xff08;默认单例&#xff09; 多例测试 单例对象成员变量测试 多例对象成员变量测试 解决方案 结论&#xff1a; 补充说明 答案&#xff1a;controller默认是单例的&#xff0c;不要使用非静态的成员变量&#xff0c;否则会发生数据逻辑混乱。 正…

Windows下SVN文件损坏,启动服务报错1067

之前碰到过一次&#xff0c;忘记最后怎么解决的了&#xff0c;只记得大概原理和原因&#xff0c;以及解决办法。 1067错误码&#xff0c;很多地方都会碰到&#xff0c;mysql也会有&#xff0c;看来应该是windows系统的错误码。跟具体程序无关。所以直接百度“SVN”、“1067”…

【Python报错】已解决ValueError: Expected 2D array, got 1D array instead

成功解决“ValueError: Expected 2D array, got 1D array instead”错误的全面指南 一、引言 在Python的数据分析和机器学习领域&#xff0c;尤其是使用NumPy、Pandas、scikit-learn等库时&#xff0c;经常会遇到各种类型错误。其中&#xff0c;“ValueError: Expected 2D arr…

AI菜鸟向前飞 — LangChain系列之十七 - 剖析AgentExecutor

AgentExecutor 顾名思义&#xff0c;Agent执行器&#xff0c;本篇先简单看看LangChain是如何实现的。 先回顾 AI菜鸟向前飞 — LangChain系列之十四 - Agent系列&#xff1a;从现象看机制&#xff08;上篇&#xff09; AI菜鸟向前飞 — LangChain系列之十五 - Agent系列&#…

大模型的发展历程

1、早期模型的探索与局限性 1.1早期模型的探索与局限性 从早期的符号逻辑到现代的深度学习 1 模型&#xff0c;AI 领域经历了数十年的探索和迭代&#xff0c;为后续突破打下了坚实基础。随着大数据的发展和 AI 计算能力的爆炸式增长&#xff0c;深度学习模型的崛起显得尤为突出…

有序二叉树java实现

类实现&#xff1a; package 树;import java.util.LinkedList; import java.util.Queue;public class BinaryTree {public TreeNode root;//插入public void insert(int value){//插入成功之后要return结束方法TreeNode node new TreeNode(value);//如果root为空的话插入if(r…

人工智能_机器学习096_PCA主成分分析降维算法_PCA降维原理_介绍和使用_模式识别_EVD特征值分解_SVD奇异值分解---人工智能工作笔记0221

首先我来看PCA降维,可以看到在图像处理中经常用到PCA,经过对数据进行降维可以去除数据噪声,发现数据中的模式,也就是 发现数据的规律. 这里的模式识别就是 机器学习中的一个分支 就是在数据中找规律的意思 我们使用代码看一下 from sklearn.docomposition import PCA from skl…

kivy 百词斩项目 报错

AttributeError: FigureCanvasKivyAgg object has no attribute resize_event AttributeError: FigureCanvasKivyAgg object has no attribute resize_event 是一种常见的Python错误&#xff0c;当你试图访问一个对象&#xff08;在这个例子中是 FigureCanvasKivyAgg 对象&am…

六、主存储器管理,计算机操作系统教程,第四版,左万利,王英

文章目录 [toc]一、存储管理的功能1.1 存储分配1.2 存储共享1.3 存储保护1.4 存储扩充1.5 地址映射 二、内存资源管理2.1 内存分区2.1.1 静态分区与动态分区2.1.2 等长分区与异长分区 2.2 内存分配2.2.1 静态等长分区的分配2.2.2 *动态异长分区的分配 2.3 碎片与紧凑 三、界地址…

从C到C++,C++入门(2)

在C入门篇&#xff08;1&#xff09;中&#xff0c;博主为大家简单介绍了什么是C&#xff0c;以及C中的关键字&#xff0c;命名空间&#xff0c;输入与输出和缺省参数的相关知识。今天就让我们继续一起学习C的基础知识点吧&#xff01;&#xff01; 1.函数重载 1.1函数重载的概…

C# WPF入门学习主线篇(十九)—— 布局管理实战『混合布局案例』

C# WPF入门学习主线篇&#xff08;十九&#xff09;—— 布局管理实战『混合布局案例』 欢迎来到C# WPF入门学习系列的第十九篇。在前几篇文章中&#xff0c;我们详细介绍了各个布局容器的基本概念和使用方法。本篇博客将通过一个综合的实战案例&#xff0c;展示如何在WPF中使用…

Comfyui容器化部署与简介

目前使用 Stable Diffusion 进行创作的工具主要有两个&#xff1a;Stable Diffusion WebUI 和 ComfyUI。本文重点介绍ComfyUI的部署使用。 ComfyUI 可定制性很强&#xff0c;可以让创作者搞出各种新奇的玩意&#xff0c;通过工作流的方式&#xff0c;也可以实现更高的自动化水平…

k8s学习--kubernetes服务自动伸缩之水平收缩(pod副本收缩)VPA详细解释与安装

文章目录 前言VPA简介简单理解详细解释VPA的优缺点优点1.自动化资源管理2.资源优化3.性能和稳定性提升5.成本节约6.集成性和灵活性 缺点1.Pod 重启影响可用性2.与 HPA 冲突3.资源监控和推荐滞后&#xff1a;4.实现复杂度&#xff1a; 核心概念Resource Requests 和 Limits自动调…

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

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

AI 边缘计算平台 - 6 TOPS 低功耗 RK3576

RK3576 是瑞芯微第二代 8nm 高性能 AIOT 平台&#xff0c;CPU 采用八核大小核构架&#xff08;4A72 2.2GHz 4A53 1.8GHz&#xff09;&#xff0c;以及一个 M0 协处理器。其 CPU 算力高达 58K DMIPS&#xff0c;足以应对各种复杂计算任务。搭载 Mali-G52 MC3 GPU&#xff0c;14…

vscode软件上安装 Fitten Code插件及使用

一. 简介 前面几篇文章学习了 Pycharm开发工具上安装 Fitten Code插件&#xff0c;以及 Fitten Code插件的使用。 Fitten Code插件是是一款由非十大模型驱动的 AI 编程助手&#xff0c;它可以自动生成代码&#xff0c;提升开发效率&#xff0c;帮您调试 Bug&#xff0c;节省…

【CS.AI】GPT-4o:重新定义人工智能的新标杆

文章目录 1 序言2 GPT-4o的技术亮点3 GPT-4o与前代版本的对比3.1 热门AI模型对比表格GPT-3.5GPT-4GPT-4oBERTT5 3.2 其他 4 个人体验与感受5 结论 1 序言 嘿&#xff0c;大家好&#xff01;今天要聊聊一个超级酷的AI新突破——GPT-4o&#xff01;最近&#xff0c;OpenAI发布了…

【报文数据流中的反压处理】

报文数据流中的反压处理 1 带存储体的反压1.1 原理图1.2 Demo 尤其是在NP芯片中&#xff0c;经常涉及到报文的数据流处理&#xff1b;为了防止数据丢失&#xff0c;和各模块的流水处理&#xff1b;因此需要到反压机制&#xff1b; 反压机制目前接触到的有两种&#xff1a;一是基…

ARM功耗管理框架之SCP

安全之安全(security)博客目录导读 目录 一、功耗管理框架中的SCP 二、SCP的示例 三、SCP固件 四、SCP启动流程 五、SCP的memory map 六、SCP与AP的通信 思考&#xff1a;功耗管理框架&#xff1f;SCP&#xff1f;PPU&#xff1f;LPI&#xff1f;之间的关系&#xff1f…

(三)React事件

1. React基础事件绑定 语法&#xff1a; on 事件名称 { 事件处理程序 }&#xff0c;整体上遵循驼峰命名法 App.js //项目根组件 //App -> index.js -> public/index.html(root)function App() {const handleClick () > {console.log(button被点击了)}return (<…