1
This commit is contained in:
@@ -33,3 +33,26 @@ export function deletePromptTemplate(key) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 大模型接入配置(与 Jarvis 共用 Redis)
|
||||||
|
export function getLlmConfig() {
|
||||||
|
return request({
|
||||||
|
url: '/jarvis/social-media/llm-config',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveLlmConfig(data) {
|
||||||
|
return request({
|
||||||
|
url: '/jarvis/social-media/llm-config/save',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetLlmConfig() {
|
||||||
|
return request({
|
||||||
|
url: '/jarvis/social-media/llm-config',
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,11 +103,77 @@
|
|||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
|
<el-card class="box-card llm-card" style="margin-top: 20px;">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span class="card-title">
|
||||||
|
<i class="el-icon-connection"></i>
|
||||||
|
大模型接入配置
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-alert
|
||||||
|
v-if="llmConfig && llmConfig.redisAvailable === false"
|
||||||
|
title="当前未连接 Redis,无法保存接入配置;Jarvis 将始终使用其 application.yml 中的默认 Ollama。"
|
||||||
|
type="warning"
|
||||||
|
:closable="false"
|
||||||
|
show-icon
|
||||||
|
style="margin-bottom: 16px;" />
|
||||||
|
<el-alert
|
||||||
|
type="info"
|
||||||
|
:closable="false"
|
||||||
|
show-icon
|
||||||
|
style="margin-bottom: 16px;">
|
||||||
|
<div slot="title">
|
||||||
|
<p style="margin: 0 0 8px 0;"><strong>说明:</strong>与上方提示词相同,配置写入 Redis,由 Jarvis 读取。可在「本地 Ollama」与「OpenAI 兼容 HTTP」之间切换。</p>
|
||||||
|
<ul style="margin: 0; padding-left: 18px;">
|
||||||
|
<li><strong>Ollama</strong>:填写根地址(如 <code>http://127.0.0.1:11434</code>),可不填则使用 Jarvis 默认;模型名可空则使用 yml 默认。</li>
|
||||||
|
<li><strong>OpenAI 兼容</strong>:填写完整 Chat Completions URL(如远程 <code>https://api.xxx.com/v1/chat/completions</code> 或本地 <code>http://127.0.0.1:11434/v1/chat/completions</code>),并填写模型名;密钥无则留空(部分本地服务不需要)。</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</el-alert>
|
||||||
|
<el-form :model="llmForm" label-width="140px" class="llm-form">
|
||||||
|
<el-form-item label="接入方式">
|
||||||
|
<el-radio-group v-model="llmForm.mode">
|
||||||
|
<el-radio label="ollama">本地 Ollama</el-radio>
|
||||||
|
<el-radio label="openai">OpenAI 兼容接口</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="llmForm.mode === 'openai' ? 'API 完整地址' : 'Ollama 根地址'">
|
||||||
|
<el-input
|
||||||
|
v-model="llmForm.baseUrl"
|
||||||
|
:placeholder="llmForm.mode === 'openai' ? 'https://api.openai.com/v1/chat/completions' : 'http://127.0.0.1:11434(可留空使用 Jarvis 默认)'"
|
||||||
|
clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="模型名称">
|
||||||
|
<el-input
|
||||||
|
v-model="llmForm.model"
|
||||||
|
:placeholder="llmForm.mode === 'openai' ? '必填,如 gpt-4o-mini、deepseek-chat' : '可选,不填则用 Jarvis 默认模型'"
|
||||||
|
clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="API 密钥">
|
||||||
|
<el-input
|
||||||
|
v-model="llmForm.apiKeyInput"
|
||||||
|
type="password"
|
||||||
|
show-password
|
||||||
|
autocomplete="new-password"
|
||||||
|
placeholder="修改时填写新密钥;留空表示保持原密钥" />
|
||||||
|
<span v-if="llmHasApiKey" class="llm-key-hint">当前已保存密钥:{{ llmApiKeyMasked || '****' }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="llmHasApiKey">
|
||||||
|
<el-checkbox v-model="llmClearApiKey">清除已保存的 API 密钥</el-checkbox>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-check" :loading="llmSaving" @click="handleSaveLlm">保存接入配置</el-button>
|
||||||
|
<el-button icon="el-icon-refresh-left" @click="handleLoadLlm">重新加载</el-button>
|
||||||
|
<el-button type="danger" plain icon="el-icon-delete" @click="handleResetLlm">恢复默认(清除 Redis 中的接入配置)</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listPromptTemplates, getPromptTemplate, savePromptTemplate, deletePromptTemplate } from '@/api/jarvis/socialMediaPrompt'
|
import { listPromptTemplates, getPromptTemplate, savePromptTemplate, deletePromptTemplate, getLlmConfig, saveLlmConfig, resetLlmConfig } from '@/api/jarvis/socialMediaPrompt'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SocialMediaPromptConfig',
|
name: 'SocialMediaPromptConfig',
|
||||||
@@ -116,11 +182,23 @@ export default {
|
|||||||
showHelp: false,
|
showHelp: false,
|
||||||
activeTab: 'keywords',
|
activeTab: 'keywords',
|
||||||
templates: {},
|
templates: {},
|
||||||
saving: {}
|
saving: {},
|
||||||
|
llmConfig: null,
|
||||||
|
llmForm: {
|
||||||
|
mode: 'ollama',
|
||||||
|
baseUrl: '',
|
||||||
|
model: '',
|
||||||
|
apiKeyInput: ''
|
||||||
|
},
|
||||||
|
llmHasApiKey: false,
|
||||||
|
llmApiKeyMasked: null,
|
||||||
|
llmClearApiKey: false,
|
||||||
|
llmSaving: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loadTemplates()
|
this.loadTemplates()
|
||||||
|
this.loadLlmConfig()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 加载所有模板 */
|
/** 加载所有模板 */
|
||||||
@@ -222,6 +300,88 @@ export default {
|
|||||||
'content:both': '通用文案'
|
'content:both': '通用文案'
|
||||||
}
|
}
|
||||||
return labels[key] || key
|
return labels[key] || key
|
||||||
|
},
|
||||||
|
|
||||||
|
async loadLlmConfig() {
|
||||||
|
try {
|
||||||
|
const res = await getLlmConfig()
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
this.llmConfig = res.data
|
||||||
|
this.llmForm.mode = res.data.mode === 'openai' ? 'openai' : 'ollama'
|
||||||
|
this.llmForm.baseUrl = res.data.baseUrl || ''
|
||||||
|
this.llmForm.model = res.data.model || ''
|
||||||
|
this.llmForm.apiKeyInput = ''
|
||||||
|
this.llmHasApiKey = !!res.data.hasApiKey
|
||||||
|
this.llmApiKeyMasked = res.data.apiKeyMasked || null
|
||||||
|
this.llmClearApiKey = false
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.msg || '加载大模型配置失败')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
this.$message.error('加载大模型配置失败:' + (e.message || '未知错误'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async handleSaveLlm() {
|
||||||
|
if (this.llmForm.mode === 'openai') {
|
||||||
|
if (!this.llmForm.baseUrl || !this.llmForm.baseUrl.trim()) {
|
||||||
|
this.$message.warning('OpenAI 兼容模式须填写完整 API 地址')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.llmForm.model || !this.llmForm.model.trim()) {
|
||||||
|
this.$message.warning('OpenAI 兼容模式须填写模型名称')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const payload = {
|
||||||
|
mode: this.llmForm.mode,
|
||||||
|
baseUrl: (this.llmForm.baseUrl || '').trim(),
|
||||||
|
model: (this.llmForm.model || '').trim()
|
||||||
|
}
|
||||||
|
if (this.llmClearApiKey) {
|
||||||
|
payload.clearApiKey = true
|
||||||
|
} else if (this.llmForm.apiKeyInput && this.llmForm.apiKeyInput.trim()) {
|
||||||
|
payload.apiKey = this.llmForm.apiKeyInput.trim()
|
||||||
|
}
|
||||||
|
this.llmSaving = true
|
||||||
|
try {
|
||||||
|
const res = await saveLlmConfig(payload)
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$message.success('大模型接入配置已保存')
|
||||||
|
await this.loadLlmConfig()
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.msg || '保存失败')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
this.$message.error('保存失败:' + (e.message || '未知错误'))
|
||||||
|
} finally {
|
||||||
|
this.llmSaving = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async handleLoadLlm() {
|
||||||
|
await this.loadLlmConfig()
|
||||||
|
this.$message.success('已重新加载')
|
||||||
|
},
|
||||||
|
|
||||||
|
async handleResetLlm() {
|
||||||
|
try {
|
||||||
|
await this.$confirm('将删除 Redis 中的大模型接入配置,Jarvis 恢复为 application.yml 默认 Ollama。是否继续?', '提示', { type: 'warning' })
|
||||||
|
const res = await resetLlmConfig()
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$message.success(res.msg || '已恢复默认')
|
||||||
|
await this.loadLlmConfig()
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.msg || '操作失败')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e !== 'cancel') {
|
||||||
|
console.error(e)
|
||||||
|
this.$message.error('操作失败:' + (e.message || '未知错误'))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,5 +445,16 @@ export default {
|
|||||||
.template-actions .el-button {
|
.template-actions .el-button {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.llm-card .llm-form {
|
||||||
|
max-width: 720px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.llm-key-hint {
|
||||||
|
display: block;
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user