Commit aefd9f11 authored by zhouxiang's avatar zhouxiang
Browse files

dcu平台fastllm推理框架

parents
Pipeline #543 failed with stages
in 0 seconds
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
\ No newline at end of file
package com.doujiao.xiaozhihuiassistant;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.doujiao.xiaozhihuiassistant", appContext.getPackageName());
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.doujiao.xiaozhihuiassistant">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:largeHeap="true"
android:theme="@style/Theme.XiaoZhihuiAssistant">
<activity
android:name=".MainActivity"
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
\ No newline at end of file
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.10.2)
# Declares and names the project.
project("assistant")
set(CMAKE_BUILD_TYPE "Release")
option(USE_CUDA "use cuda" OFF)
option(PY_API "python api" OFF)
#可以注释掉下面优化选项
#add_definitions(${CMAKE_CXX_FLAGS} "${CMAKE_CXX_FLAGS} -march=armv8.2a+dotprod")
#
#file(GLOB_RECURSE NANODET_SOURCE ../../../../../../../src/*.cpp
# ../../../../../../../src/devices/cpu/*.cpp
# ../../../../../../../src/models/*.cpp)
#
#set(PROJECT_SOURCE
# ${NANODET_SOURCE}
# )
set(PROJECT_SOURCE
../../../../../../../src/fastllm.cpp
../../../../../../../src/device.cpp
../../../../../../../src/model.cpp
../../../../../../../src/executor.cpp
../../../../../../../src/devices/cpu/cpudevice.cpp
../../../../../../../src/devices/cpu/cpudevicebatch.cpp
../../../../../../../src/models/chatglm.cpp
../../../../../../../src/models/moss.cpp
../../../../../../../src/models/llama.cpp
../../../../../../../src/models/basellm.cpp
../../../../../../../src/models/qwen.cpp
)
include_directories(
./
../../../../../../../include
../../../../../../../include/models
../../../../../../../include/utils
../../../../../../../include/devices/cpu)
add_library( # Sets the name of the library.
assistant
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${PROJECT_SOURCE} LLMChat.cpp native-lib.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
assistant
# Links the target library to the log library
# included in the NDK.
${log-lib})
#add_executable(main main.cpp ../../../../../../../src/fastllm.cpp
# ../../../../../../../src/chatglm.cpp
# ../../../../../../../src/moss.cpp)
\ No newline at end of file
#include <cstdio>
#include <cstring>
#include <iostream>
#include <getopt.h>
#include "LLMChat.h"
#include "model.h"
//void(^ __nonnull RuntimeChat)(int index,const char* _Nonnull content) = NULL;//实时回调
static int modeltype = 0;
static char* modelpath = NULL;
static std::unique_ptr<fastllm::basellm> chatGlm = NULL;
static int sRound = 0;
static std::string history;
static RuntimeResultMobile g_callback = NULL;
std::string initGptConf(const char* modelPath,int threads) {
fastllm::SetThreads(threads);
LOG_Debug("@@init llmpath:%s\n",modelPath);
chatGlm = fastllm::CreateLLMModelFromFile(modelPath);
if(chatGlm != NULL)
{
std::string modelName = chatGlm->model_type;
LOG_Debug("@@model name:%s\n",modelName.c_str());
return modelName;
}
LOG_Debug("@@CreateLLMModelFromFile failed.");
return "";
}
int chat(const char* prompt, RuntimeResultMobile chatCallback) {
std::string ret = "";
g_callback = chatCallback;
LOG_Debug("@@init llm:type:%d,prompt:%s\n",modeltype,prompt);
std::string input(prompt);
if (input == "reset") {
history = "";
sRound = 0;
g_callback(0,"Done!");
g_callback(-1,"");
return 0;
}
ret = chatGlm->Response(chatGlm->MakeInput(history, sRound, input), [](int index, const char* content) {
g_callback(index,content);
});
history = chatGlm->MakeHistory(history, sRound, input, ret);
sRound++;
long len = ret.length();
return len;
}
void uninitLLM()
{
}
//
// LLMChat.h
// LLMChat
//
// Created by 胡其斌 on 2023/5/18.
//
#ifdef __cplusplus
extern "C" {
#endif
#include <android/log.h>
#define LOG_Debug(...) __android_log_print(ANDROID_LOG_DEBUG, "Assistant", __VA_ARGS__)
typedef void(* RuntimeResultMobile)(int index,const char* content);
std::string initGptConf(const char* modelPath,int threads);
int chat(const char* prompt, RuntimeResultMobile chatCallback);
void uninitLLM();
#ifdef __cplusplus
}
#endif
#include <cstdio>
#include <cstring>
#include <iostream>
#include <getopt.h>
#include "factoryllm.h"
static factoryllm fllm;
static int modeltype = 0;
static char* modelpath = NULL;
static fastllm::basellm* chatGlm = fllm.createllm(LLM_TYPE_CHATGLM);
static fastllm::basellm* moss = fllm.createllm(LLM_TYPE_MOSS);
static int sRound = 0;
static std::string history;
struct RunConfig {
int model = LLM_TYPE_CHATGLM; // 模型类型, LLM_TYPE_CHATGLM:chatglm, LLM_TYPE_MOSS:moss
std::string path = "/sdcard/chatglm-6b-int4.bin"; // 模型文件路径
int threads = 6; // 使用的线程数
};
static struct option long_options[] = {
{"help", no_argument, nullptr, 'h'},
{"model", required_argument, nullptr, 'm'},
{"path", required_argument, nullptr, 'p'},
{"threads", required_argument, nullptr, 't'},
{nullptr, 0, nullptr, 0},
};
void Usage() {
std::cout << "Usage:" << std::endl;
std::cout << "[-h|--help]: 显示帮助" << std::endl;
std::cout << "<-m|--model> <args>: 模型类型,默认为chatglm, 可以设置为0, moss:1" << std::endl;
std::cout << "<-p|--path> <args>: 模型文件的路径" << std::endl;
std::cout << "<-t|--threads> <args>: 使用的线程数量" << std::endl;
}
void ParseArgs(int argc, char **argv, RunConfig &config) {
int opt;
int option_index = 0;
const char *opt_string = "h:m:p:t:";
while ((opt = getopt_long_only(argc, argv, opt_string, long_options, &option_index)) != -1) {
switch (opt) {
case 'h':
Usage();
exit (0);
case 'm':
config.model = atoi(argv[optind - 1]);
break;
case 'p':
config.path = argv[optind - 1];
break;
case 't':
config.threads = atoi(argv[optind - 1]);
break;
default:
Usage();
exit (-1);
}
}
}
int initLLMConf(int model,const char* modelPath,int threads) {
fastllm::SetThreads(threads);
modeltype = model;
// printf("@@init llm:type:%d,path:%s\n",model,modelPath);
if (modeltype == 0) {
chatGlm->LoadFromFile(modelPath);
}
if (modeltype == 1) {
moss->LoadFromFile(modelPath);
}
return 0;
}
int chat(const char* prompt) {
std::string ret = "";
//printf("@@init llm:type:%d,prompt:%s\n",modeltype,prompt);
std::string input(prompt);
if (modeltype == 0) {
if (input == "reset") {
history = "";
sRound = 0;
return 0;
}
history += ("[Round " + std::to_string(sRound++) + "]\n问:" + input);
auto prompt = sRound > 1 ? history : input;
ret = chatGlm->Response(prompt,[](int index,const char* content){
if(index == 0) {
printf("ChatGLM:");
}
printf("%s", content);
if (index == -1) {
printf("\n");
}
});
history += ("\n答:" + ret + "\n");
}
if (modeltype == 1) {
auto prompt = "You are an AI assistant whose name is MOSS. <|Human|>: " + input + "<eoh>";
ret = moss->Response(prompt,[](int index,const char* content){
if(index == 0) {
printf("MOSS:");
}
printf("%s", content);
if (index == -1) {
printf("\n");
}
});
}
long len = ret.length();
return len;
}
void uninitLLM()
{
if (chatGlm)
{
delete chatGlm;
chatGlm = NULL;
}
if (moss)
{
delete moss;
moss = NULL;
}
}
int main(int argc, char **argv) {
RunConfig config;
ParseArgs(argc, argv, config);
initLLMConf(config.model, config.path.c_str(), config.threads);
if (config.model == LLM_TYPE_MOSS) {
while (true) {
printf("用户: ");
std::string input;
std::getline(std::cin, input);
if (input == "stop") {
break;
}
chat(input.c_str());
}
} else if (config.model == LLM_TYPE_CHATGLM) {
while (true) {
printf("用户: ");
std::string input;
std::getline(std::cin, input);
if (input == "stop") {
break;
}
chat(input.c_str());
}
} else {
Usage();
exit(-1);
}
return 0;
}
#include <jni.h>
#include <string>
#include "LLMChat.h"
JavaVM *g_javaVM = NULL;
jobject g_obj;
void initGvm(JNIEnv *env,jobject thiz) {
if(g_javaVM == NULL) {
env->GetJavaVM(&g_javaVM);
g_obj = env->NewGlobalRef(thiz);
}
}
void chatCb(int index,const char* content) {
JNIEnv *env = NULL;
int mNeedDetach = 0;
//获取当前native线程是否有没有被附加到jvm环境中
int getEnvStat = g_javaVM->GetEnv((void **)&env,JNI_VERSION_1_6);
if (getEnvStat == JNI_EDETACHED) {
//如果没有, 主动附加到jvm环境中,获取到env
if (g_javaVM->AttachCurrentThread( &env, NULL) != 0) {
LOG_Debug("Unable to AttachCurrentThread");
return;
}
mNeedDetach = 1;
}
//通过全局变量g_obj 获取到要回调的类
jclass javaClass = env->GetObjectClass(g_obj);//env->FindClass("com/doujiao/core/AssistantCore");//
if (javaClass == 0) {
LOG_Debug("Unable to find class");
if(mNeedDetach) {
g_javaVM->DetachCurrentThread();
}
return;
}
jmethodID jgetDBpathMethod = env->GetMethodID(javaClass, "reportChat", "(Ljava/lang/String;I)V");
if (jgetDBpathMethod == NULL) {
LOG_Debug("Unable to find method:jgetDBpathMethod");
return;
}
jobject bb = env->NewDirectByteBuffer((void *) content, strlen(content));
jclass cls_Charset = env->FindClass("java/nio/charset/Charset");
jmethodID mid_Charset_forName = env->GetStaticMethodID(cls_Charset, "forName", "(Ljava/lang/String;)Ljava/nio/charset/Charset;");
jobject charset = env->CallStaticObjectMethod(cls_Charset, mid_Charset_forName, env->NewStringUTF("UTF-8"));
jmethodID mid_Charset_decode = env->GetMethodID(cls_Charset, "decode", "(Ljava/nio/ByteBuffer;)Ljava/nio/CharBuffer;");
jobject cb = env->CallObjectMethod(charset, mid_Charset_decode, bb);
env->DeleteLocalRef(bb);
jclass cls_CharBuffer = env->FindClass("java/nio/CharBuffer");
jmethodID mid_CharBuffer_toString = env->GetMethodID(cls_CharBuffer, "toString", "()Ljava/lang/String;");
jstring str = static_cast<jstring>(env->CallObjectMethod(cb, mid_CharBuffer_toString));
env->CallVoidMethod(g_obj, jgetDBpathMethod,str,index);
env->DeleteLocalRef(javaClass);
//释放当前线程
if(mNeedDetach) {
g_javaVM->DetachCurrentThread();
}
env = NULL;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_doujiao_core_AssistantCore_initLLMConfig(
JNIEnv* env,
jobject obj,
jstring modelpath,
jint threads) {
initGvm(env,obj);
const char *path = env->GetStringUTFChars(modelpath, NULL);
std::string ret = initGptConf(path,threads);
LOG_Debug("@@@initLLMConfig:%s",ret.c_str());
env->ReleaseStringUTFChars( modelpath, path);
return env->NewStringUTF(ret.c_str());
}
extern "C" JNIEXPORT jint JNICALL
Java_com_doujiao_core_AssistantCore_chat(
JNIEnv* env,
jobject obj,
jstring prompt) {
initGvm(env,obj);
const char *question = env->GetStringUTFChars(prompt, NULL);
chat(question,[](int index,const char* content){
chatCb(index,content);
});
// chatCb(1,"content");
return 0;
}
extern "C" JNIEXPORT void JNICALL
Java_com_doujiao_core_AssistantCore_uninitLLM(
JNIEnv* env,
jobject /* this */) {
uninitLLM();
}
\ No newline at end of file
package com.doujiao.core;
import android.support.annotation.Keep;
import android.util.Log;
public class AssistantCore {
private static AssistantCore instance = null;
private static runtimeResult mRuntimeRes = null;
static {
System.loadLibrary("assistant");
}
/*静态对象*/
public static AssistantCore getInstance(){
if(instance == null){
instance = new AssistantCore();
}
return instance;
}
public String initLLM(String path,runtimeResult callback) {
mRuntimeRes = callback;
return initLLMConfig(path,8);
}
@Keep
public void reportChat(String content,int index) {
Log.d("@@@","recv:"+content+",index:"+index);
if (mRuntimeRes != null) {
mRuntimeRes.callbackResult(index,content);
}
}
public interface runtimeResult {
void callbackResult(int index,String content);
}
private native String initLLMConfig(String path,int threads);
public native int chat(String prompt);
public native int uninitLLM();
}
package com.doujiao.xiaozhihuiassistant;
/**
* Created by chenpengfei on 2016/10/27.
*/
public class ChatMessage {
private String content;
private int type;
public ChatMessage(String content, int type) {
this.content = content;
this.type = type;
}
public ChatMessage(String content) {
this(content, 1);
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
package com.doujiao.xiaozhihuiassistant;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.doujiao.core.AssistantCore;
import com.doujiao.xiaozhihuiassistant.adapter.MyAdapter;
import com.doujiao.xiaozhihuiassistant.databinding.ActivityMainBinding;
import com.doujiao.xiaozhihuiassistant.utils.PrefUtil;
import com.doujiao.xiaozhihuiassistant.utils.StatusBarUtils;
import com.doujiao.xiaozhihuiassistant.utils.UriUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final int MSG_TYPE_RECVRESULT = 0;
private static final int MSG_TYPE_INITMODEL_END = 1;
private ActivityMainBinding binding;
private volatile boolean mIsRunning = false;
private EditText mInputEt = null;
private TextView mTvTips = null;
private RecyclerView mRcyViewMess = null;
private Button sendBtn;
private String mInputContent = "";
private String mOutPutContent = "";
private boolean mIsInit = false;
ArrayList<ChatMessage> messageList = new ArrayList<>();
private MyAdapter myAdapter = null;
//读写权限
private static String[] PERMISSIONS_STORAGE = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//请求状态码
private final static int REQUEST_PERMISSION_CODE = 1;
protected static Uri modelUri = null;
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int msgType = msg.what;
switch (msgType) {
case MSG_TYPE_RECVRESULT: {
int index = msg.arg1;
String content = (String) msg.obj;
if (index == 0) {
addMsgList(content,2);
}
if (index > 0) {
updateMsgList(content);
}
if(index == -1) {
// sendBtn.setEnabled(true);
}
}
break;
case MSG_TYPE_INITMODEL_END:
String model = (String)msg.obj;
if (TextUtils.isEmpty(model)) {
Toast.makeText(getApplicationContext(), "模型不正确!请下载正确模型。", Toast.LENGTH_SHORT).show();
} else {
sendBtn.setEnabled(true);
mInputEt.setText("");
mTvTips.setText(PrefUtil.getModelPath());
Toast.makeText(getApplicationContext(), "欢迎使用:"+model, Toast.LENGTH_SHORT).show();
mIsInit = true;
}
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
PrefUtil.initPref(getApplicationContext());
initView();
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
initModel();
} else {
sendBtn.setEnabled(false);
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_PERMISSION_CODE);
}
}
StatusBarUtils.hideStatusBar(getWindow(),true);
}
private void initModel() {
//init:
String modelPath = PrefUtil.getModelPath();
if (!modelPath.isEmpty()) {
mTvTips.setText("模型加载中..");
new Thread(new Runnable() {
@Override
public void run() {
if(modelUri != null) {
try {
Log.d(MainActivity.class.getName(), " writing model file to " + modelPath);
InputStream inputStream = getContentResolver().openInputStream(modelUri);
FileOutputStream fileOutputStream = new FileOutputStream(modelPath);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, bytesRead);
}
fileOutputStream.close();
inputStream.close();
Log.d("@@@", "model file write in " + modelPath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
String path = PrefUtil.getModelPath();//Environment.getExternalStorageDirectory().getAbsolutePath() + "/chatglm-6b-int4.bin";
File file = new File(path);
if(!file.exists() || file.length() < 1024 * 1024 * 1024) {
PrefUtil.setModelPath("");
String modelType = "";
Message msg = Message.obtain();
msg.obj = modelType;
msg.what = MSG_TYPE_INITMODEL_END;
mHandler.sendMessage(msg);
return;
}
String modelType = AssistantCore.getInstance().initLLM(path, new AssistantCore.runtimeResult() {
@Override
public void callbackResult(int index, String content) {
Message msg = Message.obtain();
msg.what = MSG_TYPE_RECVRESULT;
msg.arg1 = index;
msg.obj = content;
mHandler.sendMessage(msg);
}
});
Log.d("@@@","model:"+modelType);
Message msg = Message.obtain();
msg.obj = modelType;
msg.what = MSG_TYPE_INITMODEL_END;
mHandler.sendMessage(msg);
}
}).start();
} else {
mTvTips.setText(getString(R.string.app_model_tips));
}
}
public void initView() {
mTvTips = findViewById(R.id.tv_tips);
mInputEt = findViewById(R.id.edit_input);
mRcyViewMess = findViewById(R.id.rv_msgs);
mRcyViewMess.setLayoutManager(new LinearLayoutManager(this));
myAdapter = new MyAdapter(this);
mRcyViewMess.setAdapter(myAdapter);
myAdapter.setMessages(messageList);
sendBtn = findViewById(R.id.btn_send);
if (!mIsInit)
sendBtn.setEnabled(false);
sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendMsg();
}
});
Button btnSel = findViewById(R.id.btn_sel);
btnSel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!mIsRunning) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(Intent.createChooser(intent, "需要选择文件"), 1);
} else {
Toast.makeText(getApplicationContext(),"Is Running...",Toast.LENGTH_SHORT).show();
}
}
});
}
public void updateMsgList(String content) {
ChatMessage msg = messageList.get(messageList.size() - 1);
messageList.remove(messageList.size() - 1);
msg.setContent(msg.getContent() + content);
messageList.add(msg);
myAdapter.setMessages(messageList);
myAdapter.notifyItemChanged(messageList.size() - 1);
}
public void addMsgList(String content,int role) {
messageList.add(new ChatMessage(content,role));
myAdapter.setMessages(messageList);
myAdapter.notifyItemInserted(messageList.size());
}
public void sendMsg() {
mInputContent = mInputEt.getText().toString();
if (mInputContent.isEmpty()) {
Toast.makeText(getApplicationContext(),"输入不能为空",Toast.LENGTH_SHORT).show();
return;
}
if (!mIsRunning) {
mIsRunning = true;
addMsgList(mInputContent,1);
mInputEt.setText("");
new Thread(new Runnable() {
@Override
public void run() {
int ret = AssistantCore.getInstance().chat(mInputContent);
Log.d("@@@","chat end:"+ret);
mIsRunning = false;
}
}).start();
} else {
Toast.makeText(getApplicationContext(),"Is Running...",Toast.LENGTH_SHORT).show();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION_CODE) {
boolean isGrant = true;
for (int i = 0; i < permissions.length; i++) {
int grantResult = grantResults[i];
if (grantResult != PackageManager.PERMISSION_GRANTED) {
isGrant = false;
}
}
if (isGrant) {
initModel();
}else {
Toast.makeText(this, "请允许访问文件", Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();
String pathString = UriUtils.getPath(this, uri);
modelUri = null;
if(pathString == null || pathString.length()==0 || !pathString.startsWith("/")){
pathString = getApplicationContext().getExternalFilesDir("models") + "/model2.flm";
modelUri = uri;
}
Log.d(MainActivity.class.getName(), "uri: " + uri + " pathString");
PrefUtil.setModelPath(pathString);
initModel();
}
}
}
package com.doujiao.xiaozhihuiassistant.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* Created by chenpengfei on 2016/10/27.
*/
public class BaseViewHolder extends RecyclerView.ViewHolder {
private View iv;
public BaseViewHolder(View itemView) {
super(itemView);
iv = itemView;
}
public View findViewById(int id) {
return iv.findViewById(id);
}
}
package com.doujiao.xiaozhihuiassistant.adapter;
import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.doujiao.xiaozhihuiassistant.ChatMessage;
import com.doujiao.xiaozhihuiassistant.R;
import com.doujiao.xiaozhihuiassistant.utils.StatusBarUtils;
import com.doujiao.xiaozhihuiassistant.widget.ChatPromptViewManager;
import com.doujiao.xiaozhihuiassistant.widget.Location;
import com.doujiao.xiaozhihuiassistant.widget.PromptViewHelper;
import java.util.List;
public class MyAdapter extends RecyclerView.Adapter<BaseViewHolder> {
private List<ChatMessage> mChatMessageList = null;
private Activity mActivity;
public MyAdapter(Activity activity) {
mActivity = activity;
}
public void setMessages(List<ChatMessage> chatMessageList) {
mChatMessageList = chatMessageList;
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == 1) {
return new LeftViewHolder(View.inflate(mActivity, R.layout.activity_item_left, null));
} else {
return new RightViewHolder(View.inflate(mActivity, R.layout.activity_item_right, null));
}
}
@Override
public int getItemCount() {
return mChatMessageList.size();
}
@Override
public int getItemViewType(int position) {
return mChatMessageList.get(position).getType();
}
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
PromptViewHelper pvHelper = new PromptViewHelper(mActivity);
ChatMessage chatMessage = mChatMessageList.get(position);
if(holder instanceof LeftViewHolder) {
LeftViewHolder leftViewHolder = (LeftViewHolder) holder;
leftViewHolder.tv.setText(chatMessage.getContent());
pvHelper.setPromptViewManager(new ChatPromptViewManager(mActivity));
}
if(holder instanceof RightViewHolder) {
RightViewHolder rightViewHolder = (RightViewHolder) holder;
rightViewHolder.tv.setText(chatMessage.getContent());
pvHelper.setPromptViewManager(new ChatPromptViewManager(mActivity, Location.TOP_RIGHT));
}
pvHelper.addPrompt(holder.itemView.findViewById(R.id.textview_content));
pvHelper.setOnItemClickListener(new PromptViewHelper.OnItemClickListener() {
@Override
public void onItemClick(int position) {
String str = "";
switch (position) {
case 0:
str = "已复制到剪贴板!";
TextView tv = holder.itemView.findViewById(R.id.textview_content);
StatusBarUtils.copyStr2ClibBoard(mActivity.getApplicationContext(), tv.getText().toString());
break;
}
Toast.makeText(mActivity, str, Toast.LENGTH_SHORT).show();
}
});
}
class LeftViewHolder extends BaseViewHolder {
TextView tv;
public LeftViewHolder(View view) {
super(view);
tv = (TextView) findViewById(R.id.textview_content);
}
}
class RightViewHolder extends BaseViewHolder {
TextView tv;
public RightViewHolder(View view) {
super(view);
tv = (TextView) findViewById(R.id.textview_content);
}
}
}
package com.doujiao.xiaozhihuiassistant.utils;
import android.content.Context;
import android.content.SharedPreferences;
public class PrefUtil {
private static final String SF_NAME = "com.doujiao.llm.config";
private static final String MOLE_PATH = "llm_path";
private static SharedPreferences mPref;
public static void initPref(Context context) {
if (mPref == null) {
mPref = context.getSharedPreferences(SF_NAME, Context.MODE_PRIVATE);
}
}
public static void setModelPath(String path) {
if (mPref != null) {
mPref.edit().putString(MOLE_PATH,path).apply();
}
}
public static String getModelPath() {
if (mPref != null) {
return mPref.getString(MOLE_PATH,"");
}
return "";
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment