优化样式
This commit is contained in:
parent
8d507cdcb2
commit
ddea65cc8b
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4870215 */
|
||||
src: url('iconfont.woff2?t=1744201767604') format('woff2'),
|
||||
url('iconfont.woff?t=1744201767604') format('woff'),
|
||||
url('iconfont.ttf?t=1744201767604') format('truetype');
|
||||
src: url('iconfont.woff2?t=1744276722320') format('woff2'),
|
||||
url('iconfont.woff?t=1744276722320') format('woff'),
|
||||
url('iconfont.ttf?t=1744276722320') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -13,6 +13,10 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-double-loading:before {
|
||||
content: "\e8fc";
|
||||
}
|
||||
|
||||
.icon-stop:before {
|
||||
content: "\e708";
|
||||
}
|
||||
|
Binary file not shown.
@ -155,6 +155,23 @@ a {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.inner .openmcp-code-block {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.inner .code-header {
|
||||
display: none;
|
||||
color: var(--foreground);
|
||||
background-color: transparent !important;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.inner pre {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.lang-id {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ export interface ChatMessage {
|
||||
content: string;
|
||||
tool_call_id?: string
|
||||
name?: string // 工具名称,当 role 为 tool
|
||||
tool_calls?: ToolCall[]
|
||||
}
|
||||
|
||||
// 新增状态和工具数据
|
||||
@ -31,8 +32,12 @@ export interface ChatStorage {
|
||||
|
||||
export interface ToolCall {
|
||||
id?: string;
|
||||
name: string;
|
||||
arguments: string;
|
||||
index?: number;
|
||||
type: string;
|
||||
function: {
|
||||
name: string;
|
||||
arguments: string;
|
||||
}
|
||||
}
|
||||
|
||||
export const allTools = ref<ToolItem[]>([]);
|
||||
|
@ -2,13 +2,13 @@
|
||||
<div class="chat-container" :ref="el => chatContainerRef = el">
|
||||
<el-scrollbar ref="scrollbarRef" :height="'90%'" @scroll="handleScroll">
|
||||
<div class="message-list" :ref="el => messageListRef = el">
|
||||
<div v-for="(message, index) in tabStorage.messages" :key="index"
|
||||
:class="['message-item', message.role]">
|
||||
<div class="message-avatar" v-if="message.role === 'assistant'">
|
||||
<div v-for="(message, index) in renderMessages" :key="index"
|
||||
:class="['message-item', message.role.split('/')[0]]">
|
||||
<div class="message-avatar" v-if="message.role.split('/')[0] === 'assistant'">
|
||||
<span class="iconfont icon-chat"></span>
|
||||
</div>
|
||||
|
||||
<!-- 用户输入的部分,不需要渲染成 markdown -->
|
||||
<!-- 用户输入的部分 -->
|
||||
<div class="message-content" v-if="message.role === 'user'">
|
||||
<div class="message-role"></div>
|
||||
<div class="message-text">
|
||||
@ -16,26 +16,72 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 助手返回的部分 -->
|
||||
<div class="message-content" v-else-if="message.role === 'assistant'">
|
||||
<!-- 助手返回的内容部分 -->
|
||||
<div class="message-content" v-else-if="message.role === 'assistant/content'">
|
||||
<div class="message-role">Agent</div>
|
||||
<div class="message-text">
|
||||
<div v-html="markdownToHtml(message.content)"></div>
|
||||
<span class="iconfont icon-copy" @click="handleCopy(message.content)"></span>
|
||||
<div v-if="message.content" v-html="markdownToHtml(message.content)"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 待定 -->
|
||||
<div class="message-content" v-else>
|
||||
<div class="message-role">Tool</div>
|
||||
<div class="message-text">
|
||||
<div v-if="streamingToolCalls.length > 0">
|
||||
<span>正在调用工具: {{ streamingToolCalls[0].name }}</span>
|
||||
<!-- 助手调用的工具部分 -->
|
||||
<div class="message-content" v-else-if="message.role === 'assistant/tool_calls'">
|
||||
<div class="message-role">
|
||||
Agent
|
||||
<span class="message-reminder" v-if="!message.toolResult">
|
||||
正在使用工具
|
||||
<span class="tool-loading iconfont icon-double-loading">
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="message-text tool_calls">
|
||||
<div v-if="message.content" v-html="markdownToHtml(message.content)"></div>
|
||||
|
||||
<div class="tool-calls">
|
||||
<div v-for="(call, index) in message.tool_calls" :key="index" class="tool-call-item">
|
||||
<div class="tool-call-header">
|
||||
<span class="tool-name">{{ call.function.name }}</span>
|
||||
<span class="tool-type">{{ call.type }}</span>
|
||||
</div>
|
||||
<div class="tool-arguments">
|
||||
<div class="inner">
|
||||
<div v-html="jsonResultToHtml(call.function.arguments)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 工具调用结果 -->
|
||||
<div v-if="message.toolResult">
|
||||
<div class="tool-call-header">
|
||||
<span class="tool-name">{{ "响应" }}</span>
|
||||
<span style="width: 200px;" class="tools-dialog-container">
|
||||
<el-switch
|
||||
v-model="message.showJson!.value"
|
||||
inline-prompt
|
||||
active-text="JSON"
|
||||
inactive-text="Text"
|
||||
style="margin-left: 10px; width: 200px;"
|
||||
:inactive-action-style="'backgroundColor: var(--sidebar)'"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="tool-result" v-if="isValidJSON(message.toolResult)">
|
||||
<div v-if="message.showJson!.value" class="tool-result-content">
|
||||
<div class="inner">
|
||||
<div v-html="jsonResultToHtml(message.toolResult)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<span v-else>
|
||||
<div v-for="(item, index) in JSON.parse(message.toolResult)" :key="index">
|
||||
<div v-if="item.type === 'text'" class="tool-text">{{ item.text }}</div>
|
||||
<div v-else class="tool-other">{{ JSON.stringify(item) }}</div>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<span v-else>{{ message.content }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 正在加载的部分实时解析 markdown -->
|
||||
@ -72,15 +118,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, defineComponent, defineProps, onUnmounted, computed, nextTick, watch } from 'vue';
|
||||
import { ref, onMounted, defineComponent, defineProps, onUnmounted, computed, nextTick, watch, Ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useMessageBridge } from "@/api/message-bridge";
|
||||
import { ElMessage, ScrollbarInstance } from 'element-plus';
|
||||
import { tabs } from '../panel';
|
||||
import { ChatMessage, ChatStorage, getToolSchema, ToolCall } from './chat';
|
||||
|
||||
import Setting from './setting.vue';
|
||||
import { llmManager, llms } from '@/views/setting/llm';
|
||||
// 引入 markdown.ts 中的函数
|
||||
import { markdownToHtml, copyToClipboard } from './markdown';
|
||||
import { TaskLoop } from './task-loop';
|
||||
@ -106,7 +150,6 @@ const props = defineProps({
|
||||
const tab = tabs.content[props.tabId];
|
||||
const tabStorage = tab.storage as ChatStorage;
|
||||
|
||||
const bridge = useMessageBridge();
|
||||
const userInput = ref('');
|
||||
const inputHeightLines = computed(() => {
|
||||
const currentLines = userInput.value.split('\n').length;
|
||||
@ -118,6 +161,49 @@ if (!tabStorage.messages) {
|
||||
tabStorage.messages = [] as ChatMessage[];
|
||||
}
|
||||
|
||||
interface IRenderMessage {
|
||||
role: 'user' | 'assistant/content' | 'assistant/tool_calls' | 'tool';
|
||||
content: string;
|
||||
toolResult?: string;
|
||||
tool_calls?: ToolCall[];
|
||||
showJson?: Ref<boolean>;
|
||||
}
|
||||
|
||||
const renderMessages = computed(() => {
|
||||
const messages: IRenderMessage[] = [];
|
||||
for (const message of tabStorage.messages) {
|
||||
if (message.role === 'user') {
|
||||
messages.push({
|
||||
role: 'user',
|
||||
content: message.content
|
||||
});
|
||||
} else if (message.role === 'assistant') {
|
||||
if (message.tool_calls) {
|
||||
messages.push({
|
||||
role: 'assistant/tool_calls',
|
||||
content: message.content,
|
||||
tool_calls: message.tool_calls,
|
||||
showJson: ref(false)
|
||||
});
|
||||
} else {
|
||||
messages.push({
|
||||
role: 'assistant/content',
|
||||
content: message.content
|
||||
});
|
||||
}
|
||||
|
||||
} else if (message.role === 'tool') {
|
||||
// 如果是工具,则合并进入 之前 assistant 一起渲染
|
||||
const lastAssistantMessage = messages[messages.length - 1];
|
||||
if (lastAssistantMessage.role === 'assistant/tool_calls') {
|
||||
lastAssistantMessage.toolResult = message.content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return messages;
|
||||
});
|
||||
|
||||
const isLoading = ref(false);
|
||||
|
||||
const streamingContent = ref('');
|
||||
@ -145,14 +231,6 @@ const handleKeydown = (event: KeyboardEvent) => {
|
||||
// Shift+Enter 允许自然换行
|
||||
};
|
||||
|
||||
const handleCopy = async (text: string) => {
|
||||
try {
|
||||
await copyToClipboard(text);
|
||||
ElMessage.success('复制成功');
|
||||
} catch (error) {
|
||||
ElMessage.error('复制失败: ' + error);
|
||||
}
|
||||
};
|
||||
|
||||
const autoScroll = ref(true);
|
||||
const scrollbarRef = ref<ScrollbarInstance>();
|
||||
@ -252,6 +330,33 @@ onMounted(() => {
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', updateScrollHeight);
|
||||
});
|
||||
|
||||
// 新增辅助函数检查是否为有效JSON
|
||||
const isValidJSON = (str: string) => {
|
||||
try {
|
||||
JSON.parse(str);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const jsonResultToHtml = (jsonString: string) => {
|
||||
const formattedJson = JSON.stringify(JSON.parse(jsonString), null, 2);
|
||||
const html = markdownToHtml('```json\n' + formattedJson + '\n```');
|
||||
return html;
|
||||
};
|
||||
|
||||
// 新增格式化工具参数的方法
|
||||
const formatToolArguments = (args: string) => {
|
||||
try {
|
||||
const parsed = JSON.parse(args);
|
||||
return JSON.stringify(parsed, null, 2);
|
||||
} catch {
|
||||
return args;
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -293,6 +398,11 @@ onUnmounted(() => {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.message-text.tool_calls {
|
||||
border-left: 3px solid var(--main-color);
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.user .message-text {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
@ -388,6 +498,68 @@ onUnmounted(() => {
|
||||
<style scoped>
|
||||
/* 原有样式保持不变 */
|
||||
|
||||
/* 新增工具调用样式 */
|
||||
.tool-calls {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.tool-call-item {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.tool-call-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.tool-name {
|
||||
font-weight: bold;
|
||||
color: var(--el-color-primary);
|
||||
margin-right: 8px;
|
||||
margin-bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.tool-type {
|
||||
font-size: 0.8em;
|
||||
color: var(--el-text-color-secondary);
|
||||
background-color: var(--el-fill-color-light);
|
||||
padding: 2px 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.tool-arguments {
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
background-color: var(--el-fill-color-light);
|
||||
border-radius: 4px;
|
||||
font-family: monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.tool-result {
|
||||
padding: 8px;
|
||||
background-color: var(--el-fill-color-light);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.tool-text {
|
||||
white-space: pre-wrap;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.tool-other {
|
||||
font-family: monospace;
|
||||
font-size: 0.9em;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* 新增样式来减小行距 */
|
||||
.message-text p,
|
||||
.message-text h3,
|
||||
@ -404,4 +576,21 @@ onUnmounted(() => {
|
||||
margin-top: 0.2em;
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
/* 新增旋转标记样式 */
|
||||
.tool-loading {
|
||||
display: inline-block;
|
||||
margin-left: 8px;
|
||||
animation: spin 1s linear infinite;
|
||||
color: var(--main-color);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
|
||||
</style>
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="chat-settings">
|
||||
<el-tooltip content="选择模型" placement="top">
|
||||
<div class="setting-button" size="small" @click="showModelDialog = true">
|
||||
<div class="setting-button" @click="showModelDialog = true">
|
||||
<span class="iconfont icon-model">
|
||||
{{ currentServerName }}/{{ currentModelName }}
|
||||
</span>
|
||||
@ -30,14 +30,14 @@
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip content="温度参数" placement="top">
|
||||
<div class="setting-button" size="small" @click="showTemperatureSlider = true">
|
||||
<div class="setting-button" @click="showTemperatureSlider = true">
|
||||
<span class="iconfont icon-temperature"></span>
|
||||
<span class="value-badge">{{ tabStorage.settings.temperature.toFixed(1) }}</span>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip content="上下文长度" placement="top">
|
||||
<div class="setting-button" size="small" @click="showContextLengthDialog = true">
|
||||
<div class="setting-button" @click="showContextLengthDialog = true">
|
||||
<span class="iconfont icon-length"></span>
|
||||
<span class="value-badge">{{ tabStorage.settings.contextLength }}</span>
|
||||
</div>
|
||||
@ -114,6 +114,8 @@
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="enableAllTools">激活所有工具</el-button>
|
||||
<el-button type="danger" @click="disableAllTools">禁用所有工具</el-button>
|
||||
<el-button type="primary" @click="showToolsDialog = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -183,7 +185,6 @@ const hasSystemPrompt = computed(() => {
|
||||
});
|
||||
|
||||
|
||||
|
||||
const showToolsDialog = ref(false);
|
||||
|
||||
const toolActive = computed(() => {
|
||||
@ -247,6 +248,20 @@ const activeToolsSchemaHTML = computed(() => {
|
||||
"```json\n" + jsonString + "\n```"
|
||||
);
|
||||
});
|
||||
|
||||
// 新增方法 - 激活所有工具
|
||||
const enableAllTools = () => {
|
||||
tabStorage.settings.enableTools.forEach(tool => {
|
||||
tool.enabled = true;
|
||||
});
|
||||
};
|
||||
|
||||
// 新增方法 - 禁用所有工具
|
||||
const disableAllTools = () => {
|
||||
tabStorage.settings.enableTools.forEach(tool => {
|
||||
tool.enabled = false;
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@ -380,6 +395,11 @@ const activeToolsSchemaHTML = computed(() => {
|
||||
border-radius: 4px;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
background-color: var(--el-bg-color-overlay);
|
||||
}
|
||||
|
||||
.schema-viewer .openmcp-code-block {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.schema-viewer code {
|
||||
|
@ -32,8 +32,8 @@ export class TaskLoop {
|
||||
// TODO: 调用多个工具并返回调用结果?
|
||||
const toolCall = toolCalls[0];
|
||||
try {
|
||||
const toolName = toolCall.name;
|
||||
const toolArgs = JSON.parse(toolCall.arguments);
|
||||
const toolName = toolCall.function.name;
|
||||
const toolArgs = JSON.parse(toolCall.function.arguments);
|
||||
const toolResponse = await callTool(toolName, toolArgs);
|
||||
if (!toolResponse.isError) {
|
||||
const content = JSON.stringify(toolResponse.content);
|
||||
@ -57,28 +57,34 @@ export class TaskLoop {
|
||||
private handleChunkDeltaToolCalls(chunk: ChatCompletionChunk) {
|
||||
const toolCall = chunk.choices[0]?.delta?.tool_calls?.[0];
|
||||
if (toolCall) {
|
||||
if (toolCall.index === 0) {
|
||||
const currentCall = this.streamingToolCalls.value[toolCall.index];
|
||||
|
||||
if (currentCall === undefined) {
|
||||
// 新的工具调用开始
|
||||
this.streamingToolCalls.value = [{
|
||||
id: toolCall.id,
|
||||
name: toolCall.function?.name || '',
|
||||
arguments: toolCall.function?.arguments || ''
|
||||
index: 0,
|
||||
type: 'function',
|
||||
function: {
|
||||
name: toolCall.function?.name || '',
|
||||
arguments: toolCall.function?.arguments || ''
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
// 累积现有工具调用的信息
|
||||
const currentCall = this.streamingToolCalls.value[toolCall.index];
|
||||
if (currentCall) {
|
||||
if (toolCall.id) {
|
||||
currentCall.id = toolCall.id;
|
||||
}
|
||||
if (toolCall.function?.name) {
|
||||
currentCall.name = toolCall.function.name;
|
||||
currentCall.function.name = toolCall.function.name;
|
||||
}
|
||||
if (toolCall.function?.arguments) {
|
||||
currentCall.arguments += toolCall.function.arguments;
|
||||
currentCall.function.arguments += toolCall.function.arguments;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,13 +190,20 @@ export class TaskLoop {
|
||||
|
||||
// 如果存在需要调度的工具
|
||||
if (this.streamingToolCalls.value.length > 0) {
|
||||
|
||||
tabStorage.messages.push({
|
||||
role: 'assistant',
|
||||
content: this.streamingContent.value || '',
|
||||
tool_calls: this.streamingToolCalls.value
|
||||
});
|
||||
|
||||
const toolCallResult = await this.handleToolCalls(this.streamingToolCalls.value);
|
||||
if (toolCallResult) {
|
||||
const toolCall = this.streamingToolCalls.value[0];
|
||||
|
||||
tabStorage.messages.push({
|
||||
role: 'tool',
|
||||
tool_call_id: toolCall.id || toolCall.name,
|
||||
tool_call_id: toolCall.id || toolCall.function.name,
|
||||
content: toolCallResult
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"currentIndex": 0,
|
||||
"currentIndex": 1,
|
||||
"tabs": [
|
||||
{
|
||||
"name": "交互测试",
|
||||
@ -23,6 +23,18 @@
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "聚类算法(Clustering Algorithm)是一种**无监督学习**(Unsupervised Learning)方法,用于将数据集中的样本划分为若干个组(称为“簇”或“类”),使得同一组内的样本彼此相似,而不同组的样本差异较大。聚类算法的目标是通过数据的内在结构,发现数据中的潜在模式或分组。\n\n### 聚类算法的核心思想\n1. **相似性度量**:通过距离(如欧氏距离、曼哈顿距离)或相似性(如余弦相似度)来衡量样本之间的相似程度。\n2. **簇内紧凑性**:同一簇内的样本应尽可能相似。\n3. **簇间分离性**:不同簇的样本应尽可能不相似。\n\n---\n\n### 常见的聚类算法\n1. **K-Means** \n - 将数据划分为K个簇,每个簇的中心由簇内样本的平均值表示。\n - 适用于数值型数据,计算高效,但对初始中心点敏感,且需要预先指定K值。\n\n2. **层次聚类(Hierarchical Clustering)** \n - 通过自底向上(凝聚法)或自顶向下(分裂法)的方式构建树状图(Dendrogram)。\n - 不需要预先指定簇的数量,但计算复杂度较高。\n\n3. **DBSCAN(Density-Based Spatial Clustering of Applications with Noise)** \n - 基于密度的聚类,能够发现任意形状的簇,并能识别噪声点。\n - 不需要预先指定簇的数量,但对参数(如邻域半径和最小样本数)敏感。\n\n4. **高斯混合模型(GMM, Gaussian Mixture Model)** \n - 假设数据由多个高斯分布混合生成,通过概率模型进行聚类。\n - 适用于数据分布复杂的情况,但计算复杂度较高。\n\n5. **谱聚类(Spectral Clustering)** \n - 基于图论的聚类方法,利用数据的相似性矩阵进行降维和聚类。\n - 适用于非凸形状的簇,但对相似性矩阵的计算要求较高。\n\n---\n\n### 聚类算法的应用场景\n1. **客户分群**:根据消费行为将用户划分为不同群体,便于精准营销。\n2. **图像分割**:将图像中的像素聚类为不同的区域。\n3. **异常检测**:通过聚类识别离群点(如金融欺诈检测)。\n4. **文本挖掘**:对文档或词汇进行聚类,发现主题或类别。\n5. **生物信息学**:基因表达数据的聚类分析。\n\n---\n\n### 聚类算法的评估指标\n1. **轮廓系数(Silhouette Coefficient)**:衡量样本与同簇和其他簇的相似性,值越接近1表示聚类效果越好。\n2. **Calinski-Harabasz指数**:基于簇内离散度和簇间离散度的比值,值越大表示聚类效果越好。\n3. **Davies-Bouldin指数**:衡量簇内距离与簇间距离的比值,值越小表示聚类效果越好。\n\n---\n\n如果你有具体的数据或场景需要聚类分析,可以告诉我,我可以帮助你选择合适的算法或工具!"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "请帮我计算 add 1 2"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "错误: 工具调用失败: Unexpected token '}', \"}\" is not valid JSON"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "看起来在调用工具时出现了问题。让我手动帮你计算 `1 + 2` 的结果:\n\n\\[\n1 + 2 = 3\n\\]\n\n结果是 **3**!如果你有其他计算需求,也可以告诉我哦!"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
@ -55,6 +67,73 @@
|
||||
"systemPrompt": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "交互测试",
|
||||
"icon": "icon-robot",
|
||||
"type": "blank",
|
||||
"componentIndex": 3,
|
||||
"storage": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "计算 add 1 2"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "",
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "call_0_12c5b219-bb79-46db-b1ea-876d708415f5",
|
||||
"index": 0,
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "add",
|
||||
"arguments": "{\"a\":1,\"b\":2}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "tool",
|
||||
"tool_call_id": "call_0_12c5b219-bb79-46db-b1ea-876d708415f5",
|
||||
"content": "[{\"type\":\"text\",\"text\":\"3\"}]"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "1 + 2 = 3"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"modelIndex": 0,
|
||||
"enableTools": [
|
||||
{
|
||||
"name": "add",
|
||||
"description": "对两个数字进行实数域的加法",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "multiply",
|
||||
"description": "对两个数字进行实数域的乘法运算",
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"name": "is_even",
|
||||
"description": "判断一个整数是否为偶数",
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"name": "capitalize",
|
||||
"description": "将字符串首字母大写",
|
||||
"enabled": false
|
||||
}
|
||||
],
|
||||
"enableWebSearch": false,
|
||||
"temperature": 0.7,
|
||||
"contextLength": 10,
|
||||
"systemPrompt": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user