提交 60f0b3a8 编写于 作者: Y y3808080

Sat Sep 14 20:05:00 CST 2024 inscode

上级 2f824fdb
<template>
<div class="container ivu-p">
<div class="dialog">
<template v-for="(item, index) in dialogs" :key="index">
<div class="dialog-item" :class="{ 'dialog-item-me': item.role === 'me', 'dialog-item-ai': item.role === 'ai' }">
<div class="dialog-item-main">{{ item.text }}</div>
</div>
</template>
</div>
<div class="question ivu-mt">
<Input v-model="question" type="textarea" :autosize="{ minRows: 4, maxRows: 6 }" placeholder="输入内容..." />
<Row class="ivu-mt">
<Col>
<Button type="primary" size="large" icon="md-send" :loading="loading" @click="handleSend">发送</Button>
</Col>
<Col>
<Button size="large" class="ivu-ml" icon="md-add" :disabled="loading" @click="handleNewChat">新对话</Button>
</Col>
<Col>
<Button size="large" class="ivu-ml" icon="md-settings" :disabled="loading" @click="handleOpenPrompt">设置 Prompt</Button>
</Col>
</Row>
<Typography class="ivu-text-center ivu-m">
Powered By <img src="./assets/logo.png" class="logo"> <a href="https://inscode.net" target="_blank">InsCode.net</a>
</Typography>
</div>
<Modal v-model="showPrompt" title="设置 Prompt" footer-hide :styles="{top: '20px'}">
<Title :level="4">Prompt:</Title>
<Input v-model="prompt" type="textarea" :autosize="{minRows: 3,maxRows: 5}" placeholder="例如:写一个策划,主题是_____" />
<Title class="ivu-mt" :level="4">推荐:</Title>
<Space :wrap="true">
<Button @click="handleSetPrompt('写一篇140字以内的朋友圈配文,语言风格要浪漫文艺的,主题是__________')">朋友圈神器</Button>
<Button @click="handleSetPrompt('你现在需要扮演一个高情商、幽默的人,去参加一些聚会社交,请帮我回应接下来的问题,__________')">高情商回复</Button>
<Button @click="handleSetPrompt('请根据 C++ 题目来编写一个能通过此题目的程序,题面是:___________')">洛谷神器</Button>
<Button @click="handleSetPrompt('请和我在线聊天。__________')">聊聊天</Button>
<Button @click="handleSetPrompt('你现在需要扮演一个高情商、幽默的人,去参加一些聚会社交,请帮我回应接下来的问题,__________')">高情商回复</Button>
<Button @click="handleSetPrompt('我是你的专属心理咨询师,你有什么想咨询的么?')">心理咨询师</Button>
</Space>
<Title class="ivu-mt" :level="4">操作:</Title>
<Button icon="md-trash" @click="handleClearPrompt">清空 Prompt</Button>
<Button size="large" type="primary" long class="ivu-mt" @click="handleSavePrompt">保存</Button>
</Modal>
</div>
</template>
<script>
import { fetchEventSource } from '@microsoft/fetch-event-source';
import { apiKey, apiUrl } from './api';
let prompt = '';
export default {
data() {
return {
question: '',
loading: false,
dialogs: [],
prompt: '',
showPrompt: false
}
},
methods: {
handleSend() {
if (this.loading || this.question === '') return;
this.loading = true;
const question = this.question;
this.question = '';
this.dialogs.push({
id: this.dialogs.length + 1,
role: 'me',
text: question
});
const aiDialogID = this.dialogs.length + 1;
this.dialogs.push({
id: aiDialogID,
role: 'ai',
text: 'AI 思考中...'
});
const dialog = this.dialogs.find(item => item.id === aiDialogID);
/**
* 发送请求,InsCode 已经集成了 GPT 能力
* 在 vite.config.js 中已通过环境变量写入了 apiKey(该 key 是动态写入使用者的,在 IDE 中是作者,发布到社区是运行该作品的用户)
* 发布到社区后,将消耗运行者的额度
* 注意:如果部署应用,任何人通过部署后的域名访问应用时,都将消耗部署者的额度
*/
const body = {
messages: [
{
role: 'user',
content: prompt + question
}
],
apikey: apiKey
}
const source = fetchEventSource(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(body),
onopen: (response) => {
dialog.text = '';
},
onmessage: (msg) => {
if (msg.data === '[DONE]') {
this.loading = false;
return;
};
const data = JSON.parse(msg.data);
const finish_reason = data.choices[0].finish_reason;
const finish = finish_reason === 'stop' || finish_reason === 'length';
const content = data.choices[0].delta.content;
if (finish) {
this.loading = false;
} else if (content) {
const text = content;
dialog.text += text;
}
},
onerror: (err) => {
console.log("error", err);
}
});
},
handleNewChat() {
this.dialogs = [];
},
handleOpenPrompt () {
this.showPrompt = true;
},
handleSetPrompt (prompt) {
this.prompt = prompt;
},
handleSavePrompt () {
if (!this.prompt) {
this.$Message.error({
content: '提示词内容不能为空',
duration: 3,
background: true
});
} else {
const prompt = this.prompt;
localStorage.setItem('setting-prompt', prompt);
this.showPrompt = false;
this.handleLoadPrompt();
}
},
handleLoadPrompt () {
const localPrompt = localStorage.getItem('setting-prompt');
if (localPrompt) {
this.prompt = localPrompt;
prompt = localPrompt;
this.$nextTick(() => {
this.$Message.success({
content: '已加载 Prompt',
background: true
});
});
}
},
handleClearPrompt () {
localStorage.removeItem('setting-prompt');
this.prompt = '';
prompt = '';
this.$nextTick(() => {
this.$Message.success({
content: '已清空 Prompt',
background: true
});
});
}
},
mounted () {
this.handleLoadPrompt();
}
}
</script>
<style>
.container {
height: 100%;
display: flex;
flex-direction: column;
}
.dialog {
flex: 1;
overflow: auto;
}
.dialog-item {
display: flex;
}
.dialog-item-main {
max-width: 80%;
padding: 8px;
word-wrap: break-word;
margin-top: 16px;
border-radius: 4px;
}
.dialog-item-me {
justify-content: flex-end;
}
.dialog-item-me .dialog-item-main {
background-color: antiquewhite;
}
.dialog-item-ai .dialog-item-main {
background-color: #eee;
}
.logo{
width: 16px;
height: 16px;
vertical-align: middle;
position: relative;
top: -1px;
}
</style>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册