mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-09-08 00:47:15 +08:00
change the scope of blockModelSet from during process to during one time request; add the feature to specify a fixed model in test dialog
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import { saveGptCompletionRequestRecord } from '@geekgeekrun/sqlite-plugin/dist/handlers'
|
import { saveGptCompletionRequestRecord } from '@geekgeekrun/sqlite-plugin/dist/handlers'
|
||||||
|
|
||||||
export const RequestSceneEnum = {
|
export enum RequestSceneEnum {
|
||||||
testing: 1,
|
testing = 1,
|
||||||
readNoReplyAutoReminder: 2,
|
readNoReplyAutoReminder = 2,
|
||||||
geekAutoStartChatWithBoss: 3
|
geekAutoStartChatWithBoss = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
let dbInitPromise
|
let dbInitPromise
|
||||||
|
|||||||
@@ -555,7 +555,8 @@ export default function initIpc() {
|
|||||||
})
|
})
|
||||||
async function requestLlm(_, requestPayload) {
|
async function requestLlm(_, requestPayload) {
|
||||||
return await requestNewMessageContent(requestPayload.messageList, {
|
return await requestNewMessageContent(requestPayload.messageList, {
|
||||||
requestScene: RequestSceneEnum.testing
|
requestScene: RequestSceneEnum.testing,
|
||||||
|
llmConfigIdForPick: requestPayload.llmConfigIdForPick ?? null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ipcMain.handle('request-llm-for-test', requestLlm)
|
ipcMain.handle('request-llm-for-test', requestLlm)
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ export const sendLookForwardReplyEmotion = async (page: Page) => {
|
|||||||
await lookForwardReplyEmojiProxy!.click()
|
await lookForwardReplyEmojiProxy!.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockModelSet = new Set()
|
const pickLlmConfigFromList = (llmConfigList, blockModelSet) => {
|
||||||
const pickLlmConfigFromList = (llmConfigList) => {
|
|
||||||
if (llmConfigList.length === 1) {
|
if (llmConfigList.length === 1) {
|
||||||
llmConfigList[0].enabled = true
|
llmConfigList[0].enabled = true
|
||||||
llmConfigList[0].serveWeight = SINGLE_ITEM_DEFAULT_SERVE_WEIGHT
|
llmConfigList[0].serveWeight = SINGLE_ITEM_DEFAULT_SERVE_WEIGHT
|
||||||
@@ -115,7 +114,13 @@ export const writeDefaultAutoRemindPrompt = async () => {
|
|||||||
await writeStorageFile(autoReminderPromptTemplateFileName, defaultPrompt, { isJson: false })
|
await writeStorageFile(autoReminderPromptTemplateFileName, defaultPrompt, { isJson: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const requestNewMessageContent = async (chatRecords, { requestScene } = {}) => {
|
export const requestNewMessageContent = async (
|
||||||
|
chatRecords,
|
||||||
|
{
|
||||||
|
requestScene,
|
||||||
|
llmConfigIdForPick
|
||||||
|
}: { requestScene?: RequestSceneEnum; llmConfigIdForPick?: string[] } = {}
|
||||||
|
) => {
|
||||||
const template = await getValidTemplate()
|
const template = await getValidTemplate()
|
||||||
const resumeObject = (await readConfigFile('resumes.json'))?.[0]
|
const resumeObject = (await readConfigFile('resumes.json'))?.[0]
|
||||||
const resumeContent = formatResumeJsonToMarkdown(resumeObject)
|
const resumeContent = formatResumeJsonToMarkdown(resumeObject)
|
||||||
@@ -151,9 +156,15 @@ export const requestNewMessageContent = async (chatRecords, { requestScene } = {
|
|||||||
const llmRequestRecord: Omit<LlmModelUsageRecord, 'id' | 'providerApiSecretMd5'> & {
|
const llmRequestRecord: Omit<LlmModelUsageRecord, 'id' | 'providerApiSecretMd5'> & {
|
||||||
providerApiSecret: string
|
providerApiSecret: string
|
||||||
} = {}
|
} = {}
|
||||||
|
const blockModelSet = new Set()
|
||||||
while (!res) {
|
while (!res) {
|
||||||
const llmConfigList = await readConfigFile('llm.json')
|
let llmConfigList = await readConfigFile('llm.json')
|
||||||
llmConfig = pickLlmConfigFromList(llmConfigList)
|
if (llmConfigIdForPick?.length) {
|
||||||
|
llmConfigList = llmConfigList.filter((it) => {
|
||||||
|
return llmConfigIdForPick.includes(it.id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
llmConfig = pickLlmConfigFromList(llmConfigList, blockModelSet)
|
||||||
if (!llmConfig) {
|
if (!llmConfig) {
|
||||||
throw new Error(`CANNOT_FIND_A_USABLE_MODEL`)
|
throw new Error(`CANNOT_FIND_A_USABLE_MODEL`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,129 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h100vh flex flex-col">
|
<div class="h100vh flex flex-col">
|
||||||
<div
|
<div
|
||||||
|
ref="scrollElRef"
|
||||||
:style="{
|
:style="{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
overflow: `auto`,
|
overflow: `auto`,
|
||||||
margin: `0 auto`,
|
margin: `0 auto`,
|
||||||
alignItems: `flex-end`
|
alignItems: `flex-end`,
|
||||||
|
width: '100%'
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="pb20px"></div>
|
<div
|
||||||
<div v-for="(item, index) in messageList" :key="index" class="message-item">
|
v-if="messageList.length"
|
||||||
{{ item.text }}
|
:style="{
|
||||||
|
width: '480px',
|
||||||
|
margin: '0 auto'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="pb20px"></div>
|
||||||
|
<div v-for="(item, index) in messageList" :key="index" flex flex-col flex-items-end>
|
||||||
|
<div class="message-item-wrap flex flex-col">
|
||||||
|
<div class="message-item">
|
||||||
|
{{ item.text }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:style="{
|
||||||
|
width: 'fit-content',
|
||||||
|
alignSelf: 'flex-end'
|
||||||
|
}"
|
||||||
|
font-size-10px
|
||||||
|
>
|
||||||
|
{{ item.usedLlmConfig.model }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="item?.usedLlmConfig?.providerCompleteApiUrl?.trim()"
|
||||||
|
:style="{
|
||||||
|
width: 'fit-content',
|
||||||
|
overflow: 'hidden',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
alignSelf: 'flex-end',
|
||||||
|
color: '#bbb'
|
||||||
|
}"
|
||||||
|
font-size-10px
|
||||||
|
w-fit-content
|
||||||
|
max-w-20em
|
||||||
|
>
|
||||||
|
{{ item.usedLlmConfig.providerCompleteApiUrl }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pb20px"></div>
|
||||||
|
</div>
|
||||||
|
<div v-else w-full h-full flex flex-item-center justify-center>
|
||||||
|
<el-empty>
|
||||||
|
<template #description>
|
||||||
|
<template v-if="!isLoading">
|
||||||
|
点击下方 “<el-button
|
||||||
|
font-size-16px
|
||||||
|
h-fit-content
|
||||||
|
align-baseline
|
||||||
|
p0
|
||||||
|
type="text"
|
||||||
|
@click.prevent="sendLlmGeneratedContent"
|
||||||
|
>发送开场白</el-button
|
||||||
|
>” 以开始模拟聊天
|
||||||
|
</template>
|
||||||
|
<template v-else>请稍候,第一条消息正在回复的路上~</template>
|
||||||
|
</template>
|
||||||
|
</el-empty>
|
||||||
</div>
|
</div>
|
||||||
<div class="pb20px"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:style="{
|
:style="{
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateColumns: '100px 1fr',
|
gridTemplateColumns: 'min-content 1fr min-content',
|
||||||
height: `fit-content`,
|
height: `fit-content`,
|
||||||
paddingTop: `10px`,
|
paddingTop: `10px`,
|
||||||
paddingBottom: `10px`,
|
paddingBottom: `10px`,
|
||||||
backgroundColor: `#f0f0f0`
|
backgroundColor: `#f0f0f0`
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<!-- <el-select v-model="selectedLlmConfig">
|
<el-select v-model="selectedLlmConfig" ml10px w160px placeholder="随机使用一个模型">
|
||||||
<el-option v-for="(it, index) in llmConfigList" :key="index" :label="it">
|
<el-option
|
||||||
<div>{{ it.model }}</div>
|
v-for="(it, index) in llmConfigListForRender"
|
||||||
<div>{{ it.providerCompleteApiUrl }}</div>
|
:key="index"
|
||||||
|
:value="it.id"
|
||||||
|
:label="it.model"
|
||||||
|
:disabled="!it.enabled"
|
||||||
|
:style="{
|
||||||
|
paddingTop: '10px',
|
||||||
|
paddingBottom: '10px',
|
||||||
|
height: 'auto',
|
||||||
|
lineHeight: '1.25em'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
:style="{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div>{{ it.model }}</div>
|
||||||
|
<div class="font-size-12px color-#bbb">
|
||||||
|
{{ formatApiSecret(it.providerApiSecret) || '' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="it?.providerCompleteApiUrl?.trim?.()"
|
||||||
|
:style="{
|
||||||
|
color: '#bbb',
|
||||||
|
width: '35em',
|
||||||
|
fontSize: '12px',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ it.providerCompleteApiUrl }}
|
||||||
|
</div>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select> -->
|
</el-select>
|
||||||
<el-button ml20px type="text" @click="closeWindow">关闭对话框</el-button>
|
|
||||||
<el-button
|
<el-button
|
||||||
:loading="isLoading"
|
:loading="isLoading"
|
||||||
mr10px
|
|
||||||
width-fit-content
|
width-fit-content
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="sendLlmGeneratedContent"
|
@click="sendLlmGeneratedContent"
|
||||||
@@ -44,38 +132,57 @@
|
|||||||
<template v-else-if="!messageList.length">发送开场白</template>
|
<template v-else-if="!messageList.length">发送开场白</template>
|
||||||
<template v-else>发送下一句提醒内容</template>
|
<template v-else>发送下一句提醒内容</template>
|
||||||
</el-button>
|
</el-button>
|
||||||
<div></div>
|
<el-button mr10px type="text" @click="closeWindow">关闭对话框</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
|
||||||
type MessageItem = {
|
type MessageItem = {
|
||||||
text: string
|
text: string
|
||||||
generatedBy: string
|
usedLlmConfig: string
|
||||||
|
// recordInfo: any
|
||||||
}
|
}
|
||||||
const messageList = ref<MessageItem[]>([])
|
const messageList = ref<MessageItem[]>([])
|
||||||
|
|
||||||
// const llmConfigList = ref([])
|
const llmConfigList = ref([])
|
||||||
// async function getLlmConfigList() {
|
const llmConfigListForRender = computed(() => {
|
||||||
// debugger
|
return [
|
||||||
// llmConfigList.value = await electron.ipcRenderer.invoke('get-llm-config-for-test')
|
{
|
||||||
// }
|
id: null,
|
||||||
// getLlmConfigList().catch(() => {})
|
model: '随机使用一个模型',
|
||||||
// const selectedLlmConfig = ref()
|
providerCompleteApiUrl: null,
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
|
...(llmConfigList.value ?? [])
|
||||||
|
]
|
||||||
|
})
|
||||||
|
async function getLlmConfigList() {
|
||||||
|
llmConfigList.value = await electron.ipcRenderer.invoke('get-llm-config-for-test')
|
||||||
|
}
|
||||||
|
getLlmConfigList().catch(() => {})
|
||||||
|
const selectedLlmConfig = ref(null)
|
||||||
|
|
||||||
|
const scrollElRef = ref(null)
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
async function sendLlmGeneratedContent() {
|
async function sendLlmGeneratedContent() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
try {
|
try {
|
||||||
const response = await electron.ipcRenderer.invoke('request-llm-for-test', {
|
const response = await electron.ipcRenderer.invoke('request-llm-for-test', {
|
||||||
messageList: JSON.parse(JSON.stringify(messageList.value ?? []))
|
messageList: JSON.parse(JSON.stringify(messageList.value ?? [])),
|
||||||
|
llmConfigIdForPick: selectedLlmConfig.value ? [selectedLlmConfig.value] : null
|
||||||
})
|
})
|
||||||
console.log(response)
|
console.log(response)
|
||||||
messageList.value.push({
|
messageList.value.push({
|
||||||
text: response.responseText,
|
text: response.responseText,
|
||||||
generatedBy: response.usedLlmConfig
|
usedLlmConfig: response.usedLlmConfig
|
||||||
|
})
|
||||||
|
await sleep(50)
|
||||||
|
;(scrollElRef.value as any as HTMLDivElement)?.scrollTo({
|
||||||
|
top: scrollElRef.value?.scrollHeight,
|
||||||
|
behavior: 'smooth'
|
||||||
})
|
})
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
@@ -85,17 +192,32 @@ async function sendLlmGeneratedContent() {
|
|||||||
function closeWindow() {
|
function closeWindow() {
|
||||||
electron.ipcRenderer.send(`close-read-no-reply-reminder-llm-mock-window`)
|
electron.ipcRenderer.send(`close-read-no-reply-reminder-llm-mock-window`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatApiSecret(text) {
|
||||||
|
if (typeof text !== 'string' || !text?.trim()) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
if (text === 'ollama') {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
if (text.length >= 8) {
|
||||||
|
return `${text.slice(0, 4)}***${text.slice(-4)}`
|
||||||
|
}
|
||||||
|
return `***`
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.message-item {
|
.message-item-wrap {
|
||||||
line-height: 1.25em;
|
|
||||||
font-size: 14px;
|
|
||||||
background-color: #d1f0ef;
|
|
||||||
color: #333;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 8px 8px 0 8px;
|
|
||||||
margin-top: 20px;
|
|
||||||
max-width: 420px;
|
max-width: 420px;
|
||||||
|
margin-top: 20px;
|
||||||
|
.message-item {
|
||||||
|
line-height: 1.25em;
|
||||||
|
font-size: 14px;
|
||||||
|
background-color: #d1f0ef;
|
||||||
|
color: #333;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 8px 8px 0 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user