-
Notifications
You must be signed in to change notification settings - Fork 211
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
ryan
committed
Feb 14, 2025
1 parent
98a1525
commit 4a2409e
Showing
110 changed files
with
7,871 additions
and
2 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// app.js | ||
App({ | ||
onLaunch: function () { | ||
if (!wx.cloud) { | ||
console.error("请使用 2.2.3 或以上的基础库以使用云能力"); | ||
} else { | ||
wx.cloud.init({ | ||
// env 参数说明: | ||
// env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源 | ||
// 此处请填入环境 ID, 环境 ID 可打开云控制台查看 | ||
// 如不填则使用默认环境(第一个创建的环境) | ||
env: "lowcode-1gm3ep4m027742a2", | ||
traceUser: true, | ||
}); | ||
} | ||
|
||
this.globalData = {}; | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"pages": [ | ||
"pages/index/index", | ||
"pages/chatBot/chatBot" | ||
], | ||
"window": { | ||
"navigationBarBackgroundColor": "#ffffff", | ||
"navigationBarTextStyle": "black", | ||
"navigationBarTitleText": "腾讯云开发Agent-UI", | ||
"backgroundColor": "#eeeeee", | ||
"backgroundTextStyle": "light", | ||
"enablePullDownRefresh": true | ||
}, | ||
"sitemapLocation": "sitemap.json", | ||
"style": "v2", | ||
"lazyCodeLoading": "requiredComponents" | ||
} |
Empty file.
Binary file added
BIN
+637 Bytes
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/imgs/clear.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+715 Bytes
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/imgs/copy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.18 KB
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/imgs/down.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+940 Bytes
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/imgs/send.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1008 Bytes
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/imgs/set.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+838 Bytes
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/imgs/share.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.36 KB
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/imgs/share1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+973 Bytes
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/imgs/star.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1006 Bytes
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/imgs/star_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1021 Bytes
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/imgs/stop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
219 changes: 219 additions & 0 deletions
219
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
// components/agent-ui/index.js | ||
import { guide, checkConfig } from './tools' | ||
Component({ | ||
properties: { | ||
agentConfig: { | ||
type: Object, | ||
value: { | ||
type: "", // 值为'bot'或'model'。当type='bot'时,botId必填;当type='model'时,model必填 | ||
botId: "", // agent id | ||
modelName: "", // 大模型服务商 | ||
model: "", // 具体的模型版本 | ||
logo: "",// 图标(只在model模式下生效) | ||
welcomeMessage: ""// 欢迎语(只在model模式下生效) | ||
} | ||
} | ||
}, | ||
|
||
data: { | ||
isLoading: true, // 判断是否尚在加载中 | ||
article: {}, | ||
windowInfo: wx.getWindowInfo(), | ||
bot: {}, | ||
inputValue: '', | ||
output: "", | ||
chatRecords: [], | ||
scrollTop: 0, | ||
streamStatus: false, | ||
setPanelVisibility: false, | ||
questions: [], | ||
scrollTop: 0, | ||
guide, | ||
showGuide: false | ||
}, | ||
|
||
attached: async function () { | ||
const { botId, type } = this.data.agentConfig | ||
const [check, message] = checkConfig(this.data.agentConfig) | ||
if (!check) { | ||
wx.showModal({ | ||
title: '提示', | ||
content: message, | ||
}) | ||
this.setData({ showGuide: true }) | ||
} else { | ||
this.setData({ showGuide: false }) | ||
} | ||
if (type === 'bot') { | ||
const ai = wx.cloud.extend.AI | ||
const bot = await ai.bot.get({ botId }) | ||
this.setData({ bot, questions: bot.initQuestions }) | ||
return; | ||
} | ||
}, | ||
methods: { | ||
bindKeyInput: function (e) { | ||
this.setData({ | ||
inputValue: e.detail.value | ||
}) | ||
}, | ||
clearChatRecords: function () { | ||
this.setData({ chatRecords: [], streamStatus: false, setPanelVisibility: !this.data.setPanelVisibility }) | ||
}, | ||
stop: function () { | ||
const { chatRecords } = this.data | ||
const newChatRecords = [...chatRecords] | ||
const record = newChatRecords[newChatRecords.length - 1] | ||
if (record.content === '...') { | ||
record.content = '已暂停回复' | ||
} | ||
this.setData({ streamStatus: false, chatRecords: newChatRecords }) | ||
}, | ||
openSetPanel: function () { | ||
this.setData({ setPanelVisibility: true }) | ||
}, | ||
closeSetPanel: function () { | ||
this.setData({ setPanelVisibility: false }) | ||
}, | ||
sendMessage: async function (event) { | ||
const { message } = event.currentTarget.dataset | ||
let { inputValue, bot, agentConfig } = this.data | ||
if (message) { | ||
inputValue = message | ||
} | ||
if (!inputValue) { | ||
return; | ||
} | ||
const { type, modelName, model } = agentConfig | ||
// console.log(inputValue,bot.botId) | ||
const userRecord = { | ||
content: inputValue, | ||
record_id: 'record_id' + String(+new Date() - 10), | ||
role: "user" | ||
} | ||
const record = { | ||
content: "...", | ||
record_id: 'record_id' + String(+new Date() + 10), | ||
role: "assistant" | ||
} | ||
this.setData({ inputValue: "", questions: [], chatRecords: [...this.data.chatRecords, userRecord, record], streamStatus: false }) | ||
// 先这样写,后面抽离出来 | ||
if (type === 'bot') { | ||
const ai = wx.cloud.extend.AI | ||
const res = await ai.bot.sendMessage({ | ||
data: { | ||
botId: bot.botId, | ||
history: [], | ||
msg: inputValue, | ||
} | ||
}) | ||
this.setData({ streamStatus: true }) | ||
let contentText = "" | ||
let reasoningText = "" | ||
for await (let event of res.eventStream) { | ||
if (!this.data.streamStatus) { | ||
break; | ||
} | ||
this.toBottom() | ||
const { data } = event | ||
try { | ||
const dataJson = JSON.parse(data) | ||
// console.log(dataJson) | ||
const { content, reasoning_content, record_id } = dataJson | ||
contentText += content | ||
reasoningText += reasoning_content | ||
const newValue = [...this.data.chatRecords] | ||
newValue[newValue.length - 1] = { record_id, role: dataJson.role || 'assistant', content: contentText, reasoning_content: reasoningText } | ||
this.setData({ chatRecords: newValue }) | ||
} catch (e) { | ||
// console.log('err', event, e) | ||
break; | ||
} | ||
} | ||
this.setData({ streamStatus: false }) | ||
if (bot.isNeedRecommend) { | ||
const ai = wx.cloud.extend.AI | ||
const recommendRes = await ai.bot.getRecommendQuestions({ | ||
data: { | ||
botId: bot.botId, | ||
history: [], | ||
msg: inputValue, | ||
agentSetting: "", | ||
introduction: "", | ||
name: "", | ||
} | ||
}) | ||
let result = '' | ||
for await (let str of recommendRes.textStream) { | ||
// console.log(str); | ||
this.toBottom() | ||
result += str | ||
this.setData({ questions: result.split('\n').filter(item => !!item) }) | ||
} | ||
} | ||
} | ||
if (type === 'model') { | ||
const aiModel = wx.cloud.extend.AI.createModel(modelName); | ||
const res = await aiModel.streamText({ | ||
data: { | ||
model: model, | ||
messages: [{ | ||
role: "user", | ||
content: inputValue | ||
}], | ||
}, | ||
}); | ||
let contentText = '' | ||
let reasoningText = '' | ||
this.setData({ streamStatus: true }) | ||
for await (let event of res.eventStream) { | ||
if (!this.data.streamStatus) { | ||
break; | ||
} | ||
this.toBottom() | ||
|
||
const { data } = event | ||
try { | ||
const dataJson = JSON.parse(data) | ||
const { id, choices = [] } = dataJson || {} | ||
const { delta, finish_reason } = choices[0] || {} | ||
if (finish_reason === 'stop') { | ||
break | ||
} | ||
const { content, reasoning_content, role } = delta | ||
reasoningText += (reasoning_content || '') | ||
contentText += (content || '') | ||
const newValue = [...this.data.chatRecords] | ||
newValue[newValue.length - 1] = { | ||
content: contentText, | ||
reasoning_content: reasoningText, | ||
record_id: 'record_id' + String(id), | ||
role: role | ||
} | ||
this.setData({ chatRecords: newValue }) | ||
} catch (e) { | ||
// console.log(e, event) | ||
break; | ||
} | ||
} | ||
this.setData({ streamStatus: false }) | ||
} | ||
}, | ||
toBottom: function () { | ||
this.setData({ scrollTop: this.data.scrollTop + 4 }) | ||
}, | ||
copyChatRecord: function (e) { | ||
// console.log(e) | ||
const { content } = e.currentTarget.dataset | ||
wx.setClipboardData({ | ||
data: content + '\n\n来自微信云开发AI+', | ||
success: function (res) { | ||
wx.showToast({ | ||
title: '复制成功', | ||
icon: 'success' | ||
}); | ||
} | ||
}); | ||
} | ||
} | ||
}) |
6 changes: 6 additions & 0 deletions
6
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/index.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"component": true, | ||
"usingComponents": { | ||
"markdownPreview":"/components/agent-ui/markdownPreview/index" | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
miniprogram/tcb-agent-ui/miniprogram/components/agent-ui/index.wxml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<!-- agent ui 组件根容器 --> | ||
<view class="agent-ui"> | ||
<!-- 聊天对话区 --> | ||
<scroll-view class="main" style="height: {{windowInfo.windowHeight-80}}px;" scroll-y="{{true}}" bind:tap="toBottom" scroll-top="{{scrollTop}}"> | ||
<view class="nav"> | ||
<image src="{{bot.avatar||agentConfig.logo}}" mode="aspectFill" class="avatar" /> | ||
<view style="line-height: 47px;">{{agentConfig.type==='bot'?bot.name:agentConfig.modelName}}</view> | ||
<view style="line-height: 26px;padding: 0px 16px;">{{agentConfig.type==='bot'?"":agentConfig.welcomeMessage}}</view> | ||
</view> | ||
<view class="system" wx:if="{{showGuide}}"> | ||
<markdownPreview markdown="{{guide}}"></markdownPreview> | ||
</view> | ||
<view class="system" wx:if="{{agentConfig.type==='bot'}}"> | ||
<markdownPreview markdown="{{bot.introduction||''}}"></markdownPreview> | ||
</view> | ||
<block wx:for="{{chatRecords}}" wx:key="record_id"> | ||
<view class="system" wx:if="{{item.role==='assistant'}}"> | ||
<view wx:if="{{!!item.reasoning_content}}" style="opacity: 0.7;"> | ||
<view>{{item.reasoning_content&&!item.content?"思考中...":"已深度思考"}}</view> | ||
<view style="padding-left: 30rpx;border-left: rgb(165, 164, 164) solid 2px;"> | ||
<markdownPreview markdown="{{item.reasoning_content||''}}"></markdownPreview> | ||
</view> | ||
</view> | ||
<markdownPreview markdown="{{item.content||''}}"></markdownPreview> | ||
<view style="display: flex; gap: 10px;justify-content: flex-end;" wx:if="{{!streamStatus}}"> | ||
<image mode="widthFix" bind:tap="copyChatRecord" src='./imgs/copy.png' style="width: 36rpx; height: 36rpx;" data-content="{{item.content}}" /> | ||
<button class="share_btn" open-type="share"> | ||
<image mode="widthFix" src='./imgs/share1.png' style="width: 36rpx; height: 36rpx;vertical-align: top;" bind:tap="share" /> | ||
</button> | ||
</view> | ||
</view> | ||
<view class="user" wx:if="{{item.role==='user'}}"> | ||
<view> | ||
{{item.content}} | ||
</view> | ||
</view> | ||
</block> | ||
<!-- 推荐问题 --> | ||
<block wx:for="{{questions}}" wx:key="item"> | ||
<view class="questions"> | ||
<view class="question_content" bind:tap="sendMessage" data-message="{{item}}">{{item}}</view> | ||
</view> | ||
</block> | ||
<view style="width: 100%;height: 20px;"></view> | ||
</scroll-view> | ||
<!-- 底部输入区 --> | ||
<view class="footer"> | ||
<view class="input_box"> | ||
<input class="input" value="{{inputValue}}" type="text" maxlength="1024" bindinput="bindKeyInput" placeholder="说点什么吧" bindconfirm="sendMessage" confirm-type="send" adjust-position cursor-spacing="20" /> | ||
<image src="./imgs/set.png" class="set" mode="widthFix" bind:tap="openSetPanel" /> | ||
<image src="./imgs/send.png" class="set" mode="widthFix" wx:if="{{!!inputValue&&!streamStatus}}" bind:tap="sendMessage" /> | ||
<image src="./imgs/stop.png" class="set" mode="widthFix" wx:if="{{!!streamStatus}}" bind:tap="stop" /> | ||
</view> | ||
<!-- 设置面板 --> | ||
<view class="set_panel_modal" wx:if="{{setPanelVisibility}}" bind:tap="closeSetPanel"> | ||
<view class="set_panel"> | ||
<view class="set_panel_funtion"> | ||
<view class="function" bind:tap="clearChatRecords"> | ||
<image src="./imgs/clear.png" alt="widthFix" class="icon" /> | ||
<text class="text_desc">清除对话</text> | ||
</view> | ||
</view> | ||
<view class="set_panel_cancel" bind:tap="closeSetPanel">取消</view> | ||
</view> | ||
</view> | ||
</view> | ||
</view> |
Oops, something went wrong.