aiModel.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <script setup lang="ts">
  2. import {NSelect, NInput,NSlider, NButton, useMessage,NTag} from "naive-ui"
  3. import { ref ,computed,watch, onMounted} from "vue";
  4. import {gptConfigStore, homeStore,useChatStore} from '@/store'
  5. import { mlog,chatSetting } from "@/api";
  6. import { t } from "@/locales";
  7. import { getKnowledge } from '@/api/knowledge'
  8. import { getToken } from "@/store/modules/auth/helper";
  9. import to from "await-to-js";
  10. import { modelList } from '@/api/model'
  11. const emit = defineEmits(['close']);
  12. const chatStore = useChatStore();
  13. const uuid = chatStore.active;
  14. const chatSet = new chatSetting( uuid==null?1002:uuid);
  15. const nGptStore = ref( chatSet.getGptConfig() );
  16. const message = useMessage()
  17. onMounted(() => { fetchData(),fetchDataGetKnowledge() });
  18. const config = ref([])
  19. const fetchData = async () => {
  20. try {
  21. // 发起一个请求
  22. const [err, result] = await to(modelList('chat'));
  23. if (err) {
  24. message.error(err.message)
  25. config.value = []; // 设置为空数组,避免迭代错误
  26. } else {
  27. config.value = result.data;
  28. }
  29. } catch (error) {
  30. console.error('Error fetching data:', error);
  31. }
  32. };
  33. const fetchDataGetKnowledge = async () => {
  34. if(getToken()){
  35. try {
  36. // 发起一个请求
  37. const [err, result] = await to(getKnowledge());
  38. console.log("result===", result.rows)
  39. if (err) {
  40. ms.error(err.message)
  41. } else {
  42. options.value = result.rows.map((item: any) => ({
  43. label: item.kname, // 假设后台返回的数据有 'name' 字段
  44. value: item.id // 假设每个数据项都有一个唯一的 'id' 字段
  45. }));
  46. // 请求成功
  47. options.value.push({ label: '暂不配置', value: '' });
  48. }
  49. } catch (error) {
  50. console.error('Error fetching data:', error);
  51. }
  52. }
  53. };
  54. const st= ref({openMore:false });
  55. const voiceList= computed(()=>{
  56. let rz=[];
  57. for(let o of "alloy,echo,fable,onyx,nova,shimmer".split(/[ ,]+/ig))rz.push({label:o,value:o})
  58. return rz;
  59. });
  60. const modellist = computed(() => { //
  61. let rz =[ ];
  62. for(let o of config.value){
  63. rz.push({label:o.modelDescribe,value:o.modelName})
  64. }
  65. if(gptConfigStore.myData.userModel){
  66. let arr = gptConfigStore.myData.userModel.split(/[ ,]+/ig);
  67. for(let o of arr ){
  68. rz.push({label:o,value:o})
  69. }
  70. }
  71. //服务端的 CUSTOM_MODELS 设置
  72. if( homeStore.myData.session.cmodels ){
  73. let delModel:string[] = [];
  74. let addModel:string[]=[];
  75. homeStore.myData.session.cmodels.split(/[ ,]+/ig).map( (v:string)=>{
  76. if(v.indexOf('-')==0){
  77. delModel.push(v.substring(1))
  78. }else{
  79. addModel.push(v);
  80. }
  81. });
  82. mlog('cmodels',delModel,addModel);
  83. rz= rz.filter(v=> delModel.indexOf(v.value)==-1 );
  84. addModel.map(o=>rz.push({label:o,value:o}) )
  85. }
  86. let uniqueArray: { label: string, value: string }[] = Array.from(
  87. new Map(rz.map(item => [JSON.stringify(item), item]))
  88. .values()
  89. );
  90. return uniqueArray ;
  91. });
  92. const ms= useMessage();
  93. const saveChat=(type:string)=>{
  94. chatSet.save( nGptStore.value );
  95. gptConfigStore.setMyData( nGptStore.value );
  96. homeStore.setMyData({act:'saveChat'});
  97. if(type!='hide')ms.success( t('common.saveSuccess'));
  98. emit('close');
  99. }
  100. // 添加一个空选项
  101. const options = ref([]);
  102. const onSelectChange = (newValue: any) => {
  103. const option = options.value.find(optionValue => optionValue.value === newValue);
  104. nGptStore.value.kName = option.label;
  105. };
  106. const onSelectChange1 = (newValue: any) => {
  107. const option = modellist.value.find(optionValue => optionValue.value === newValue);
  108. nGptStore.value.modelLabel = option.label;
  109. };
  110. watch(()=>nGptStore.value.model,(n)=>{
  111. nGptStore.value.gpts=undefined;
  112. let max=4096;
  113. if( n.indexOf('vision')>-1){
  114. max=4096;
  115. }else if( n.indexOf('gpt-4')>-1 || n.indexOf('16k')>-1 ){ //['16k','8k','32k','gpt-4'].indexOf(n)>-1
  116. max=4096*2;
  117. }else if( n.toLowerCase().includes('claude-3') ){
  118. max=4096*2;
  119. }
  120. config.value.maxToken=max/2;
  121. if(nGptStore.value.max_tokens> config.value.maxToken ) nGptStore.value.max_tokens= config.value.maxToken;
  122. })
  123. const reSet=()=>{
  124. gptConfigStore.setInit();
  125. nGptStore.value= gptConfigStore.myData;
  126. }
  127. </script>
  128. <template>
  129. <section class="mb-5 justify-between items-center" >
  130. <div style="margin-bottom: 8px;"><span class="text-red-500">*</span> {{ $t('mjset.model') }}</div>
  131. <n-select class="change-select" v-model:value="nGptStore.model" :options="modellist" @update:value="onSelectChange1" size="small" />
  132. </section>
  133. <section class="mb-5 flex justify-between items-center" >
  134. <n-input class="change-select" :placeholder="$t('mjchat.modlePlaceholder')" v-model:value="nGptStore.userModel">
  135. <template #prefix>
  136. {{ $t('mjchat.myModle') }}
  137. </template>
  138. </n-input>
  139. </section>
  140. <section class="mb-5 justify-between items-center" >
  141. <div style="margin-bottom: 8px;">{{ $t('mjchat.knowledgeBase') }} </div>
  142. <n-select class="change-select" v-model:value="nGptStore.kid" :options="options" @update:value="onSelectChange" size="small" />
  143. </section>
  144. <section class=" flex justify-between items-center" >
  145. <div style="margin-bottom: 8px;"> {{ $t('mjchat.historyCnt') }}
  146. </div>
  147. <div class=" flex justify-end items-center w-[80%] max-w-[240px]">
  148. <div class=" w-[200px]"><n-slider class="change-slider" v-model:value="nGptStore.talkCount" :step="1" :max="50" /></div>
  149. <div class="w-[40px] text-right">{{ nGptStore.talkCount }}</div>
  150. </div>
  151. </section>
  152. <div class="mb-5 text-[12px] text-gray-300 dark:text-gray-300/20">{{ $t('mjchat.historyToken') }}</div>
  153. <section class=" flex justify-between items-center" >
  154. <div> {{ $t('mjchat.historyTCnt') }}
  155. </div>
  156. <div class=" flex justify-end items-center w-[80%] max-w-[240px]">
  157. <div class=" w-[200px]"><n-slider class="change-slider" v-model:value="nGptStore.max_tokens" :step="1" :max="1280000" :min="1" /></div>
  158. <div class="w-[100px] text-right">{{ nGptStore.max_tokens }}</div>
  159. </div>
  160. </section>
  161. <div class="mb-5 text-[16px] text-gray-300 dark:text-gray-300/20">{{ $t('mjchat.historyTCntInfo') }} </div>
  162. <section class="mb-5 change-select" >
  163. <div style="margin-bottom: 8px;">{{ $t('mjchat.role') }}</div>
  164. <div>
  165. <n-input type="textarea" :placeholder=" $t('mjchat.rolePlaceholder') " v-model:value="nGptStore.systemMessage" :autosize="{ minRows: 3 }"
  166. />
  167. </div>
  168. </section>
  169. <template v-if="st.openMore">
  170. <section class=" flex justify-between items-center " >
  171. <div>{{ $t('mj.temperature') }}</div>
  172. <div class=" flex justify-end items-center w-[80%] max-w-[240px]">
  173. <div class=" w-[200px]"><n-slider class="change-slider" v-model:value="nGptStore.temperature" :step="0.01" :max="1" /></div>
  174. <div class="w-[40px] text-right">{{ nGptStore.temperature }}</div>
  175. </div>
  176. </section>
  177. <div class="mb-5 text-[12px] text-gray-300 dark:text-gray-300/20"> {{ $t('mj.temperatureInfo') }}</div>
  178. <section class=" flex justify-between items-center " >
  179. <div> {{ $t('mj.top_p') }}</div>
  180. <div class=" flex justify-end items-center w-[80%] max-w-[240px]">
  181. <div class=" w-[200px]"><n-slider class="change-slider" v-model:value="nGptStore.top_p" :step="0.01" :max="1" /></div>
  182. <div class="w-[40px] text-right">{{ nGptStore.top_p }}</div>
  183. </div>
  184. </section>
  185. <div class="mb-5 text-[12px] text-gray-300 dark:text-gray-300/20">{{ $t('mj.top_pInfo') }}</div>
  186. <section class=" flex justify-between items-center " >
  187. <div> {{ $t('mj.presence_penalty') }}</div>
  188. <div class=" flex justify-end items-center w-[80%] max-w-[240px]">
  189. <div class=" w-[200px]"><n-slider class="change-slider" v-model:value="nGptStore.presence_penalty" :step="0.01" :max="1" /></div>
  190. <div class="w-[40px] text-right">{{ nGptStore.presence_penalty }}</div>
  191. </div>
  192. </section>
  193. <div class="mb-5 text-[12px] text-gray-300 dark:text-gray-300/20">{{ $t('mj.presence_penaltyInfo') }} </div>
  194. <section class=" flex justify-between items-center " >
  195. <div>{{ $t('mj.frequency_penalty') }}</div>
  196. <div class=" flex justify-end items-center w-[80%] max-w-[240px]">
  197. <div class=" w-[200px]"><n-slider class="change-slider" v-model:value="nGptStore.frequency_penalty" :step="0.01" :max="1" /></div>
  198. <div class="w-[40px] text-right">{{ nGptStore.frequency_penalty }}</div>
  199. </div>
  200. </section>
  201. <div class="mb-5 text-[12px] text-gray-300 dark:text-gray-300/20">{{ $t('mj.frequency_penaltyInfo') }}</div>
  202. <section class="mb-4 justify-between items-center change-select" >
  203. <div style="margin-bottom: 8px;">{{ $t('mj.tts_voice') }}</div>
  204. <n-select v-model:value="nGptStore.tts_voice" :options="voiceList" size="small" />
  205. </section>
  206. </template>
  207. <div v-else class="text-right cursor-pointer mb-4" @click="st.openMore=true">
  208. <NTag type="primary" round size="small" :bordered="false" class="!cursor-pointer">More...</NTag>
  209. </div>
  210. <section class=" text-right flex justify-end space-x-2 model-button" >
  211. <NButton :bordered="false" @click="reSet()">{{ $t('mj.setBtBack') }}</NButton>
  212. <!-- <NButton type="primary" @click="saveChat">{{ $t('mj.setBtSaveChat') }}</NButton>
  213. <NButton type="primary" @click="save">{{ $t('mj.setBtSaveSys') }}</NButton> -->
  214. <NButton :bordered="false" @click="saveChat('no')">{{ $t('common.save') }}</NButton>
  215. </section>
  216. </template>