大家好,今天给大家讲解下如何实现一个基于百度文心一言的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上就可以了。
网创有方论坛http://www.wcyf520.cn
chattokenjsonapicliappideurlchatgptgptragparseivaunitetlcreatecode百度文心utmroi