Skip to content

Commit

Permalink
Merge pull request #32 from OVINC-CN/feat_tool
Browse files Browse the repository at this point in the history
feat: tool
  • Loading branch information
OrenZhang authored Jun 30, 2024
2 parents b79dcff + 588bc2b commit 8651ffd
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 3 deletions.
8 changes: 8 additions & 0 deletions src/api/tool.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import http from './index';

export const listToolsAPI = () => new Promise((resolve, reject) => {
http.get('/tools/').then(
(res) => resolve(res),
(err) => reject(err),
);
});
112 changes: 111 additions & 1 deletion src/components/ChatInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {extractFileAPI, extractFileStatusAPI, getCOSConfigAPI, getCOSUploadTempK
import {loadCOSClient} from '@/utils/cos';
import {IconFile, IconDelete} from '@arco-design/web-vue/es/icon';
import {listSystemPresetAPI} from '@/api/model';
import {listToolsAPI} from '@/api/tool';
// props
const props = defineProps({
Expand Down Expand Up @@ -109,6 +110,10 @@ const doChat = async () => {
if (props.systemDefine) {
params.messages.unshift({role: 'system', content: props.systemDefine});
}
// use tool
if (currentTool.value) {
params['tools'] = [currentTool.value];
}
// call api
let key = '';
await preCheckAPI(params)
Expand Down Expand Up @@ -361,6 +366,43 @@ onMounted(() => {
}
});
// tools
const tools = ref([]);
const loadTools = () => {
listToolsAPI().then((res) => tools.value = res.data);
};
onMounted(() => loadTools());
const currentTool = ref('');
const currentToolDesc = computed(() => {
let val = '';
tools.value.forEach((item) => {
if (item.id === currentTool.value) {
val = item.desc;
}
});
return val ? val : '';
});
const toolVisible = ref(false);
const changeTool = () => toolVisible.value = true;
const doSubmitTool = () => {
toolVisible.value = false;
localStorage.setItem(localToolKey.value, JSON.stringify(currentTool.value));
};
const resetTool = () => {
toolVisible.value = false;
currentTool.value = '';
currentToolDesc.value = '';
};
const localToolKey = ref('local-tool');
onMounted(() => {
const value = localStorage.getItem(localToolKey.value);
if (value) {
try {
currentTool.value = JSON.parse(value);
} catch (_) {}
}
});
defineExpose({reGenerate, promptForm});
</script>

Expand Down Expand Up @@ -420,6 +462,16 @@ defineExpose({reGenerate, promptForm});
>
<icon-bulb />
</a-button>
<a-button
v-if="showEditBox && tools.length > 0"
:disabled="chatLoading"
@click="changeTool"
class="chat-input-left-button"
:type="currentTool ? 'primary': undefined"
:status="currentTool ? 'warning' : undefined"
>
<icon-apps />
</a-button>
<a-button
v-if="uploadEnabled && showEditBox"
:disabled="chatLoading"
Expand Down Expand Up @@ -487,6 +539,58 @@ defineExpose({reGenerate, promptForm});
</a-spin>
</a-form-item>
</a-form>
<a-modal
v-model:visible="toolVisible"
:footer="false"
:esc-to-close="true"
>
<template #title>
<div style="text-align: left; width: 100%">
{{ $t('Tools') }}
</div>
</template>
<a-space
direction="vertical"
id="chat-input-tool-choose"
>
<a-select
:placeholder="$t('PleaseChooseTool')"
:allow-search="true"
v-model="currentTool"
>
<a-option
v-for="item in tools"
:key="item.id"
:value="item.id"
:label="item.name"
/>
</a-select>
<a-textarea
v-model="currentToolDesc"
:auto-size="{minRows: 3, maxRows: 10}"
:placeholder="$t('PleaseChooseTool')"
/>
<div class="model-tool-tips">
{{ $t('ToolUseTips') }}
</div>
<a-space style="width: 100%; display: flex; justify-content: flex-end">
<a-button
v-if="currentTool"
type="primary"
status="warning"
@click="resetTool"
>
{{ $t('Remove') }}
</a-button>
<a-button
type="primary"
@click="doSubmitTool"
>
{{ $t('Save') }}
</a-button>
</a-space>
</a-space>
</a-modal>
<a-modal
v-model:visible="maxMessageVisible"
:footer="false"
Expand Down Expand Up @@ -611,8 +715,14 @@ defineExpose({reGenerate, promptForm});
}
.model-ignore-system-tips,
.model-context-tips {
.model-context-tips,
.model-tool-tips {
color: var(--color-neutral-6);
font-size: 12px;
}
#chat-input-tool-choose,
#chat-input-system-define-content > :deep(.arco-space-item) {
width: 100%;
}
</style>
2 changes: 1 addition & 1 deletion src/components/MessageContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const emits = defineEmits(['reGenerate']);
{{ message.file.split('/').slice(-1)[0] }}
</a-space>
</a-link>
<icon-loading v-show="!message.content && chatLoading" />
<icon-loading v-show="isLast && chatLoading" />
</div>
<a-avatar
v-show="false"
Expand Down
5 changes: 4 additions & 1 deletion src/locale/en-us.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@ const mEnUS = {
Save: 'Save',
PleaseChoosePreset: 'Please choose one preset',
Remove: 'Remove',
ModelIgnoreSystemDefineTips: 'Some models may ignore presets, if the output does not meet expectations, try switching models.',
ModelIgnoreSystemDefineTips: 'Some models may ignore presets, if the output does not meet expectations, try switching models',
MaxMessagesCount: 'Max Context',
ModelContextLengthTips: 'Context refers to historical messages and related information within a conversation. By carrying context, ChatGPT can better understand the user’s intent and adjust the content of its responses accordingly.',
Tools: 'Tools',
ToolUseTips: 'Some models do not support tool, if the output does not meet expectations, please switch models',
PleaseChooseTool: 'Please choose tool',
};

export default mEnUS;
3 changes: 3 additions & 0 deletions src/locale/zh-cn.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ const mZhCN = {
ModelIgnoreSystemDefineTips: '部分模型可能会忽略预设,如果输出不符合预期,请切换模型',
MaxMessagesCount: '对话上下文数量',
ModelContextLengthTips: '上下文是指对话中的历史消息和相关信息。通过携带上下文,模型可以更好地理解用户的意图,并对回复内容进行调整',
Tools: '插件',
ToolUseTips: '部分模型不支持插件,如果输出不符合预期,请切换模型',
PleaseChooseTool: '请选择插件',
};

export default mZhCN;

0 comments on commit 8651ffd

Please sign in to comment.