Chatgpt 角色 AI 开发 so easy:我用几行代码实现了 prompt 和云端化

288 天前
 C900612

最近本人花了不到一天的时间,开发了一个简单的 AI 角色 Android 小软件,可以实现 AI 角色的云端化,可以指定大量的 AI 角色和对应 prompt 。闲话少说,先直接上图,再简单分解开发过程。如果你对文章没兴趣,可以跳过下面的内容,直接获取源码。

https://github.com/bmob/Bmob-Android-AI-Prompt

一、数据表的设计

角色表

登录 Bmob 后端云账号,创建应用之后,创建角色表( Character ):

聊天内容表

聊天内容表( Message ):

二、java bean 设计

创建和数据表对应的 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 {
}

三、初始化 Bmob 和 AI

创建 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);
                    }
                });
            }
        });

649 次点击
所在节点    OpenAI
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/960137

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX