Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bot api doc #525

Merged
merged 2 commits into from
Sep 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion web/src/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"common": {
"ask_user_register": "请注册, 只有注册账号才能继续对话",
"help": "第一条是主题(prompt, 角色定义), 上下文默认包括10条信息, 参数可以点击按钮进行调节, 请务必注意隐私, 不输入涉密, 敏感信息.",
"copy": "复制",
"edit": "编辑",
"delete": "删除",
"save": "保存",
Expand Down Expand Up @@ -40,7 +41,8 @@
"list": "机器人列表",
"all": {
"title": "机器人列表"
}
},
"showCode": "生成API调用代码"
},
"chat": {
"new": "新对话",
Expand Down
56 changes: 56 additions & 0 deletions web/src/service/snapshot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { displayLocaleDate, formatYearMonth } from '@/utils/date'





export function generateAPIHelper(uuid: string, apiToken: string, origin: string) {
const data = {
"message": "Your message here",
"snapshot_uuid": uuid,
"stream": false,
}
return `curl -X POST ${origin}/api/chatbot -H "Content-Type: application/json" -H "Authorization: Bearer ${apiToken}" -d '${JSON.stringify(data)}'`
}

export function getChatbotPosts(posts: Snapshot.Snapshot[]) {
return posts
.filter((post: Snapshot.Snapshot) => post.typ === 'chatbot')
.map((post: Snapshot.Snapshot): Snapshot.PostLink => ({
uuid: post.uuid,
date: displayLocaleDate(post.createdAt),
title: post.title,
}))
}

export function getSnapshotPosts(posts: Snapshot.Snapshot[]) {
return posts
.filter((post: Snapshot.Snapshot) => post.typ === 'snapshot')
.map((post: Snapshot.Snapshot): Snapshot.PostLink => ({
uuid: post.uuid,
date: displayLocaleDate(post.createdAt),
title: post.title,
}))
}

export function postsByYearMonthTransform(posts: Snapshot.PostLink[]) {
const init: Record<string, Snapshot.PostLink[]> = {}
return posts.reduce((acc, post) => {
const yearMonth = formatYearMonth(new Date(post.date))
if (!acc[yearMonth])
acc[yearMonth] = []

acc[yearMonth].push(post)
return acc
}, init)
}

export function getSnapshotPostLinks(snapshots: Snapshot.Snapshot[]): Record<string, Snapshot.PostLink[]> {
const snapshotPosts = getSnapshotPosts(snapshots)
return postsByYearMonthTransform(snapshotPosts)
}

export function getBotPostLinks(bots: Snapshot.Snapshot[]): Record<string, Snapshot.PostLink[]> {
const chatbotPosts = getChatbotPosts(bots)
return postsByYearMonthTransform(chatbotPosts)
}
20 changes: 20 additions & 0 deletions web/src/typings/chat.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,24 @@ declare namespace Chat {
userEmail: string
rateLimit: string
}


}

declare namespace Snapshot {

interface Snapshot {
uuid: string;
title: string;
summary: string;
tags: Record<string, unknown>;
createdAt: string;
typ: 'chatbot' | 'snapshot';
}

interface PostLink {
uuid: string;
date: string;
title: string;
}
}
119 changes: 65 additions & 54 deletions web/src/views/bot/all.vue
Original file line number Diff line number Diff line change
@@ -1,56 +1,42 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { onMounted, ref, h } from 'vue'
import { NModal, useDialog, useMessage } from 'naive-ui'
import Search from '../snapshot/components/Search.vue'
import { fetchSnapshotAll, fetchSnapshotDelete } from '@/api'
import { displayLocaleDate, formatYearMonth } from '@/utils/date'
import { HoverButton, SvgIcon } from '@/components/common'
import { generateAPIHelper, getBotPostLinks } from '@/service/snapshot'
import request from '@/utils/request/axios'
import { t } from '@/locales'
const dialog = useDialog()
const nui_msg = useMessage()
const search_visible = ref(false)

interface PostLink {
uuid: string
date: string
title: string
}

function post_url(uuid: string): string {
return `#/bot/${uuid}`
}
const search_visible = ref(false)
const apiToken = ref('')

const postsByYearMonth = ref<Record<string, PostLink[]>>({})
const postsByYearMonth = ref<Record<string, Snapshot.PostLink[]>>({})

function postsByYearMonthTransform(posts: PostLink[]) {
const init: Record<string, PostLink[]> = {}
return posts.reduce((acc, post) => {
const yearMonth = formatYearMonth(new Date(post.date))
if (!acc[yearMonth])
acc[yearMonth] = []
onMounted(async () => {
await refreshSnapshot()
try {
const response = await request.get('/token_10years')
if (response.status === 200) {
apiToken.value = response.data.accessToken
}
else {
nui_msg.error('Failed to fetch API token')
}
} catch (error) {
nui_msg.error('Error fetching API token')
}
})

acc[yearMonth].push(post)
return acc
}, init)
}

async function getPostLinks() {
const rawPosts = await fetchSnapshotAll()
const rawPostsFormated = rawPosts.filter( (post: any) => post.typ === 'chatbot').map((post: any) => {
return {
uuid: post.uuid,
date: displayLocaleDate(post.createdAt),
title: post.title,
}
})
return postsByYearMonthTransform(rawPostsFormated)
async function refreshSnapshot() {
const bots: Snapshot.Snapshot[] = await fetchSnapshotAll()
postsByYearMonth.value = getBotPostLinks(bots)
}

onMounted(async () => {
postsByYearMonth.value = await getPostLinks()
})

function handleDelete(post: PostLink) {
function handleDelete(post: Snapshot.PostLink) {
const dialogBox = dialog.warning({
title: t('chat_snapshot.deletePost'),
content: post.title,
Expand All @@ -60,7 +46,7 @@ function handleDelete(post: PostLink) {
try {
dialogBox.loading = true
await fetchSnapshotDelete(post.uuid)
postsByYearMonth.value = await getPostLinks()
await refreshSnapshot()
dialogBox.loading = false
nui_msg.success(t('chat_snapshot.deleteSuccess'))
Promise.resolve()
Expand All @@ -74,20 +60,43 @@ function handleDelete(post: PostLink) {
},
})
}


function handleShowCode(post: Snapshot.PostLink) {
const dialogBox = dialog.info({
title: t('bot.showCode'),
content: () => h('code', { class: 'whitespace-pre-wrap' }, genAPIHelper(post)),
positiveText: t('common.copy'),
onPositiveClick: () => {
// copy to clipboard
navigator.clipboard.writeText(genAPIHelper(post))
dialogBox.loading = false
nui_msg.success(t('common.success'))
},
})
}


function post_url(uuid: string): string {
return `#/bot/${uuid}`
}

function genAPIHelper(post: Snapshot.PostLink) {
return generateAPIHelper(post.uuid, apiToken.value, window.location.origin)
}


</script>

<template>
<div class="flex flex-col w-full h-full dark:text-white">
<header class="flex items-center justify-between h-16 z-30 border-b dark:border-neutral-800 bg-white/80 dark:bg-black/20 dark:text-white backdrop-blur">
<header
class="flex items-center justify-between h-16 z-30 border-b dark:border-neutral-800 bg-white/80 dark:bg-black/20 dark:text-white backdrop-blur">
<div class="flex items-center ml-10">
<svg
class="w-8 h-8 mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
/>
<svg class="w-8 h-8 mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<h1 class="text-xl font-semibold text-gray-900">
{{ $t('bot.all.title') }}
Expand All @@ -104,7 +113,8 @@ function handleDelete(post: PostLink) {
</header>
<div id="scrollRef" ref="scrollRef" class="h-full overflow-hidden overflow-y-auto">
<div class="max-w-screen-xl px-4 py-8 mx-auto">
<div v-for="[yearMonth, postsOfYearMonth] in Object.entries(postsByYearMonth)" :key="yearMonth" class="flex mb-2">
<div v-for="[yearMonth, postsOfYearMonth] in Object.entries(postsByYearMonth)" :key="yearMonth"
class="flex mb-2">
<h2 class="flex-none w-28 text-lg font-medium">
{{ yearMonth }}
</h2>
Expand All @@ -114,15 +124,16 @@ function handleDelete(post: PostLink) {
<div class="flex">
<time :datetime="post.date" class="mb-1 text-sm font-medium text-gray-600">{{
post.date
}}</time>
}}</time>
<div class="ml-2 text-sm" @click="handleDelete(post)">
<SvgIcon icon="ic:baseline-delete-forever" />
</div>
<div class="ml-4 cursor-pointer" @click="handleShowCode(post)">
<SvgIcon icon="ic:outline-code" />
</div>
</div>
<a
:href="post_url(post.uuid)" :title="post.title"
class="block text-xl font-semibold text-gray-900 hover:text-blue-600 mb-2"
>{{ post.title }}</a>
<a :href="post_url(post.uuid)" :title="post.title"
class="block text-xl font-semibold text-gray-900 hover:text-blue-600 mb-2">{{ post.title }}</a>
</div>
</li>
</ul>
Expand Down
45 changes: 10 additions & 35 deletions web/src/views/snapshot/all.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,29 @@ import { onMounted, ref } from 'vue'
import { NModal, useDialog, useMessage } from 'naive-ui'
import Search from './components/Search.vue'
import { fetchSnapshotAll, fetchSnapshotDelete } from '@/api'
import { displayLocaleDate, formatYearMonth } from '@/utils/date'
import { HoverButton, SvgIcon } from '@/components/common'
import { getSnapshotPostLinks } from '@/service/snapshot'
import { t } from '@/locales'
const dialog = useDialog()
const nui_msg = useMessage()
const search_visible = ref(false)

interface PostLink {
uuid: string
date: string
title: string
}

function post_url(uuid: string): string {
return `#/snapshot/${uuid}`
}

const postsByYearMonth = ref<Record<string, PostLink[]>>({})

function postsByYearMonthTransform(posts: PostLink[]) {
const init: Record<string, PostLink[]> = {}
return posts.reduce((acc, post) => {
const yearMonth = formatYearMonth(new Date(post.date))
if (!acc[yearMonth])
acc[yearMonth] = []

acc[yearMonth].push(post)
return acc
}, init)
}

async function getPostLinks() {
const rawPosts = await fetchSnapshotAll()
const rawPostsFormated = rawPosts.filter( (post: any) => post.typ === 'snapshot' ).map((post: any) => {
return {
uuid: post.uuid,
date: displayLocaleDate(post.createdAt),
title: post.title,
}
})
return postsByYearMonthTransform(rawPostsFormated)
}
const postsByYearMonth = ref<Record<string, Snapshot.PostLink[]>>({})

onMounted(async () => {
postsByYearMonth.value = await getPostLinks()
await refreshSnapshot()
})

function handleDelete(post: PostLink) {
async function refreshSnapshot() {
const snapshots: Snapshot.Snapshot[] = await fetchSnapshotAll()
postsByYearMonth.value = getSnapshotPostLinks(snapshots)
}

function handleDelete(post: Snapshot.PostLink) {
const dialogBox = dialog.warning({
title: t('chat_snapshot.deletePost'),
content: post.title,
Expand All @@ -60,7 +35,7 @@ function handleDelete(post: PostLink) {
try {
dialogBox.loading = true
await fetchSnapshotDelete(post.uuid)
postsByYearMonth.value = await getPostLinks()
await refreshSnapshot()
dialogBox.loading = false
nui_msg.success(t('chat_snapshot.deleteSuccess'))
Promise.resolve()
Expand Down
Loading