最近本人花了不到一天的时间,开发了一个简单的 AI 角色 Android 小软件,可以实现 AI 角色的云端化,可以指定大量的 AI 角色和对应 prompt 。闲话少说,先直接上图,再简单分解开发过程。如果你对文章没兴趣,可以跳过下面的内容,直接获取源码。/p>
https://github.com/bmob/Bmob-Android-AI-Prompt
登录 Bmob 后端云账号,创建应用之后,创建角色表( Character ):
聊天内容表( Message ):
创建和数据表对应的 Character 、Message 和 User 的 java bean 。
Character 类的代码如下:
public class Character extends BmobObject { /** * 这个 AI 助手有多少人在用 */ String userNum; /** * AI 助手的名称 */ String title; /** * 角色的英文名 */ String name; /** * AI 助手的图片 */ String img; /** * AI 助手的 prompt */ String prompt; /** * AI 助手的描述信息 */ String description; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImg() { return img; } public void setImg(String img) { this.img = img; } public String getPrompt() { return prompt; } public void setPrompt(String prompt) { this.prompt = prompt; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getUserNum() { return userNum; } public void setUserNum(String userNum) { this.userNum = userNum; } }
Message 类的代码如下:
/** * 聊天内容类 */ public class Message extends BmobObject { public static String SEND_BY_ME="me"; public static String SEND_BY_BOT="bot"; /** * 会话 */ String session; /** * 内容的归属权 */ String username; /** * 发送的内容 */ String message; /** * 发送者( me 和 bot 两种类型) */ String sendBy; /** * 获取用户的名字 * @return */ public String getUsername() { return username; } /** * 设置用户的名字 * @param username */ public void setUsername(String username) { this.username = username; } /** * 获取会话信息 * @return */ public String getSession() { return session; } /** * 设置会话信息 * @param session */ public void setSession(String session) { this.session = session; } /** * 获取聊天内容 * @return */ public String getMessage() { return message; } /** * 设置聊天内容 * @param message */ public void setMessage(String message) { this.message = message; } /** * 获取发送者 * @return */ public String getSendBy() { return sendBy; } /** * 设置发送者 * @param sendBy */ public void setSendBy(String sendBy) { this.sendBy = sendBy; } /** * 聊天内容的构造函数 * @param message 聊天内容 * @param sendBy 发送者 */ public Message(String message, String sendBy,String session,String username) { this.message = message; this.sendBy = sendBy; this.session = session; this.username = username; } }
User 类的代码如下:
public class User extends BmobUser { }
创建 BmobApp 类,继承自 Application 类,代码如下:
public class BmobApp extends Application { public static BmobAI bmobAI; @Override public void onCreate() { super.onCreate(); //初始化 Bmob 后端云 Bmob.initialize(this,"这个替换为你自己的 application id"); //初始化 AI bmobAI = new BmobAI(); } }
登录页面直接调用了 BmobSMS 类的发送方法( requestSMSCode )和 BmobUser 类的短信验证码自动注册登录方法( signOrLoginByMobilePhone )。
public void onClick(View v) { if(v==getCodeBt){ if(!radioButton.isChecked()){ Toast.makeText(v.getContext(),"请同意以上服务条款",Toast.LENGTH_SHORT).show(); return; } //获取验证码 String phOne= phoneEdit.getText().toString().trim(); //这里不检查 phone 的更多合规性问题,自行补上 if(phone.length()!=11){ Toast.makeText(v.getContext(),"请输入正确的手机号码",Toast.LENGTH_SHORT).show(); return; } //发送验证码 BmobSMS.requestSMSCode(phone, "", new QueryListener<Integer>() { @Override public void done(Integer integer, BmobException e) { if(e==null){ //获取到验证码 Toast.makeText(v.getContext(),"验证码发送成功",Toast.LENGTH_SHORT).show(); } } }); }else if(v==submitBt){ //注册登录 String phOne= phoneEdit.getText().toString().trim(); String code = codeEdit.getText().toString().trim(); if(code.isEmpty() || code.length()!=6){ Toast.makeText(v.getContext(),"请输入验证码",Toast.LENGTH_SHORT).show(); return; } //执行登录操作 BmobUser.signOrLoginByMobilePhone(phone, code, new LogInListener<BmobUser>() { @Override public void done(BmobUser o, BmobException e) { if(e==null){ startActivity(new Intent(LoginActivity.this,MainActivity.class)); } else{ Toast.makeText(v.getContext(),"短信验证失败",Toast.LENGTH_SHORT).show(); } } }); } }
角色列表页面主要是从 Bmob 后端云上面获取角色列表,呈现在 RecycleView 上面。代码如下:
//从 Bmob 上面获取 AI 角色信息 BmobQuery<Character> query = new BmobQuery<>(); query.findObjects(new FindListener<Character>() { @Override public void done(List<Character> characterList, BmobException e) { CharacterAdapter characterAdapter = new CharacterAdapter(characterList,getContext()); prompt_recycle_view.setAdapter(characterAdapter); LinearLayoutManager llm = new LinearLayoutManager(getActivity()); llm.setStackFromEnd(true); prompt_recycle_view.setLayoutManager(llm); } });
获取历史聊天记录的代码如下:
BmobQuery<Message> query = new BmobQuery<>(); query.addWhereEqualTo("username",username); query.addWhereEqualTo("session",session); query.findObjects(new FindListener<Message>() { @Override public void done(List<Message> list, BmobException e) { if(e==null && list!=null){ messageList.addAll(list); } chatAdapter = new ChatAdapter(messageList,logo); recyclerView.setAdapter(chatAdapter); LinearLayoutManager llm = new LinearLayoutManager(getApplicationContext()); llm.setStackFromEnd(true); recyclerView.setLayoutManager(llm); } });
聊天对话的核心代码如下(主要是通过设置 prompt 实现角色):
//设置 prompt 信息 if(prompt!=null && !prompt.isEmpty()) BmobApp.bmobAI.setPrompt(prompt); //点击发送提问到 AI 服务器的按钮 sendButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //获取问题 String quesion = messageEditText.getText().toString().trim(); if(quesion.isEmpty() || quesion.trim()=="") return; //连接 AI 服务器(这个代码为了防止 AI 连接中断) BmobApp.bmobAI.Connect(); //显示问题 addToChat(quesion,Message.SEND_BY_ME); messageEditText.setText(""); //发送内容到 AI 中 BmobApp.bmobAI.Chat(quesion, session, new ChatMessageListener() { @Override public void onMessage(String s) { //消息流的形式返回 AI 的结果 addToLastMessage(s); Log.d("ai",s); } @Override public void onFinish(String s) { //一次性返回全部结果,这个方法需要等待一段时间,友好性较差 //addToChat(s,Message.SEND_BY_BOT); Message newmessage = new Message(s,Message.SEND_BY_BOT,session,username); newmessage.save(new SaveListener<String>() { @Override public void done(String s, BmobException e) { } }); sendButton.setEnabled(true); } @Override public void onError(String s) { //OpenAI 的密钥错误或者超过 OpenAI 并发时,会返回这个错误 Log.d("ai",s); sendButton.setEnabled(true); } @Override public void onClose() { //连接关闭了 Log.d("ai","close"); sendButton.setEnabled(true); } }); } });