Skip to content

Commit

Permalink
Merge pull request #1128 from TencentBlueKing/develop
Browse files Browse the repository at this point in the history
v1.13 merge develop to master
  • Loading branch information
ielgnaw committed Oct 20, 2023
2 parents fbc6586 + 6b82f80 commit 370b424
Show file tree
Hide file tree
Showing 258 changed files with 44,057 additions and 1,802 deletions.
181 changes: 137 additions & 44 deletions lib/client/src/common/ai.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import {
isJSON
} from './util'

const emptyFunction = () => {}

export class Ai {
constructor ({
handlerStart,
Expand All @@ -7,23 +12,32 @@ export class Ai {
handleMessage,
handleApiError,
handleCmdError,
systemPrompt
systemPrompt,
needCmd,
type
}) {
// event
this.handlerStart = handlerStart
this.handleEnd = handleEnd
this.handleCmd = handleCmd
this.handleMessage = handleMessage
this.handleApiError = handleApiError
this.handleCmdError = handleCmdError
this.handlerStart = handlerStart || emptyFunction
this.handleEnd = handleEnd || emptyFunction
this.handleCmd = handleCmd || emptyFunction
this.handleMessage = handleMessage || emptyFunction
this.handleApiError = handleApiError || emptyFunction
this.handleCmdError = handleCmdError || emptyFunction

// Prompt
this.systemPrompt = systemPrompt
this.inputs = []

// type
this.type = type
this.needCmd = needCmd

// content
this.content = ''

// controllers
this.controllers = []

// init
this.pushPrompt(systemPrompt, 'system')
}
Expand All @@ -48,29 +62,30 @@ export class Ai {
this.handleMessage(aiMessage, this.content)
}

endReceiveMessage () {
async endReceiveMessage () {
this.pushPrompt(this.content, 'assistant')
// 触发指令
const cmdIndex = this.content.indexOf('``')
const cmdMessage = this.content.slice(cmdIndex)
if (cmdIndex > -1 && !/(cmd(?:\d)?): (?:<)?([^>\n]+)(?:>)?/gmi.test(cmdMessage)) {
this.chart('It looks like the command is not formatted correctly, please rethink and issue commands')
if (this.needCmd && cmdIndex > -1 && !/(cmd(?:\d)?): (?:<)?([^>\n]+)(?:>)?/gmi.test(cmdMessage)) {
this.chatStream('It looks like the command is not formatted correctly, please rethink and issue commands')
return
}
const exp = /(cmd(?:\d)?): (?:<)?([^>\n]+)(?:>)?/gmi
const exp = /(cmd(?:\d)?): (?:<)?([^\n]+\))(?:>)?/gmi
let result
let errorCmd
try {
do {
result = exp.exec(cmdMessage)
if (result) {
this.handleCmd(result[1], result[2])
}
} while (result)
} catch (error) {
errorCmd = result[2]
if (this.needCmd) {
try {
do {
result = exp.exec(cmdMessage)
if (result) {
await this.handleCmd(result[1], result[2])
}
} while (result)
} catch (error) {
errorCmd = result[2]
}
}
this.content = ''
// trigger end
if (errorCmd) {
this.handleCmdError(errorCmd)
Expand All @@ -79,7 +94,7 @@ export class Ai {
}
}

chat (message) {
chatStream (message) {
// push user prompt
this.pushPrompt(message, 'user')
// api
Expand All @@ -88,7 +103,7 @@ export class Ai {
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ inputs: this.inputs })
body: JSON.stringify({ inputs: this.inputs, type: this.type })
}).then(async response => {
const reader = response.body
.pipeThrough(new window.TextDecoderStream())
Expand All @@ -97,36 +112,114 @@ export class Ai {
// trigger start
this.handlerStart()

this.content = ''

// 临时存储数据
let temp = ''

while (true) {
const { value, done } = await reader.read()
if (done) break
const values = (temp + value.toString()).split(/(?<=})\s*(?={\"errors\")/)
values.forEach((value) => {
const item = value.trim()
if (item.startsWith('{') && item.endsWith('}')) {
const {
data,
message
} = JSON.parse(item)
if (data?.status === 'success') {
const choice = JSON.parse(data?.data?.[0]?.output?.[0]?.output)?.choices[0] || {}
if (!choice?.finish_reason) {
this.receiveMessage(choice?.delta?.content)
try {
const { value, done } = await reader.read()
if (done) break
const values = (temp + value.toString()).split(/(?<=})\s*(?={"result")/)
values.forEach((value) => {
const item = value.trim()
if (isJSON(item)) {
const {
result,
data,
message
} = JSON.parse(item)
if (result === true) {
const choice = data?.result?.choices?.[0]
if (!choice) {
this.handleApiError('模型调用失败,返回对象为空')
} else if (choice.finish_reason) {
this.endReceiveMessage()
} else if (choice.delta.content) {
this.receiveMessage(choice.delta.content)
}
} else {
this.endReceiveMessage()
this.handleApiError(message || '模型调用失败')
}
} else {
this.handleApiError(message || '调用 aiops 接口失败')
temp = ''
} else if (item) {
temp = item
}
temp = ''
} else if (item) {
temp = item
})
} catch (error) {
if (error?.code !== 20) {
this.handleApiError(`模型调用失败:${error.message}`)
}
})
break
}
}
})
}

chat (message) {
// push user prompt
this.pushPrompt(message, 'user')
this.handlerStart()
this.content = ''
return fetch('/api/ai/chat', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ inputs: this.inputs, type: this.type })
}).then(async response => {
const data = await response.json()
if (data?.result) {
const choice = data?.data?.result?.choices?.[0]
if (!choice) {
this.handleApiError('模型调用失败,返回对象为空')
} else {
this.receiveMessage(choice.message.content)
this.endReceiveMessage()
}
} else {
this.handleApiError(`模型调用失败:${data?.message}`)
}
}).catch((error) => {
this.handleApiError(`模型调用失败:${error.message}`)
})
}

code (prompt, promptSuffix, lang) {
this.handlerStart()
this.content = ''
const controller = new AbortController()
this.controllers.push(controller)
return fetch('/api/ai/code', {
method: 'post',
signal: controller.signal,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ prompt, promptSuffix, lang })
}).then(async response => {
const data = await response.json()
if (data?.result) {
const result = data?.data?.[0]?.result
if (!result) {
this.handleApiError('模型调用失败,返回对象为空')
} else {
this.receiveMessage(result)
this.endReceiveMessage()
}
} else {
this.handleApiError(`模型调用失败:${data?.message}`)
}
}).catch((error) => {
this.handleApiError(`模型调用失败:${error.message}`)
})
}

stop () {
this.controllers.forEach((controller) => {
controller?.abort?.()
})
this.handleEnd()
}
}
57 changes: 57 additions & 0 deletions lib/client/src/common/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -967,3 +967,60 @@ export function renderHeaderAddTitle (h, data) {
data.column.label
)
}

export const cssProperties = [
'align-content',
'align-items',
'align-self',
'animation',
'background',
'background-color',
'border',
'border-bottom',
'border-color',
'border-radius',
'border-style',
'bottom',
'box-shadow',
'color',
'column-count',
'cursor',
'display',
'flex',
'flex-basis',
'flex-direction',
'flex-flow',
'flex-shrink',
'font',
'font-family',
'font-size',
'font-weight',
'height',
'justify-content',
'letter-spacing',
'line-height',
'margin',
'max-height',
'max-width',
'min-height',
'min-width',
'opacity',
'overflow',
'padding',
'position',
'text-align',
'text-decoration',
'text-transform',
'transition',
'width',
'z-index'
]

export const isJSON = (str) => {
try {
JSON.parse(str)
return true
} catch (e) {
return false
}
}
4 changes: 4 additions & 0 deletions lib/client/src/common/vant.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import { Button,
TabbarItem,
Sidebar,
SidebarItem,
Grid,
GridItem,
Popup } from 'vant'
import 'vant/lib/index.css'

Expand Down Expand Up @@ -82,6 +84,8 @@ Vue.use(TabbarItem)
Vue.use(Sidebar)
Vue.use(SidebarItem)
Vue.use(Popup)
Vue.use(Grid)
Vue.use(GridItem)

// Vue.use(Calendar)
Vue.use(Lazyload)
24 changes: 22 additions & 2 deletions lib/client/src/components/changelog-version/changelog-data.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
export default [
{
date: '2023.10.18',
detailList: [
{
reviseTitle: window.i18n.t('新增'),
logMassage: [
window.i18n.t('应用: markdown类型页面以组件形式整合到自定义页面'),
window.i18n.t('函数: 代码编辑器支持代码提示跟代码生成'),
window.i18n.t('数据源: 数据管理模块支持自然语言描述生成SQL'),
window.i18n.t('移动端: 新增宫格布局'),
window.i18n.t('移动端: 新增简易tab组件'),
window.i18n.t('画布: transfer, cascade, process, big-tree等组件可配置对应的实际使用字段跟展示字段'),
window.i18n.t('画布: ai对话框增加常用提示模板'),
window.i18n.t('画布: 支持事件行为跟自然语言描述生成事件'),
window.i18n.t('画布: 可切换类型的组件 value值设置及校验需要和类型一致')

]
}
]
},
{
date: '2023.08.31',
detailList: [
Expand All @@ -9,13 +29,13 @@ export default [
window.i18n.t('应用: 发布部署模块页面重构'),
window.i18n.t('移动端: 新增侧边导航'),
window.i18n.t('画布: 页面内置边距回显到页面样式的padding属性'),
window.i18n.t('画布: 组件属性面板支持搜索'),
window.i18n.t('画布: 组件属性面板支持搜索')
]
}, {
reviseTitle: window.i18n.t('修复'),
logMassage: [
window.i18n.t('画布: 当页面模板中含有tab组件时,应用页面模板失败'),
window.i18n.t('应用: 国际化相关样式修复'),
window.i18n.t('应用: 国际化相关样式修复')
]
}
]
Expand Down
Loading

0 comments on commit 370b424

Please sign in to comment.