接入本地模型
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
<el-button type="text" @click="getModelAccount">应用</el-button>
|
<el-button type="text" @click="getModelAccount">应用</el-button>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-row v-loading="loadingAccount" element-loading-background="#272A37">
|
<el-row v-loading="loadingAccount" element-loading-background="#272A37" v-if="!isLocal">
|
||||||
<el-form-item label="账号用户" class="fill">{{ account.username }}</el-form-item>
|
<el-form-item label="账号用户" class="fill">{{ account.username }}</el-form-item>
|
||||||
<el-form-item label="账户余额" class="fill">{{ [account.usage, account.total].join(" / ") }}</el-form-item>
|
<el-form-item label="账户余额" class="fill">{{ [account.usage, account.total].join(" / ") }}</el-form-item>
|
||||||
<el-button type="text" @click="getModelAccount">刷新</el-button>
|
<el-button type="text" @click="getModelAccount">刷新</el-button>
|
||||||
@@ -57,7 +57,8 @@ export default {
|
|||||||
models: () => Object.values(models),
|
models: () => Object.values(models),
|
||||||
account: v => v.settings.account || {usage: 0, total: 0},
|
account: v => v.settings.account || {usage: 0, total: 0},
|
||||||
apiKey: v => v.settings.model.apiKey || "key无效或网络波动,请重新尝试",
|
apiKey: v => v.settings.model.apiKey || "key无效或网络波动,请重新尝试",
|
||||||
isGPT: v => v.settings.model.name == "ChatGPT"
|
isGPT: v => v.settings.model.name == "ChatGPT",
|
||||||
|
isLocal: v => typeof v.settings.model?.getAccount != "function"
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initModel(model) {
|
initModel(model) {
|
||||||
@@ -66,7 +67,7 @@ export default {
|
|||||||
if (ins.apiKey) {
|
if (ins.apiKey) {
|
||||||
clearInterval(timer)
|
clearInterval(timer)
|
||||||
this.settings.model = ins
|
this.settings.model = ins
|
||||||
this.getModelAccount()
|
!this.isLocal && this.getModelAccount()
|
||||||
}
|
}
|
||||||
}, 500)
|
}, 500)
|
||||||
},
|
},
|
||||||
@@ -83,8 +84,8 @@ export default {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.settings {
|
.settings {
|
||||||
min-width: 375px;
|
|
||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
|
width: 300px;
|
||||||
|
|
||||||
:deep(.el-form) {
|
:deep(.el-form) {
|
||||||
.el-form-item__label {
|
.el-form-item__label {
|
||||||
@@ -108,6 +109,7 @@ export default {
|
|||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
border-color: #409EFF;
|
border-color: #409EFF;
|
||||||
|
|||||||
@@ -212,6 +212,80 @@ export class ChatGLM extends BaseModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 集成私有的Alpaca
|
||||||
|
*/
|
||||||
|
export class Alpaca extends BaseModel {
|
||||||
|
static base = "https://testai.cunwuyun.cn"
|
||||||
|
static avatar = "https://cdn.cunwuyun.cn/img/logo.svg"
|
||||||
|
static name = "Alpaca"
|
||||||
|
static id = "alpaca-7b-plus"
|
||||||
|
static desc = "llama所基于的中文权重本地模型"
|
||||||
|
|
||||||
|
constructor(params) {
|
||||||
|
const {avatar, name, desc, id} = Alpaca
|
||||||
|
super({avatar, name, desc, id, ...params})
|
||||||
|
this.setApiKey("alpaca-7b-plus")
|
||||||
|
}
|
||||||
|
|
||||||
|
async chat(history) {
|
||||||
|
const messages = history.map(e => ({role: e.role, content: e.msg}))
|
||||||
|
return await axios.post(Alpaca.base + "/v1/chat/completions", JSON.stringify({messages, model: this.id}), {
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + this.apiKey, "Content-Type": "application/json", Accept: "application/json",
|
||||||
|
},
|
||||||
|
}).then(res => res.json()).then(data => data?.choices?.[0]?.message?.content || "key无效或网络波动,请重新尝试");
|
||||||
|
}
|
||||||
|
|
||||||
|
async chatStream(history) {
|
||||||
|
const messages = history.map(e => ({role: e.role, content: e.msg}))
|
||||||
|
return await axios.post(Alpaca.base + "/v1/chat/completions", JSON.stringify({
|
||||||
|
messages,
|
||||||
|
model: this.id,
|
||||||
|
stream: true
|
||||||
|
}), {
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + this.apiKey, "Content-Type": "application/json", Accept: "application/json",
|
||||||
|
},
|
||||||
|
}).then(res => res?.body?.getReader());
|
||||||
|
}
|
||||||
|
|
||||||
|
streamOutput(reader, chat) {
|
||||||
|
return reader.read().then(({done, value}) => {
|
||||||
|
if (done) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!chat.reminder) {
|
||||||
|
chat.reminder = ""
|
||||||
|
}
|
||||||
|
let decode = new TextDecoder().decode(value)
|
||||||
|
decode = chat.reminder + decode
|
||||||
|
let decodedArray = decode.split("data: ");
|
||||||
|
let longstr = "";
|
||||||
|
decodedArray.forEach(decoded => {
|
||||||
|
decoded = decoded.trim();
|
||||||
|
try {
|
||||||
|
if (longstr != "") {
|
||||||
|
decoded = longstr + decoded;
|
||||||
|
longstr = "";
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
longstr = decoded;
|
||||||
|
decoded = "";
|
||||||
|
}
|
||||||
|
if (!!decoded && decoded !== "[DONE]") {
|
||||||
|
const choices = JSON.parse(decoded).choices
|
||||||
|
if (choices?.length > 0) {
|
||||||
|
const response = choices[0].delta.content || "";
|
||||||
|
chat.msg += response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return this.streamOutput(reader, chat)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 集成免费的New Bing搜索,TODO
|
* 集成免费的New Bing搜索,TODO
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user