bugfix
This commit is contained in:
parent
0cdf9aec7e
commit
c102c61261
@ -1,46 +0,0 @@
|
||||
var bricks = window.bricks || {};
|
||||
bricks.AG_Grid = class extends bricks.JsWidget {
|
||||
/*
|
||||
{
|
||||
dataurl:
|
||||
fields:
|
||||
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
ag_opts = {}
|
||||
}
|
||||
|
||||
init(){
|
||||
this.datasource = {
|
||||
getRows:this.getRows,
|
||||
startRow
|
||||
this.ag_opts.columnDefs = [];
|
||||
this.ag_opts.rowModelType = 'infinite';
|
||||
this.ag_opts.maxConcurrentDatasourceRequests: 1,
|
||||
this.ag_opts.datasource = this.datasource;
|
||||
for (var i=0; i< this.opts.fields.length; i++){
|
||||
var f = {
|
||||
width:this.opts.fields[i].width | 100,
|
||||
headerName:this.opts.fields[i].label|this.opts.fields[i].name,
|
||||
field:this.opts.fields[i].name
|
||||
},
|
||||
this.ag_opts.columnDefs.push(f)
|
||||
}
|
||||
this.ag_opts.defaultColDef = {sortable: true, filter: true};
|
||||
this.ag_opts.rowSelection = 'multiple';
|
||||
this.ag_opts.animateRows = true;
|
||||
this.ag_opts.onCellClicked = this.cell_clicked.bind(this);
|
||||
this.aggrid = new agGrid.Grid(this.dom_element, this.ag_opts);
|
||||
fetch(this.opts.dataurl)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// load fetched data into grid
|
||||
this.ag_opts.api.setRowData(data);
|
||||
});
|
||||
}
|
||||
cell_clicked(params){
|
||||
bricks.debug('clicked, params=', params);
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,7 @@ SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.js \
|
||||
paging.js datagrid.js iframe.js cols.js echartsext.js \
|
||||
floaticonbar.js miniform.js wterm.js dynamicaccordion.js \
|
||||
binstreaming.js streaming_audio.js vadtext.js rtc.js docxviewer.js \
|
||||
llm_dialog.js llm.js websocket.js datarow.js tabular.js continueaudio.js \
|
||||
llm.js websocket.js datarow.js tabular.js continueaudio.js \
|
||||
line.js pie.js bar.js gobang.js period.js iconbarpage.js \
|
||||
keypress.js asr.js webspeech.js countdown.js progressbar.js \
|
||||
qaframe.js svg.js videoplayer.js "
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
var css = {
|
||||
multicolumns:{
|
||||
columnWidth:'350px',
|
||||
colummGap:'10px'
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,7 +5,6 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="{{entire_url('/bricks/3parties/xterm.css')}}" />
|
||||
<link href="{{entire_url('/bricks/3parties/video-js.css')}}" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="{{entire_url('/bricks/css/bricks.css')}}">
|
||||
<link rel="stylesheet", href="{{entire_url('/css/myapp.css')}}">
|
||||
</head>
|
||||
@ -28,10 +27,6 @@
|
||||
<script src="{{entire_url('/bricks/3parties/xterm.js')}}"></script>
|
||||
<script src="{{entire_url('/bricks/3parties/xterm-addon-fit.js')}}"></script>
|
||||
<script src="{{entire_url('/bricks/3parties/video.min.js')}}"></script>
|
||||
<!---
|
||||
<link href="https://unpkg.com/video.js@6/dist/video-js.css" rel="stylesheet">
|
||||
<script src="https://unpkg.com/video.js@6/dist/video.js"></script></head>
|
||||
--->
|
||||
|
||||
<script src="{{entire_url('/bricks/3parties/recorder.wav.min.js')}}"></script>
|
||||
<script src="https://sage.opencomputing.cn/bricks/3parties/hls.js"></script>
|
||||
|
||||
@ -1,222 +0,0 @@
|
||||
var bricks = window.bricks || {}
|
||||
|
||||
bricks.escapeSpecialChars = function(s){
|
||||
return s
|
||||
.replace(/\\/g, '\\\\') // escape backslashes
|
||||
.replace(/"/g, '\\"') // escape double quotes
|
||||
// .replace(/'/g, '\\\'') // escape single quotes
|
||||
.replace(/\n/g, '\\n') // escape newlines
|
||||
.replace(/\r/g, '\\r') // escape carriage returns
|
||||
.replace(/\t/g, '\\t') // escape tabs
|
||||
.replace(/\f/g, '\\f') // escape form feeds
|
||||
.replace(/\v/g, '\\v') // escape vertical tabs
|
||||
.replace(/\0/g, '\\0'); // escape null bytes
|
||||
}
|
||||
|
||||
bricks.UserMsgBox = class extends bricks.HBox {
|
||||
/*
|
||||
{
|
||||
"icon",
|
||||
"prompt",
|
||||
"msg_css"
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
var img = new bricks.Svg({rate:2,url:this.icon||bricks_resource('imgs/chat-user.svg')});
|
||||
var w = new bricks.MdWidget({mdtext:this.prompt});
|
||||
w.set_css('filler');
|
||||
w.set_css(this.msg_css||'user_msg');
|
||||
this.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
this.add_widget(w);
|
||||
this.add_widget(img);
|
||||
}
|
||||
}
|
||||
|
||||
bricks.LlmMsgBox = class extends bricks.HBox {
|
||||
/*
|
||||
{
|
||||
"model",
|
||||
"mapi",
|
||||
"url",
|
||||
"icon",
|
||||
"msg_css"
|
||||
"response_mode"
|
||||
"user_msg":{
|
||||
}
|
||||
|
||||
"llm_msg":{
|
||||
}
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
var img = new bricks.Svg({rate:2,url:this.icon||bricks_resource('imgs/user.png')});
|
||||
this.w = new bricks.MdWidget({mdtext:' '});
|
||||
this.w.set_css('filler');
|
||||
this.run = new bricks.BaseRunning({target:this});
|
||||
this.w.set_css(this.msg_css||'llm_msg');
|
||||
this.add_widget(img);
|
||||
this.add_widget(this.run)
|
||||
this.add_widget(this.w);
|
||||
this.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
this.messages = [];
|
||||
}
|
||||
responsed(){
|
||||
this.run.stop_timepass();
|
||||
this.remove_widget(this.run);
|
||||
this.w.md_content = '';
|
||||
}
|
||||
user_msg_format(){
|
||||
return this.user_msg||{role:'user',content:"${prompt}"}
|
||||
}
|
||||
llm_msg_format(){
|
||||
return this.llm_msg || {role:'assistant', content:"${content}"}
|
||||
}
|
||||
chunk_response(l){
|
||||
var d = JSON.parse(l);
|
||||
if (! d.content || d.content == ''){
|
||||
return;
|
||||
}
|
||||
var txt = this.w.md_content + d.content;
|
||||
this.w.set_content(txt);
|
||||
this.bind('updated');
|
||||
}
|
||||
chunk_ended(){
|
||||
var msg = this.llm_msg_format();
|
||||
var txt = this.w.md_content;
|
||||
txt = bricks.escapeSpecialChars(txt);
|
||||
var lmsg = bricks.apply_data(msg, {content:txt});
|
||||
this.messages.push(lmsg);
|
||||
}
|
||||
async set_prompt(prompt){
|
||||
var msg = this.user_msg_format();
|
||||
var umsg = bricks.apply_data(msg,{prompt:prompt});
|
||||
this.messages.push(umsg);
|
||||
var d = {
|
||||
messages:this.messages,
|
||||
mapi:this.mapi,
|
||||
model:this.model,
|
||||
}
|
||||
// console.log('messages=', this.messages, 'msg=', msg, 'umsg=', umsg);
|
||||
if (this.response_mode == 'stream') {
|
||||
var hr = new bricks.HttpResponseStream();
|
||||
var resp = await hr.post(this.url, {data:d});
|
||||
this.responsed();
|
||||
await hr.handle_chunk(resp, this.chunk_response.bind(this));
|
||||
this.chunk_ended();
|
||||
} else {
|
||||
var hj = new bricks.HttpJson()
|
||||
var resp = await hj.post(this.url, {params:d});
|
||||
if (this.response_mode == 'sync'){
|
||||
this.responsed();
|
||||
this.w.set_content(resp.content);
|
||||
var msg = this.llm_msg_format();
|
||||
var lmsg = bricks.apply_data(msg, resp);
|
||||
this.messages.push(lmsg)
|
||||
} else {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bricks.LlmDialog = class extends bricks.VBox {
|
||||
/*
|
||||
{
|
||||
"models":[
|
||||
{
|
||||
"model":
|
||||
"mapi":
|
||||
"icon":
|
||||
"url"
|
||||
"css"
|
||||
"user_msg":{
|
||||
}
|
||||
|
||||
"llm_msg":{
|
||||
}
|
||||
}
|
||||
]
|
||||
"response_mode":"stream", "async","async"
|
||||
"user_msg_css"
|
||||
"user_icon",
|
||||
"title_ccs"
|
||||
}
|
||||
method:
|
||||
set_prompt(prompt)
|
||||
event:
|
||||
llm_answer event.params = assistant answer content
|
||||
*/
|
||||
constructor(opts){
|
||||
opts.height = opts.height || '100%';
|
||||
super(opts);
|
||||
this.title_w = new bricks.HBox({cheight:2});
|
||||
this.title_w.set_css(this.title_ccs||'llm_title');
|
||||
this.add_widget(this.title_w);
|
||||
this.model_info_ws = {};
|
||||
this.show_models_info();
|
||||
var filler = new bricks.Filler({});
|
||||
this.body = new bricks.VScrollPanel({height:'100%'});
|
||||
filler.add_widget(this.body);
|
||||
this.add_widget(filler);
|
||||
}
|
||||
show_models_info(){
|
||||
for(var i=0;i<this.models.length;i++){
|
||||
this.show_model_info(this.models[i]);
|
||||
}
|
||||
}
|
||||
show_model_info(model){
|
||||
var w = new bricks.HBox({margin:'5px'});
|
||||
w.add_widget(new bricks.Svg({url:model.icon||bricks_resource('imgs/llm.svg'), rate:2}));
|
||||
w.add_widget(new bricks.Text({text:model.model}));
|
||||
this.title_w.add_widget(w);
|
||||
this.model_info_ws[model.model] = w;
|
||||
}
|
||||
add_model(model){
|
||||
this.models.push(model);
|
||||
this.show_model_info(model);
|
||||
}
|
||||
delete_model(model){
|
||||
for(var i=0;i<this.models.length;i++){
|
||||
if (this.models[i].model == model.model){
|
||||
this.models.splice(i,1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete this.model_info_ws[model.model];
|
||||
}
|
||||
async set_prompt(prompt){
|
||||
prompt = bricks.escapeSpecialChars(prompt);
|
||||
var box = new bricks.UserMsgBox({
|
||||
width:'100%',
|
||||
icon:this.user_icon,
|
||||
prompt:prompt,
|
||||
msg_css:this.user_msg_css||'user_msg'
|
||||
});
|
||||
this.body.add_widget(box);
|
||||
this.body.dom_element.scrollTop = this.body.dom_element.scrollHeight;
|
||||
await this.llm_request(prompt);
|
||||
}
|
||||
async llm_request(prompt){
|
||||
for (var i=0;i<this.models.length;i++){
|
||||
var model = this.models[i];
|
||||
var box = new bricks.LlmMsgBox({
|
||||
width:'100%',
|
||||
response_mode:this.response_mode || 'stream',
|
||||
model:model.model,
|
||||
mapi:model.mapi,
|
||||
icon:model.icon,
|
||||
msg_css:model.css,
|
||||
url:model.url,
|
||||
user_msg:model.user_msg,
|
||||
llm_msg:model.llm_msg
|
||||
});
|
||||
this.body.add_widget(box);
|
||||
schedule_once(box.set_prompt.bind(box, prompt), 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('LlmDialog', bricks.LlmDialog);
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
var bricks = window.bricks || {};
|
||||
|
||||
bricks.TreeChoose = class extends bricks.VBox {
|
||||
/*
|
||||
{
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
|
||||
}
|
||||
173
bricks/video.js
173
bricks/video.js
@ -1,173 +0,0 @@
|
||||
var bricks = window.bricks || {};
|
||||
/*
|
||||
we use videojs for video play
|
||||
https://videojs.com
|
||||
event: play_end video play finished
|
||||
play_failed video play failed
|
||||
play_ok video start to play
|
||||
|
||||
*/
|
||||
var bricks = window.bricks || {};
|
||||
|
||||
bricks.Video = class extends bricks.Layout {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
this.opts = opts || {};
|
||||
this.set_csses('video-js', 'vjs-big-play-centered', 'vjs-fluid');
|
||||
this.set_style('object-fit', 'contain');
|
||||
this.set_style('width', '100%');
|
||||
this.set_style('height', '100%');
|
||||
this.cur_url = opts.url;
|
||||
this.cur_vtype = opts.type || this.guess_type(this.cur_url);
|
||||
schedule_once(this.create_player.bind(this), 0.1);
|
||||
}
|
||||
|
||||
create() {
|
||||
let e = document.createElement('video');
|
||||
this.dom_element = e;
|
||||
e.controls = true;
|
||||
}
|
||||
|
||||
create_player() {
|
||||
this.player = videojs(this.dom_element, {
|
||||
controls: true,
|
||||
autoplay: this.opts.autoplay || false,
|
||||
preload: "auto",
|
||||
muted: true,
|
||||
crossorigin: 'anonymous',
|
||||
nativeTextTracks: false
|
||||
});
|
||||
|
||||
this.player.on('play', () => this.dispatch('play_ok', { src: this.cur_url }));
|
||||
this.player.on('ended', () => this.dispatch('play_end', { src: this.cur_url }));
|
||||
this.player.on('error', () => this.dispatch('play_failed', { src: this.cur_url }));
|
||||
|
||||
this.player.ready(() => {
|
||||
this.disable_captions();
|
||||
if (this.opts.fullscreen && !this.player.isFullscreen()) {
|
||||
this.player.requestFullscreen();
|
||||
}
|
||||
this.set_source(this.cur_url, this.cur_vtype);
|
||||
schedule_once(this.unmuted.bind(this), 1);
|
||||
});
|
||||
}
|
||||
|
||||
disable_captions() {
|
||||
let tt = this.player.textTracks();
|
||||
for (let i = 0; i < tt.length; i++) {
|
||||
tt[i].mode = 'disabled';
|
||||
}
|
||||
}
|
||||
|
||||
set_source(url, vtype) {
|
||||
this.cur_url = url;
|
||||
this.cur_vtype = vtype || this.guess_type(url);
|
||||
this.player.src({ src: this.cur_url, type: this.cur_vtype });
|
||||
}
|
||||
|
||||
guess_type(url) {
|
||||
let t = url.toLowerCase();
|
||||
if (t.endsWith('.m3u8')) return 'application/x-mpegURL';
|
||||
if (t.endsWith('.mp4')) return 'video/mp4';
|
||||
if (t.endsWith('.avi')) return 'video/avi';
|
||||
if (t.endsWith('.webm')) return 'video/webm';
|
||||
return 'application/x-mpegURL';
|
||||
}
|
||||
|
||||
play() {
|
||||
if (this.player) this.player.play();
|
||||
}
|
||||
|
||||
unmuted() {
|
||||
if (this.player) {
|
||||
this.player.muted(false);
|
||||
this.player.volume(1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Iptv = class extends bricks.VBox {
|
||||
/*
|
||||
{
|
||||
iptv_data_url:
|
||||
playok_url:
|
||||
playfailed_url:
|
||||
}
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
schedule_once(this.build_subwidgets.bind(this), 0.1);
|
||||
}
|
||||
async build_subwidgets(){
|
||||
console.log('build_subwidgets called');
|
||||
if (!this.user_data){
|
||||
var jc = new bricks.HttpJson();
|
||||
this.deviceid = bricks.deviceid('iptv')
|
||||
this.user_data = await jc.httpcall(this.iptv_data_url, {
|
||||
params:{
|
||||
deviceid:this.deviceid
|
||||
},
|
||||
method:'GET'
|
||||
});
|
||||
}
|
||||
console.log('this.user_data =', this.user_data);
|
||||
this.video = new bricks.Video({
|
||||
autoplay:true,
|
||||
url:this.user_data.url
|
||||
});
|
||||
this.title_w = new bricks.Text({text:this.user_data.tv_name, wrap:false});
|
||||
this.add_widget(this.title_w);
|
||||
this.add_widget(this.video);
|
||||
this.video.bind('play_ok', this.report_play_ok.bind(this));
|
||||
this.video.bind('play_failed', this.report_play_failed.bind(this));
|
||||
}
|
||||
async report_play_ok(){
|
||||
console.log(this.user_data, 'channel playing ...', this.playok_url);
|
||||
if (this.playok_url){
|
||||
var ht = new bricks.HttpText();
|
||||
var resp = ht.httpcall(this.playok_url,{
|
||||
params:{
|
||||
deviceid:this.deviceid,
|
||||
channelid:this.user_data.id
|
||||
},
|
||||
method:"GET"
|
||||
});
|
||||
if (resp != 'Error'){
|
||||
console.log('report playok ok');
|
||||
} else {
|
||||
console.log('report playok failed');
|
||||
}
|
||||
} else {
|
||||
console.log('this.playok_url not defined', this.playok_url);
|
||||
}
|
||||
}
|
||||
async report_play_failed(){
|
||||
console.log(this.user_data, 'channel play failed ...');
|
||||
if (this.playfailed_url){
|
||||
var ht = new bricks.HttpText();
|
||||
var resp = ht.httpcall(this.playfailed_url,{
|
||||
params:{
|
||||
deviceid:this.deviceid,
|
||||
channelid:this.user_data.id
|
||||
},
|
||||
method:"GET"
|
||||
});
|
||||
if (resp != 'Error'){
|
||||
console.log('report playfailed ok');
|
||||
} else {
|
||||
console.log('report playfailed failed');
|
||||
}
|
||||
} else {
|
||||
console.log('this.playfailed_url not defined', this.playfailed_url);
|
||||
}
|
||||
}
|
||||
setValue(data){
|
||||
this.user_data = data;
|
||||
this.title_w.set_text(data.tv_name);
|
||||
this.video.set_url(data.url);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
bricks.Factory.register('Video', bricks.Video);
|
||||
bricks.Factory.register('Iptv', bricks.Iptv);
|
||||
@ -1,5 +0,0 @@
|
||||
bricks = window.bricks || {}
|
||||
|
||||
bricks.Vision = class extend bricks.Layout {
|
||||
|
||||
}
|
||||
471
bricks/wsllm.js
471
bricks/wsllm.js
@ -1,471 +0,0 @@
|
||||
bricks = window.bricks || {}
|
||||
|
||||
bricks.ModelOutput = class extends bricks.VBox {
|
||||
bricks.RoleOutput = class extends bricks.VBox {
|
||||
/*
|
||||
{
|
||||
icon:
|
||||
role:'user' or 'llm',
|
||||
output_view:
|
||||
}
|
||||
完成模型输出的控件的初始化以及获得数据后的更新, 更新是的数据在流模式下,需要使用累积数据
|
||||
*/
|
||||
constructor(opts){
|
||||
if(! opts){
|
||||
opts = {};
|
||||
}
|
||||
opts.width = '100%';
|
||||
opts.height = 'auto';
|
||||
super(opts);
|
||||
var hb = new bricks.HBox({width:'100%', cheight:2});
|
||||
var default_icon;
|
||||
if (this.role == 'llm'){
|
||||
default_icon = bricks_resource('imgs/llm.svg')
|
||||
} else {
|
||||
defautl_icon = bricks_resource('imgs/user.svg')
|
||||
}
|
||||
this.img = new bricks.Svg({
|
||||
rate:2,
|
||||
tip:this.opts.model,
|
||||
url:this.icon || default_icon
|
||||
});
|
||||
hb.add_widget(this.img);
|
||||
var mname = new bricks.Text({text:this.opts.model});
|
||||
hb.add_widget(mname);
|
||||
this.add_widget(hb);
|
||||
|
||||
this.content = new bricks.HBox({width:'100%'});
|
||||
this.add_widget(this.content);
|
||||
this.logid = null;
|
||||
this.run = new bricks.BaseRunning({target:this});
|
||||
this.content.add_widget(this.run);
|
||||
this.filler = new bricks.VBox({});
|
||||
this.filler.set_css('filler');
|
||||
if (this.role == 'llm'){
|
||||
this.content.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
}
|
||||
this.content.add_widget(this.filler);
|
||||
if (this.role != 'llm'){
|
||||
this.content.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
}
|
||||
if (this.role == 'llm'){
|
||||
this.build_estimate_widgets();
|
||||
}
|
||||
}
|
||||
build_estimate_widgets(){
|
||||
if (!this.estimate_url) return;
|
||||
this.estimate_w = new bricks.HBox({width:'100%', cheight:2});
|
||||
var txtw = new bricks.Text({
|
||||
otext:'结果满意吗?',
|
||||
i18n:true,
|
||||
});
|
||||
var likew = new bricks.Svg({rate:2, url:bricks_resource('imgs/like.svg')});
|
||||
var unlikew = new bricks.Svg({rate:2, url:bricks_resource('imgs/unlike.svg')});
|
||||
likew.bind('click', this.estimate_llm.bind(this, 1));
|
||||
unlikew.bind('click', this.estimate_llm.bind(this, -1))
|
||||
this.estimate_w.add_widget(txtw);
|
||||
this.estimate_w.add_widget(likew);
|
||||
this.estimate_w.add_widget(new bricks.BlankIcon({rate:1, flexShrink:0}));
|
||||
this.estimate_w.add_widget(unlikew);
|
||||
likew.set_style('cursor', 'pointer');
|
||||
unlikew.set_style('cursor', 'pointer');
|
||||
this.estimate_w.hide();
|
||||
}
|
||||
async estimate_llm(val, event){
|
||||
var desc = {
|
||||
"widgettype":"urlwidget",
|
||||
"options":{
|
||||
"params":{
|
||||
"logid":this.logid,
|
||||
"value":val
|
||||
},
|
||||
"url":this.estimate_url
|
||||
}
|
||||
};
|
||||
var icon = event.target.bricks_widget;
|
||||
icon.rate = 2;
|
||||
icon.charsize_sizing();
|
||||
var w = await bricks.widgetBuild(desc, this);
|
||||
this.estimate_w.disabled(true);
|
||||
}
|
||||
async update_data(data){
|
||||
if (this.run) {
|
||||
this.run.stop_timepass();
|
||||
this.content.remove_widget(this.run);
|
||||
if(this.textvoice){
|
||||
this.upstreaming = new bricks.UpStreaming({
|
||||
url:this.tts_url
|
||||
});
|
||||
this.upstreaming.go();
|
||||
}
|
||||
}
|
||||
if (this.upstreaming){
|
||||
this.upstreaming.send(data.content);
|
||||
}
|
||||
this.run = null;
|
||||
this.filler.clear_widgets();
|
||||
if (typeof this.output_view === 'string'){
|
||||
this.output_view = JSON.parse(this.output_view);
|
||||
}
|
||||
var desc = bricks.apply_data(this.output_view, data);
|
||||
var w = await bricks.widgetBuild(desc, this.llmio);
|
||||
if (! w){
|
||||
console.log('widgetBuild() return null, desc=', this.output_view, desc, 'data=', data);
|
||||
return;
|
||||
}
|
||||
w.set_css('llm_msg');
|
||||
w.set_style('width', '100%');
|
||||
this.filler.add_widget(w);
|
||||
this.filler.add_widget(this.estimate_w);
|
||||
if (data.logid){
|
||||
this.logid = data.logid;
|
||||
if (this.estimate_url){
|
||||
this.estimate_w.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
finish(){
|
||||
if (this.upstreaming){
|
||||
this.upstreaming.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bricks.LlmModel = class extends bricks.JsWidget {
|
||||
/*
|
||||
{
|
||||
icon:
|
||||
model:
|
||||
url:
|
||||
output_view:
|
||||
params:
|
||||
user_message_format:
|
||||
system_message_format:
|
||||
llm_message_format:
|
||||
use_session:
|
||||
input_from:
|
||||
textvoice:
|
||||
tts_url:
|
||||
response_mode:stream, sync or async
|
||||
}
|
||||
*/
|
||||
constructor(llmio, opts){
|
||||
super(opts);
|
||||
this.llmio = llmio;
|
||||
this.messages = [];
|
||||
}
|
||||
render_title(){
|
||||
var w = new bricks.HBox({padding:'15px'});
|
||||
w.bind('click', this.show_setup_panel.bind(this))
|
||||
var img = new bricks.Svg({
|
||||
rate:2,
|
||||
tip:this.opts.model,
|
||||
url:this.opts.icon||bricks_resource('imgs/llm.svg')
|
||||
});
|
||||
// var txt = new bricks.Text({text:this.opts.model});
|
||||
w.add_widget(img);
|
||||
// w.add_widget(txt);
|
||||
return w;
|
||||
}
|
||||
show_setup_panel(event){
|
||||
|
||||
}
|
||||
inputdata2uploaddata(data){
|
||||
var d;
|
||||
if (data instanceof FormData){
|
||||
d = bricks.formdata_copy(data);
|
||||
} else {
|
||||
d = objcopy(data);
|
||||
}
|
||||
var fmt = this.opts.user_message_format;
|
||||
if (fmt){
|
||||
var umsg = bricks.apply_data(fmt, inputdata2dic(data));
|
||||
this.messages.push(umsg);
|
||||
}
|
||||
if (data instanceof FormData){
|
||||
d.append('model', this.opts.model)
|
||||
d.append('modelinstanceid', this.opts.modelinstanceid)
|
||||
d.append('modeltypeid', this.opts.modeltypeid)
|
||||
d.append('messages', JSON.stringify(this.messages));
|
||||
} else {
|
||||
d.messages = JSON.stringify(this.messages);
|
||||
d.model = this.opts.model;
|
||||
d.modelinstanceid = this.opts.modelinstanceid;
|
||||
d.modeltypeid = this.opts.modeltypeid;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
async model_inputed(data){
|
||||
if (!opts.use_session){
|
||||
this.messages = [];
|
||||
}
|
||||
var mout = new bricks.ModelOutput({
|
||||
textvoice:this.textvoice,
|
||||
tts_url:this.tts_url,
|
||||
icon:this.opts.icon,
|
||||
model:this.opts.model,
|
||||
estimate_url:this.llmio.estimate_url,
|
||||
output_view:this.opts.output_view});
|
||||
this.llmio.o_w.add_widget(mout);
|
||||
if (this.response_mode == 'stream' || this.response_mode == 'async') {
|
||||
var d = this.inputdata2uploaddata(data);
|
||||
console.log('data_inouted=', data, 'upload_data=', d);
|
||||
var hr = new bricks.HttpResponseStream();
|
||||
var resp = await hr.post(this.opts.url, {params:d});
|
||||
await hr.handle_chunk(resp, this.chunk_response.bind(this, mout));
|
||||
this.chunk_ended();
|
||||
} else {
|
||||
var d = this.inputdata2uploaddata(data);
|
||||
var hj = new bricks.HttpJson()
|
||||
var resp = await hj.post(this.opts.url, {params:d});
|
||||
if (this.response_mode == 'sync'){
|
||||
resp.content = bricks.escapeSpecialChars(resp.content)
|
||||
mout.update_data(resp);
|
||||
if (this.messages){
|
||||
var msg = this.llm_msg_format();
|
||||
var lmsg = bricks.apply_data(msg, resp);
|
||||
this.messages.push(lmsg)
|
||||
}
|
||||
} else {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
is_accept_source(source){
|
||||
if (this.opts.input_from == source){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
llm_msg_format(){
|
||||
return this.llm_message_format || {role:'assistant', content:"${content}"}
|
||||
}
|
||||
chunk_response(mout, l){
|
||||
var d = JSON.parse(l);
|
||||
if (! d.content || d.content == ''){
|
||||
return;
|
||||
}
|
||||
d.content = bricks.escapeSpecialChars(d.content);
|
||||
this.resp_data = d;
|
||||
mout.update_data(d);
|
||||
// console.log('stream data=', d);
|
||||
}
|
||||
chunk_ended(){
|
||||
if (! this.messages) {
|
||||
console.log('this.messages is null !!!!!!!!!');
|
||||
return;
|
||||
}
|
||||
var msg = this.llm_msg_format();
|
||||
var txt = bricks.escapeSpecialChars(this.resp_data.content)
|
||||
this.resp_data.content = txt;
|
||||
var lmsg = bricks.apply_data(msg, this.resp_data);
|
||||
this.messages.push(lmsg);
|
||||
}
|
||||
}
|
||||
bricks.LlmIO = class extends bricks.VBox {
|
||||
/*
|
||||
options:
|
||||
{
|
||||
ws_url:
|
||||
user_icon:
|
||||
list_models_url:
|
||||
input_fields:
|
||||
input_view:
|
||||
output_view:
|
||||
models:
|
||||
}
|
||||
models:[
|
||||
{
|
||||
icon:
|
||||
model:
|
||||
url:
|
||||
params:
|
||||
use_session:
|
||||
system_prompt:
|
||||
user_parmpt:
|
||||
input_from:
|
||||
io_mode:stream, sync or async
|
||||
}
|
||||
]
|
||||
*/
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.ws = new bricks.WebSocket(this.ws_url);
|
||||
this.llmmodels = [];
|
||||
this.title_w = new bricks.HBox({cheight:3});
|
||||
var bottom_box = new bricks.HBox({cheight:3});
|
||||
this.i_w = new bricks.Svg({
|
||||
rate:2,
|
||||
url:bricks_resource('imgs/input.svg'),
|
||||
margin:'14px',
|
||||
tip:'input data',
|
||||
css:'clickable'
|
||||
});
|
||||
this.nm_w = new bricks.Svg({
|
||||
rate:2,
|
||||
url:bricks_resource('imgs/add.svg'),
|
||||
margin:'14px',
|
||||
tip:'add new model',
|
||||
css:'clickable'
|
||||
});
|
||||
bottom_box.add_widget(this.i_w);
|
||||
bottom_box.add_widget(this.nm_w);
|
||||
|
||||
this.nm_w.bind('click', this.open_search_models.bind(this));
|
||||
this.i_w.bind('click', this.open_input_widget.bind(this));
|
||||
this.o_w = new bricks.Filler({overflow:'auto'});
|
||||
this.add_widget(this.title_w);
|
||||
this.add_widget(this.o_w);
|
||||
if (this.models.length < 2 && this.tts_url){
|
||||
this.textvoice = true;
|
||||
}
|
||||
this.add_widget(bottom_box);
|
||||
this.models.forEach( m =>{
|
||||
this.show_added_model(m);
|
||||
});
|
||||
}
|
||||
show_added_model(m){
|
||||
if (this.textvoice){
|
||||
m.textvoice = true;
|
||||
m.tts_url = this.tts_url;
|
||||
}
|
||||
var lm = new bricks.LlmModel(this, m);
|
||||
this.llmmodels.push(lm);
|
||||
var tw = lm.render_title();
|
||||
this.title_w.add_widget(tw);
|
||||
}
|
||||
async open_search_models(event){
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
var rect = this.showRectage();
|
||||
var opts = {
|
||||
title:"select model",
|
||||
icon:bricks_resource('imgs/search.svg'),
|
||||
auto_destroy:true,
|
||||
auto_open:true,
|
||||
auto_dismiss:false,
|
||||
movable:true,
|
||||
top:rect.top + 'px',
|
||||
left:rect.left + 'px',
|
||||
width: rect.right - rect.left + 'px',
|
||||
height: rect.bottom - rect.top + 'px'
|
||||
}
|
||||
var w = new bricks.PopupWindow(opts);
|
||||
var sopts = {
|
||||
data_url:this.list_models_url,
|
||||
data_params:{
|
||||
mii:this.models[0].modelinstanceid,
|
||||
mti:this.models[0].modeltypeid
|
||||
},
|
||||
data_method:'POST',
|
||||
col_cwidth: 24,
|
||||
record_view:{
|
||||
widgettype:"VBox",
|
||||
options:{
|
||||
cheight:20,
|
||||
css:"card"
|
||||
},
|
||||
subwidgets:[
|
||||
{
|
||||
widgettype:"Title4",
|
||||
options:{
|
||||
text:"${name}"
|
||||
}
|
||||
},
|
||||
{
|
||||
widgettype:"Filler",
|
||||
options:{
|
||||
css:"scroll"
|
||||
},
|
||||
subwidgets:[
|
||||
{
|
||||
widgettype:"VBox",
|
||||
options:{
|
||||
css:"subcard"
|
||||
},
|
||||
subwidgets:[
|
||||
{
|
||||
widgettype:"Text",
|
||||
options:{
|
||||
text:"模型描述:${description}",
|
||||
wrap:true
|
||||
}
|
||||
},
|
||||
{
|
||||
widgettype:"Text",
|
||||
options:{
|
||||
text:"启用日期:${enable_date}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
var cols = new bricks.Cols(sopts);
|
||||
cols.bind('record_click', this.add_new_model.bind(this));
|
||||
cols.bind('record_click', w.dismiss.bind(w));
|
||||
w.add_widget(cols);
|
||||
w.open();
|
||||
}
|
||||
async add_new_model(event){
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.models.push(event.params);
|
||||
this.show_added_model(event.params);
|
||||
}
|
||||
async open_input_widget(event){
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
var rect = this.showRectage();
|
||||
var opts = {
|
||||
title:"input data",
|
||||
icon:bricks_resource('imgs/input.svg'),
|
||||
auto_destroy:true,
|
||||
auto_open:true,
|
||||
auto_dismiss:false,
|
||||
movable:true,
|
||||
top:rect.top + 'px',
|
||||
left:rect.left + 'px',
|
||||
width: rect.right - rect.left + 'px',
|
||||
height: rect.bottom - rect.top + 'px'
|
||||
}
|
||||
var w = new bricks.PopupWindow(opts);
|
||||
var fopts = {
|
||||
fields:this.input_fields
|
||||
}
|
||||
var fw = new bricks.Form(fopts);
|
||||
fw.bind('submit', this.handle_input.bind(this));
|
||||
fw.bind('submit', w.destroy.bind(w));
|
||||
w.add_widget(fw);
|
||||
w.open();
|
||||
}
|
||||
async handle_input(event){
|
||||
var params = event.params;
|
||||
await this.show_input(params);
|
||||
for(var i=0;i<this.llmmodels.length;i++){
|
||||
var lm = this.llmmodels[i];
|
||||
if (lm.is_accept_source('userinput')){
|
||||
schedule_once(lm.model_inputed.bind(lm, params), 0.01);
|
||||
// await lm.model_inputed(params);
|
||||
}
|
||||
};
|
||||
}
|
||||
async show_input(params){
|
||||
var box = new bricks.HBox({width:'100%'});
|
||||
var data = inputdata2dic(params);
|
||||
console.log('data=', data, 'input_view=', this.input_view);
|
||||
var w = await bricks.widgetBuild(this.input_view, this.o_w, data);
|
||||
w.set_css(this.msg_css||'user_msg');
|
||||
w.set_css('filler');
|
||||
var img = new bricks.Svg({rate:2,url:this.user_icon||bricks_resource('imgs/user.svg')});
|
||||
box.add_widget(new bricks.BlankIcon({rate:2, flexShrink:0}));
|
||||
box.add_widget(w);
|
||||
box.add_widget(img);
|
||||
this.o_w.add_widget(box);
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('LlmIO', bricks.LlmIO);
|
||||
Loading…
x
Reference in New Issue
Block a user