# 【智体OS】官方上新发布”智体聊“——集成了deepseek-R1私有化部署版本支持、支持会话保存、分享、构建prompt提示语开源社区和二创社区——比deepseek官方app功能还强大

dtns.network是一款主要由JavaScript编写的智体世界引擎(内嵌了three.js编辑器的定制版-支持以第一视角浏览3D场馆),可以在浏览器和node.js、deno、electron上运行,它是一个跨平台的软件,支持多个操作系统使用!

dtns.connector是dtns.network的客户端软件,允许多用户方便自由地连接dtns.network的智体设备。支持使用内置的poplang智体编程语言实现3D组件的智能化编程——语法超简单,一句话语法,人人轻松上手!通过poplang智体编程,可轻松创建、编辑、分发xverse-3D智体应用。

【智体OS】是集成dtns.network、dtns.connector、dtns.dweb、dtns.ibchat、poplang智体编程语言、DTNSManager、dtns协议、dtns.dnalink、dtns.plugin插件集合等等的智体运行环境。支持在智能手机等移动设备、windows和macos和linux等传统个人电脑和服务器设备、任意的智能设备上运行的智能体操作系统。可以将普通的个人电脑PC、服务器、智能手机、机器人、智能设备等变身为可自然语言编程(智体编程)和控制的开源的、可二次开发的【智体】。结合大语言模型和多模态,甚至可以变身成超人形态的有形和无形的AGI通用人工智能设备。通过开源和自然语言对话和编程,拥有多个智体的个人用户可以变身百倍效率达人和创作达人,装有智体OS的智体设备是真正的跨时代的超人必备套件。【未来已来】

本次上新的主要内容为:dtns.os智体OS的客户端dtns.connector德塔世界连接器,新上线的dtns.ibchat智体聊,集成了deepseek-R1私有化部署版本的支持。并重点支持了对话历史保存、分享、恢复历史会话。结合dtns.dweb头榜功能,基于对话prompt历史纪录的分享与恢复,轻松实现智体世界、智体OS的prompt提示语社区。从而让更多的人分享、学习、记录、同步、恢复deepseek-R1的深度思考的结果。让AI+智体能力在二创爱好者群体中轻松传播。

# 更新内容

1、【智体聊】:直接与deepseek-R1进行对话,深度思考并实时返回结果。

2、【提示语输入框】:支持新会话、会话、结束、保存、分享等对话功能指令,以实现LLM大语言模型(deepseek-R1)版本的功能集成,并易于分享给其他用户。

3、【dweb头榜】:支持dtns.ibchat智体聊分享过来的对话历史纪录的文件分享、点击加载恢复到dtns.ibchat聊天窗口界面,并自动创建新的会话,在原来历史纪录的基础上继续对话。从而形成多轮多用户分享对话并二次创作的能力,这个功能远胜于官方deepseek的APP和网页版本。

【完全开源】dtns.connector和相关项目均开源。详见官网dtns.top

# 详细升级内容

2-19日:

dtns.connector

【删除】apiindex.js中的connectIBChatSvr代码---已经不需要,直接使用rt-ibchat插件的api即可。

【新增】chat.vue中使用rtibchat的api进行智体聊---ollma-chat.

【修复】chat.vue智体聊的各个BUG,1-显示多行答案(重复显示多行);2-不能正确结束和开启新会话;3-答案显示异常。

【新增】新会话之时,结束上面的会话(避免泄露内存和影响速度)

dtns.forklist.network

【新增】rtibchat实时智体聊的配置

【新增】rt-ibchat实时智体聊插件---主要是对接ollma(deepseek)

【修复】rt-ibchatindex.js中的失败时使用flag=false

经测试,能很好的实现dtns.connector与deepseek-R1大语言模板的集成(体验不错)

2-21

dtns.connector

【新增】FileItem.vue中增加了rtibchat-session.json文件的支持,以恢复ibchat智体聊会话。

【新增】chat.vue中增加会话的保存、分享、【会话】历史。并优化了代码。

【新增】DChatManager.js中增加了对rtibchat-session的json文件的识别支持。

【修复】结束指令时,错误将this.session_id设置为ret.session_id,并优化掉多余的“会话”指令重复处理代码

dtns.forklist.network

【新增】rtibchatsessionrecover恢复会话的api接口--主要是使用用户提供的history来恢复session会话--可用于Prompt社区分享的会话初始化--重建工作

【新增】chat接口新增nostream参数,并支持ibchat函数的host定义--以便实现局域网内连接ollma

【新增】rtibchat新增了saveSession功能api,用于保存session,以便分享等

【新增】session_path参数。

【新增】rt-ibchatindex.js中的saveSession函数,增加share参数,以便保存至dnalink,方便dtns.connector分享至社区头榜。

【修改】upload_file_fast函数删除了fileInfo.s_id的返回值(不能把参数s_id返回)。

经测试,实现了dtns.connector德塔世界的dtns.ibchat智体聊之prompt分享社区(LLM模型之对话分享社区)

# 使用教程(让我们看看【智体聊】都能干什么?)

一、 打开 dtns.connector 的智体 IB 界面

1.png

二、 打开智体聊后,输入提示语: 2 吨的汽车从 120KM 时速减速至 0 ,损失多少动能(转换为电能是多少度电)?

2.png

注:可以看到,经过一小会(大概几秒钟的深度思考),智体聊得到了deepseek-R1:1.5b的思考结果(如上图),显示思考和计算过程,并得到了0.309度电的精准结果(经测算基本无误),体现了deepseek-R1强大的精确的数学逻辑计算能力——期间还正确使用了动能公式0.5mg*h,并运用了电能转换公式。从而得到精准的结果。

三、 将提示语输入修改为:假如汽车的重量是 1 吨呢?

3.png

注:这次我们重点关注“思考中”,这个思考中视提示语的复杂度,会进行0.1-30秒左右的思考(主要是设备算力不能,问题的复杂度不同决定的)——本文测试所采用的设备为macos-i5的CPU,内存是8GB。从1.5B版本的deepseek-R1,可以看到结果照样精准,思考所需延迟仅1-10秒,速度惊人——比物理学家计算速度都要快。

4.png

短短不到2秒,很快得到答案。这里我们使用了stream=true的实时对话结果流式反馈,可以将思考后的结果直接实时反馈到对话框上。从而看到整个deepseek运算的过程,这时的速度达到了2-10tokens/s左右,比人类的打字速度要快上不少。所以基本上是能满足大部分人的需要的(关键是开源的、老旧电脑可运行的)

5.png

如上图所示,持续输出tokens结果。

6.png

最终我们得到了答案:0.154度电,恰好是0.309度电的一半左右。经验算,完全正确。

四、 使用结束指令来结束提示语的思考:假如汽车的重量是 3 吨呢?

7.png

注:如上图,在提示语输入框输入“结束”点击发送,可结束当前“思考中…”的思考过程。

9.png

注:如上图所示,我们看到了结果结果为{“ret”:true,msg:”success”}代表成功保存当前思考过程(会话纪录)。

五、 实现对话纪录的 dweb 头榜分享功能,可在提示语输入框输入:分享

10.png

如上图所示,我们在提示语输入框输入分享后,点击右侧底部的【发送】,即可实现当前会话纪录的分享至头榜(如下图)

11.png

注:将分享文字内容追加——重量变为1吨再计算。然后点击右上角的【确认】,即可成功将会话纪录rtibchat-session-*.json文件分享至头榜(从上图可大概看到分享后的头榜内容预览)。

分享成功如下图所示:

12.png

返回头榜查看分享成功后的结果(如下图所示):

13.png

注:如上图所示,可以看到成功分享后的头榜内容(基本与分享预览一致)

六、 点击头榜的会话纪录文件,下载成功后再点击一次进入到 ibchat 智体聊,可恢复会话历史纪录,以便进行继续对话

14.png

注:如上图所示,点击rtibchat-session-*.json文件后下载完成

继续点击该文件,可以进入ibchat智体聊看到恢复后的会话纪录(如下图所示)

15.png

七、继续会话,输入提示语:假如汽车的重量是 3 吨呢?

16.png

经过1秒不到的思考过程,成功继续进行了智体聊会话(如上图所示)

17.png

注:最终我们看到了如上图所示的新问题的结果。从结果来看,亦非常准备。

注2:这个点击rtibchat-session-*.json文件的方式进行恢复会话历史纪录,,并且不限于只是会话的创作者,任何人均可以基本头榜分享的会话纪录进行特有的会话恢复并继续对话——每个人的会话ID都是私有的,可以继续基于会话纪录进行对话——分享后可见-不分享仅自己可见)。从而实现了人人可基于ibchat智体聊分享到dweb头榜的会话纪录的二次创作、再次私人体验继续提问的便捷快乐。

注3:这既保证了隐私、又可实现公开的deepseek-R1会话纪录的群体协作、分享、二创,按照自己的理解衍生出新的版本对话内容。从而实现分享-学习-二次分享-多轮创作。实现【星火传递】,让智体聊的超能力在个体之间快速传递。这是prompt提示语开源社区的魅力所在。

八、手机进行 ibchat 智体聊会话:新媒体内容做哪方面的好,容易获得流量

18.jpg

继续提问:如何发掘超级粉丝

19.jpg

20.jpg

注:如上图(2图)所示,最终我们追加提问得到了长长的让人见识到思考广度与深度兼具的答案。

# dtns.plugin/rtibchat/index.js 的源码分享

const  http=require( 'http' );

/**
 * rt-ibchat智体聊的插件代码
 */
window.rtibchat_c = {}
// const rtibchat_c_token_name = OBJ_TOKEN_NAME
// const rtibchat_c_api_base   = OBJ_API_BASE
// const rtibchat_c_token_root = OBJ_TOKEN_ROOT
let model = null
let host = null
let session_path = null
const file_util = require('../../libs/file_util');
const str_filter = require('../../libs/str_filter');
rtibchat_c.routers =async function(app)
{
    if(!app) return 
    // if(!app.setChatC) return 
    // const urlParser = null
    app.all('/rtibchat/session/new',urlParser,session_filter,rtibchat_c.newSession)
    app.all('/rtibchat/session/recover',urlParser,session_filter,rtibchat_c.recoverSession)
    app.all('/rtibchat/session/chat',urlParser,session_filter,rtibchat_c.chat)
    app.all('/rtibchat/session/chat/stop',urlParser,session_filter,rtibchat_c.stopChat)//停下(思考)
    app.all('/rtibchat/session/history',urlParser,session_filter,rtibchat_c.history)
    app.all('/rtibchat/session/save',urlParser,session_filter,rtibchat_c.saveSession)

    //加载setting
    try{
        let setting = JSON.parse( await file_util.readFile(window.config.runtime_current_dir +'/setting/rtibchat_setting.json'))
        model   = setting.model
        host    = setting.host
        session_path = setting.session_path
    }catch(ex)
    {
        console.error('loadding rtibchat_setting.json failed!',ex)
    }
}

//避免隐私泄露(直接内存中保存,定时镜像至磁盘?!)
const sessionsMap = new Map()
rtibchat_c.newSession = async function(req,res) 
{
    let {user_id} = str_filter.get_req_data(req)
    let session_id = 'rtibchat-session-'+Date.now()+'-'+ parseInt( Math.random()*1000000 )
    let sessionInfo = {user_id,session_id,time: parseInt(Date.now()/1000),datetime:str_filter.GetDateTimeFormat(parseInt(Date.now()/1000))}
    sessionsMap.set(session_id,sessionInfo)
    return res.json({ret:true,msg:'success',session_id})
}
/**
 * 恢复会话(用于定义Prompt模板--以分享给其它用户继续提问,例如预设了很多背景信息,以便进一步提问并输出结果分享)
 * @param {*} req 
 * @param {*} res 
 * @returns 
 */
rtibchat_c.recoverSession = async function(req,res) 
{
    let {user_id,history} = str_filter.get_req_data(req)
    let session_id = 'rtibchat-session-'+Date.now()+'-'+ parseInt( Math.random()*1000000 )
    try{
        history = JSON.parse(history)
        if(!history || history.length<=0) return res.json({ret:false,msg:'param(history) is empty'})
    }catch(ex)
    {
        return res.json({ret:false,msg:'param(history) is error'})
    }
    sessionsMap.set(session_id,{user_id,session_id,history})
    return res.json({ret:true,msg:'success',session_id})
}
/**
 * 聊天,支持历史纪录
 * @param {*} req 
 * @param {*} res 
 * @returns 
 */
rtibchat_c.chat = async function(req,res) 
{
    let {user_id,session_id,prompt,nostream} = str_filter.get_req_data(req)
    let sessionInfo =  sessionsMap.get(session_id)
    if(!sessionInfo) return res.json({ret:false,msg:'sessionInfo is empty'})
    if(sessionInfo.user_id != user_id) return res.json({ret:false,msg:'not your chat-session'})
    if(sessionInfo.http_req) return res.json({ret:false,msg:'you are chatting...please wait!'})
    let history = sessionInfo.history
    res.json({ret:true,msg:'success'})
    let stream = nostream ? false:true
    history = await ibchat(sessionInfo,req,prompt,history,stream)
    sessionInfo.history = history
}

/**
 * 关闭当前聊天(思考)
 * @param {*} req 
 * @param {*} res 
 * @returns 
 */
rtibchat_c.stopChat = async function(req,res) 
{
    let {user_id,session_id} = str_filter.get_req_data(req)
    let sessionInfo =  sessionsMap.get(session_id)
    if(!sessionInfo) return res.json({ret:false,msg:'sessionInfo is empty'})
    if(sessionInfo.user_id != user_id) return res.json({ret:false,msg:'not your chat-session'})
    if(!sessionInfo.http_req) return res.json({ret:false,msg:'not in chat'})
    let http_req = sessionInfo.http_req
    sessionInfo.http_req = null
    res.json({ret:true,msg:'success'})
    http_req.destroy()
}

rtibchat_c.history = async function(req,res) 
{
    let {user_id,session_id} = str_filter.get_req_data(req)
    let sessionInfo =  sessionsMap.get(session_id)
    if(!sessionInfo) return res.json({ret:false,msg:'sessionInfo is empty'})
    if(sessionInfo.user_id != user_id) return res.json({ret:false,msg:'not your chat-session'})
    let history = sessionInfo.history
    res.json({ret:true,msg:'success',history})
}

rtibchat_c.saveSession = async function(req,res) 
{
    let {user_id,session_id,share,s_id} = str_filter.get_req_data(req)
    let sessionInfo =  sessionsMap.get(session_id)
    if(!sessionInfo) return res.json({ret:false,msg:'sessionInfo is empty'})
    if(sessionInfo.user_id != user_id) return res.json({ret:false,msg:'not your chat-session'})
    let history = sessionInfo.history
    let saveObj = Object.assign({},sessionInfo)
    delete saveObj.http_req
    let filePath = session_path ? session_path :  window.config.runtime_current_dir +'/data'
    let fileName = session_id+'.json'
    saveObj.save_time = parseInt(Date.now()/1000)
    saveObj.save_datetime = str_filter.GetDateTimeFormat(parseInt(Date.now()/1000))
    let jsonStr = JSON.stringify(saveObj)
    let writeFlag = await file_util.writeFile(filePath +'/'+fileName,Buffer.from(jsonStr))
    if(!writeFlag) return res.json({ret:false,msg:'save session-file failed'})
    if(share)
    {
        if(!history || history.length<=0) return res.json({ret:false,msg:'session-history is empty'})
        //复制一份至file_temp
        let hash = await str_filter.hashVal(filePath +'/'+fileName)
        let fileWriteFlag = await file_util.writeFile(window.config.file_temp+'/'+hash,Buffer.from(jsonStr))
        if(!fileWriteFlag) return res.json({ret:false,msg:'save session-file to dnalink failed'})
        //user_id,s_id,hash,size,file_kind
        let fileInfo = {fieldname:"file",encoding:'fromfile_binary',originalname:fileName,
            mimetype:'application/json',filename:fileName,path:'file-path',
            size:Buffer.byteLength(jsonStr),file_kind:'file',random:Math.random(),data:null,user_id,s_id,hash}
        let fastSaveRet = await new Promise((resolve)=>{
            window.file_c.upload_file_fast({params:fileInfo},{
                json:function(data)
                {
                    resolve(data)
                }
            })
            setTimeout(()=>resolve({ret:false,msg:'fast save fileInfo timeout'}),30000)
        })
        fastSaveRet.first_question =history &&history.length>0 ?  history[0].content :'空问题'
        return res.json(fastSaveRet)
    }
    res.json({ret:true,msg:'success'})
}

async function ibchat(sessionInfo,req,prompt,history = [],stream = true) 
{
    history = history ? history :[]
    return await new Promise((resolve)=>{
        let  post_data={model,"messages":(history.concat([
            {
            role:'user',
            "content": prompt
            }
        ])),stream}; //这是需要提交的数据
        let  content=JSON.stringify(post_data)
        
        let  options = {
            host: host ,
            port: 11434,
            path: '/api/chat' ,
            method: 'POST' ,
            headers:{
            'Content-Type' : 'application/json' ,
            'Content-Length' :Buffer.byteLength(content)
            },
            //    body:content
        };
        console.log( "post options:\n" ,options);
        console.log( "content:" ,content);
        console.log( "\n" );
        
        let http_req = http.request(options, function (res) {
            console.log( "statusCode: " , res.statusCode,res);
            console.log( "headers: " , res.headers);
            let  _data= '' ;
            let result_content = ''
            res.on( 'data' , function (chunk){
                console.log('data:',chunk.toString(),post_data.messages[0].role)
                _data += chunk;
                result_content += JSON.parse(chunk.toString()).message.content
                if(sessionInfo.http_req == http_req) //在会话状态(否则已被手工关闭)
                req.peer.send(JSON.stringify({channel:'rtibchat',notify_type:sessionInfo.session_id,data:JSON.parse(chunk.toString())}))
            });
            res.on( 'end' , function (){
                sessionInfo.http_req = null //置为空
                console.log( "\n--->>\nresult:" ,_data)
                history.push({role:'user',"content": prompt})
                history.push({"role":"assistant","content":result_content})
                resolve(history)
            });
        });
        sessionInfo.http_req = http_req
        http_req.write(content);
        http_req.end();
    })
}

注:通过ollama的http-api实现了对deepseek-R1的stream=true的连续会话。基于dtns://协议提供了/rtibchat/session/new和recover等等的dtns-api接口,从而在dtns.ibchat中轻松集成了私有化部署版本的deepseek-R1:1.5B。轻松构建基于dtns.ibchat和dtns.dweb的Prompt提示语分享社群。

总结:通过dtns.ibchat智体聊,我们能与deepseek-R1进行深度的对话。并且将其分享到dtns.dweb头榜社区,实现了Prompt提示语会话纪录的开源、并允许任何人基于开源会话纪录继续对话和继续二次创作、二次分享。从而实现智体+AI+人类的超智慧个体的大规模出现。实现智体OS助力超级个体变身超人的slogan口号。