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 \
|
paging.js datagrid.js iframe.js cols.js echartsext.js \
|
||||||
floaticonbar.js miniform.js wterm.js dynamicaccordion.js \
|
floaticonbar.js miniform.js wterm.js dynamicaccordion.js \
|
||||||
binstreaming.js streaming_audio.js vadtext.js rtc.js docxviewer.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 \
|
line.js pie.js bar.js gobang.js period.js iconbarpage.js \
|
||||||
keypress.js asr.js webspeech.js countdown.js progressbar.js \
|
keypress.js asr.js webspeech.js countdown.js progressbar.js \
|
||||||
qaframe.js svg.js videoplayer.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 http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="stylesheet" href="{{entire_url('/bricks/3parties/xterm.css')}}" />
|
<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('/bricks/css/bricks.css')}}">
|
||||||
<link rel="stylesheet", href="{{entire_url('/css/myapp.css')}}">
|
<link rel="stylesheet", href="{{entire_url('/css/myapp.css')}}">
|
||||||
</head>
|
</head>
|
||||||
@ -28,10 +27,6 @@
|
|||||||
<script src="{{entire_url('/bricks/3parties/xterm.js')}}"></script>
|
<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/xterm-addon-fit.js')}}"></script>
|
||||||
<script src="{{entire_url('/bricks/3parties/video.min.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="{{entire_url('/bricks/3parties/recorder.wav.min.js')}}"></script>
|
||||||
<script src="https://sage.opencomputing.cn/bricks/3parties/hls.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