提交代码
This commit is contained in:
parent
abdbe0ff2f
commit
14d114771b
71
application/admin/controller/deepseek/Question.php
Normal file
71
application/admin/controller/deepseek/Question.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\deepseek;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
|
||||
/**
|
||||
* deepseek提问
|
||||
*
|
||||
* @icon fa fa-circle-o
|
||||
*/
|
||||
class Question extends Backend
|
||||
{
|
||||
|
||||
/**
|
||||
* Question模型对象
|
||||
* @var \app\admin\model\deepseek\Question
|
||||
*/
|
||||
protected $model = null;
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
parent::_initialize();
|
||||
$this->model = new \app\admin\model\deepseek\Question;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
|
||||
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
|
||||
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//当前是否为关联查询
|
||||
$this->relationSearch = true;
|
||||
//设置过滤方法
|
||||
$this->request->filter(['strip_tags', 'trim']);
|
||||
if ($this->request->isAjax()) {
|
||||
//如果发送的来源是Selectpage,则转发到Selectpage
|
||||
if ($this->request->request('keyField')) {
|
||||
return $this->selectpage();
|
||||
}
|
||||
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
|
||||
|
||||
$list = $this->model
|
||||
->with(['user'])
|
||||
->where($where)
|
||||
->order($sort, $order)
|
||||
->paginate($limit);
|
||||
|
||||
foreach ($list as $row) {
|
||||
|
||||
$row->getRelation('user')->visible(['nickname','mobile','avatar']);
|
||||
}
|
||||
|
||||
$result = array("total" => $list->total(), "rows" => $list->items());
|
||||
|
||||
return json($result);
|
||||
}
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
}
|
71
application/admin/controller/deepseek/Stream.php
Normal file
71
application/admin/controller/deepseek/Stream.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\deepseek;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
|
||||
/**
|
||||
* deepseek流式应答采集数据
|
||||
*
|
||||
* @icon fa fa-circle-o
|
||||
*/
|
||||
class Stream extends Backend
|
||||
{
|
||||
|
||||
/**
|
||||
* Stream模型对象
|
||||
* @var \app\admin\model\deepseek\Stream
|
||||
*/
|
||||
protected $model = null;
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
parent::_initialize();
|
||||
$this->model = new \app\admin\model\deepseek\Stream;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
|
||||
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
|
||||
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//当前是否为关联查询
|
||||
$this->relationSearch = true;
|
||||
//设置过滤方法
|
||||
$this->request->filter(['strip_tags', 'trim']);
|
||||
if ($this->request->isAjax()) {
|
||||
//如果发送的来源是Selectpage,则转发到Selectpage
|
||||
if ($this->request->request('keyField')) {
|
||||
return $this->selectpage();
|
||||
}
|
||||
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
|
||||
|
||||
$list = $this->model
|
||||
->with(['question'])
|
||||
->where($where)
|
||||
->order($sort, $order)
|
||||
->paginate($limit);
|
||||
|
||||
foreach ($list as $row) {
|
||||
|
||||
$row->getRelation('question')->visible(['user_id','content']);
|
||||
}
|
||||
|
||||
$result = array("total" => $list->total(), "rows" => $list->items());
|
||||
|
||||
return json($result);
|
||||
}
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
}
|
12
application/admin/lang/zh-cn/deepseek/question.php
Normal file
12
application/admin/lang/zh-cn/deepseek/question.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Id' => '提问id',
|
||||
'User_id' => '提问用户',
|
||||
'Content' => '提问的问题',
|
||||
'Createtime' => '创建时间',
|
||||
'Endtime' => '答完时间',
|
||||
'User.nickname' => '昵称',
|
||||
'User.mobile' => '手机号',
|
||||
'User.avatar' => '头像'
|
||||
];
|
15
application/admin/lang/zh-cn/deepseek/stream.php
Normal file
15
application/admin/lang/zh-cn/deepseek/stream.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Id' => 'id',
|
||||
'Question_id' => '提问id',
|
||||
'Assistant_id' => '应答id',
|
||||
'Object' => '应答对象',
|
||||
'Created_time' => '应答时间',
|
||||
'Model' => '应答模型',
|
||||
'Usage_json' => 'usagejson',
|
||||
'Choices_json' => '应答实体json',
|
||||
'Createtime' => '创建时间',
|
||||
'Question.user_id' => '提问用户',
|
||||
'Question.content' => '提问的问题'
|
||||
];
|
52
application/admin/model/deepseek/Question.php
Normal file
52
application/admin/model/deepseek/Question.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model\deepseek;
|
||||
|
||||
use think\Model;
|
||||
|
||||
|
||||
class Question extends Model
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'deepseek_question';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
'endtime_text'
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function getEndtimeTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['endtime']) ? $data['endtime'] : '');
|
||||
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
|
||||
}
|
||||
|
||||
protected function setEndtimeAttr($value)
|
||||
{
|
||||
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
|
||||
}
|
||||
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('app\admin\model\User', 'user_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
}
|
52
application/admin/model/deepseek/Stream.php
Normal file
52
application/admin/model/deepseek/Stream.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model\deepseek;
|
||||
|
||||
use think\Model;
|
||||
|
||||
|
||||
class Stream extends Model
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'deepseek_stream';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
'created_time_text'
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function getCreatedTimeTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['created_time']) ? $data['created_time'] : '');
|
||||
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
|
||||
}
|
||||
|
||||
protected function setCreatedTimeAttr($value)
|
||||
{
|
||||
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
|
||||
}
|
||||
|
||||
|
||||
public function question()
|
||||
{
|
||||
return $this->belongsTo('Question', 'question_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
}
|
27
application/admin/validate/deepseek/Question.php
Normal file
27
application/admin/validate/deepseek/Question.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\validate\deepseek;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class Question extends Validate
|
||||
{
|
||||
/**
|
||||
* 验证规则
|
||||
*/
|
||||
protected $rule = [
|
||||
];
|
||||
/**
|
||||
* 提示消息
|
||||
*/
|
||||
protected $message = [
|
||||
];
|
||||
/**
|
||||
* 验证场景
|
||||
*/
|
||||
protected $scene = [
|
||||
'add' => [],
|
||||
'edit' => [],
|
||||
];
|
||||
|
||||
}
|
27
application/admin/validate/deepseek/Stream.php
Normal file
27
application/admin/validate/deepseek/Stream.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\validate\deepseek;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class Stream extends Validate
|
||||
{
|
||||
/**
|
||||
* 验证规则
|
||||
*/
|
||||
protected $rule = [
|
||||
];
|
||||
/**
|
||||
* 提示消息
|
||||
*/
|
||||
protected $message = [
|
||||
];
|
||||
/**
|
||||
* 验证场景
|
||||
*/
|
||||
protected $scene = [
|
||||
'add' => [],
|
||||
'edit' => [],
|
||||
];
|
||||
|
||||
}
|
27
application/admin/view/deepseek/question/add.html
Normal file
27
application/admin/view/deepseek/question/add.html
Normal file
@ -0,0 +1,27 @@
|
||||
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-user_id" data-rule="required" data-source="user/user/index" data-field="nickname" class="form-control selectpage" name="row[user_id]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-content" class="form-control" name="row[content]" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Endtime')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-endtime" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[endtime]" type="text" value="{:date('Y-m-d H:i:s')}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
27
application/admin/view/deepseek/question/edit.html
Normal file
27
application/admin/view/deepseek/question/edit.html
Normal file
@ -0,0 +1,27 @@
|
||||
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-user_id" data-rule="required" data-source="user/user/index" data-field="nickname" class="form-control selectpage" name="row[user_id]" type="text" value="{$row.user_id|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-content" class="form-control" name="row[content]" type="text" value="{$row.content|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Endtime')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-endtime" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[endtime]" type="text" value="{:$row.endtime?datetime($row.endtime):''}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
29
application/admin/view/deepseek/question/index.html
Normal file
29
application/admin/view/deepseek/question/index.html
Normal file
@ -0,0 +1,29 @@
|
||||
<div class="panel panel-default panel-intro">
|
||||
{:build_heading()}
|
||||
|
||||
<div class="panel-body">
|
||||
<div id="myTabContent" class="tab-content">
|
||||
<div class="tab-pane fade active in" id="one">
|
||||
<div class="widget-body no-padding">
|
||||
<div id="toolbar" class="toolbar">
|
||||
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
|
||||
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('deepseek/question/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
|
||||
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('deepseek/question/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
|
||||
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('deepseek/question/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('deepseek/question/edit')}"
|
||||
data-operate-del="{:$auth->check('deepseek/question/del')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
71
application/admin/view/deepseek/stream/add.html
Normal file
71
application/admin/view/deepseek/stream/add.html
Normal file
@ -0,0 +1,71 @@
|
||||
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Question_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-question_id" data-rule="required" data-source="deepseek/question/index" class="form-control selectpage" name="row[question_id]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Assistant_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-assistant_id" data-rule="required" data-source="assistant/index" class="form-control selectpage" name="row[assistant_id]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Object')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-object" class="form-control" name="row[object]" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Created_time')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-created_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[created_time]" type="text" value="{:date('Y-m-d H:i:s')}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Model')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-model" class="form-control" name="row[model]" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Usage_json')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
||||
<dl class="fieldlist" data-name="row[usage_json]">
|
||||
<dd>
|
||||
<ins>{:__('Key')}</ins>
|
||||
<ins>{:__('Value')}</ins>
|
||||
</dd>
|
||||
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
|
||||
<textarea name="row[usage_json]" class="form-control hide" cols="30" rows="5"></textarea>
|
||||
</dl>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Choices_json')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
||||
<dl class="fieldlist" data-name="row[choices_json]">
|
||||
<dd>
|
||||
<ins>{:__('Key')}</ins>
|
||||
<ins>{:__('Value')}</ins>
|
||||
</dd>
|
||||
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
|
||||
<textarea name="row[choices_json]" class="form-control hide" cols="30" rows="5"></textarea>
|
||||
</dl>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
71
application/admin/view/deepseek/stream/edit.html
Normal file
71
application/admin/view/deepseek/stream/edit.html
Normal file
@ -0,0 +1,71 @@
|
||||
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Question_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-question_id" data-rule="required" data-source="deepseek/question/index" class="form-control selectpage" name="row[question_id]" type="text" value="{$row.question_id|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Assistant_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-assistant_id" data-rule="required" data-source="assistant/index" class="form-control selectpage" name="row[assistant_id]" type="text" value="{$row.assistant_id|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Object')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-object" class="form-control" name="row[object]" type="text" value="{$row.object|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Created_time')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-created_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[created_time]" type="text" value="{:$row.created_time?datetime($row.created_time):''}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Model')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-model" class="form-control" name="row[model]" type="text" value="{$row.model|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Usage_json')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
||||
<dl class="fieldlist" data-name="row[usage_json]">
|
||||
<dd>
|
||||
<ins>{:__('Key')}</ins>
|
||||
<ins>{:__('Value')}</ins>
|
||||
</dd>
|
||||
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
|
||||
<textarea name="row[usage_json]" class="form-control hide" cols="30" rows="5">{$row.usage_json|htmlentities}</textarea>
|
||||
</dl>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Choices_json')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
||||
<dl class="fieldlist" data-name="row[choices_json]">
|
||||
<dd>
|
||||
<ins>{:__('Key')}</ins>
|
||||
<ins>{:__('Value')}</ins>
|
||||
</dd>
|
||||
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
|
||||
<textarea name="row[choices_json]" class="form-control hide" cols="30" rows="5">{$row.choices_json|htmlentities}</textarea>
|
||||
</dl>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
29
application/admin/view/deepseek/stream/index.html
Normal file
29
application/admin/view/deepseek/stream/index.html
Normal file
@ -0,0 +1,29 @@
|
||||
<div class="panel panel-default panel-intro">
|
||||
{:build_heading()}
|
||||
|
||||
<div class="panel-body">
|
||||
<div id="myTabContent" class="tab-content">
|
||||
<div class="tab-pane fade active in" id="one">
|
||||
<div class="widget-body no-padding">
|
||||
<div id="toolbar" class="toolbar">
|
||||
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
|
||||
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('deepseek/stream/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
|
||||
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('deepseek/stream/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
|
||||
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('deepseek/stream/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('deepseek/stream/edit')}"
|
||||
data-operate-del="{:$auth->check('deepseek/stream/del')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
239
application/api/controller/deepseek/Deepseek.php
Normal file
239
application/api/controller/deepseek/Deepseek.php
Normal file
@ -0,0 +1,239 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller\deepseek;
|
||||
|
||||
use app\common\model\deepseek\Question;
|
||||
use app\common\model\deepseek\Stream;
|
||||
use app\common\controller\Api;
|
||||
class Deepseek extends Api{
|
||||
|
||||
protected $noNeedLogin = ['*'];
|
||||
protected $noNeedRight = ['*'];
|
||||
|
||||
|
||||
protected $model = null;
|
||||
protected $listmodel = null;
|
||||
|
||||
/**
|
||||
* 初始化操作
|
||||
* @access protected
|
||||
*/
|
||||
protected function _initialize()
|
||||
{
|
||||
|
||||
$this->model = new Question();
|
||||
$this->listmodel = new Stream();
|
||||
parent::_initialize();
|
||||
|
||||
//判断登录用户是否是员工
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ApiTitle(deepseek提问)
|
||||
* @ApiSummary(deepseek提问)
|
||||
* @ApiMethod(POST)
|
||||
* @ApiParams(name = "messages", type = "string",required=true,description = "提问数组 {'role': 'user', 'content': '中原算力是一个什么样的公司'},{'role': 'assistant', 'content': '</think>'} ")
|
||||
* @ApiParams(name = "key", type = "string",required=true,description = "单次提问唯一key")
|
||||
* @ApiParams(name = "session_key", type = "string",required=false,description = "会话唯一key:不传默认取当前日期")
|
||||
* @ApiReturn({
|
||||
|
||||
*
|
||||
*})
|
||||
*/
|
||||
public function question(){
|
||||
|
||||
$this->setUrlLock("all","deepseek-question");
|
||||
|
||||
$messages = $this->request->post('messages/s',"");
|
||||
$messages = htmlspecialchars_decode($messages);
|
||||
$key = $this->request->post('key/s',"");
|
||||
$session_key = $this->request->post('session_key/s',"");
|
||||
//不传默认取当前日期
|
||||
if(!$session_key) $session_key = date("Ymd");
|
||||
// $messages = "[{'role': 'user', 'content': '中原算力是一个什么样的公司'},{'role': 'assistant', 'content': '</think>'}]";
|
||||
// var_dump($messages);
|
||||
$user_id = 0;
|
||||
$user = $this->auth->getUser();//登录用户
|
||||
if($user)$user_id = $user['id'];
|
||||
// if(empty($id)){
|
||||
// $this->error(__('缺少必要参数'));
|
||||
// }
|
||||
|
||||
try {
|
||||
$res = $this->model->question($messages,$user_id,$key,$session_key,false);
|
||||
} catch (\Exception $e){
|
||||
// Log::log($e->getMessage());
|
||||
$this->error($e->getMessage(),['errcode'=>$e->getCode()]);
|
||||
}
|
||||
$this->success('请求成功,请求结果请轮询查询结果接口', ['detail' => $res]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @ApiTitle( 输出结果查询接口-list为空数组为在思考中)
|
||||
* @ApiSummary(输出结果查询接口)
|
||||
* @ApiMethod(GET)
|
||||
* @ApiParams(name = "key", type = "string",required=false,description = "提问时自定义的key或提问id")
|
||||
* @ApiParams(name = "page", type = "string",required=true,description = "页数")
|
||||
* @ApiParams(name = "limit", type = "string",required=true,description = "条数")
|
||||
* @ApiParams(name = "session_key", type = "string",required=false,description = "会话id")
|
||||
* @ApiReturn({
|
||||
*
|
||||
*})
|
||||
*/
|
||||
public function answer_list()
|
||||
{
|
||||
$user_id = 0;
|
||||
$user = $this->auth->getUser();//登录用户
|
||||
if($user)$user_id = $user['id'];
|
||||
|
||||
$params = [];
|
||||
$my = $this->request->get('my/d', 0); //我的评价
|
||||
if($my && $user_id){
|
||||
$params['user_id'] = $user_id;
|
||||
}
|
||||
$page = $this->request->get('page/d', 1); //页数
|
||||
$limit = $this->request->get('limit/d', 10); //条数
|
||||
$params["key"] = $this->request->get('key/s', ''); //搜索关键字
|
||||
$params["session_key"] = $this->request->get('session_key/s', ''); //搜索关键字
|
||||
|
||||
|
||||
try{
|
||||
//当前申请状态
|
||||
$res = $this->listmodel::answerList($page, $limit,$params);
|
||||
// if($user_id =='670153'){
|
||||
// file_put_contents("ceshi66.txt",(new AppointmentOrder())->getLastSql());
|
||||
// }
|
||||
}catch (\Exception $e){
|
||||
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success('查询成功', $res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @ApiTitle( 查询我的所有会话)
|
||||
* @ApiSummary(查询我的所有会话)
|
||||
* @ApiMethod(GET)
|
||||
* @ApiReturn({
|
||||
*
|
||||
*})
|
||||
*/
|
||||
public function seesion_list()
|
||||
{
|
||||
$user_id = 0;
|
||||
$user = $this->auth->getUser();//登录用户
|
||||
if($user)$user_id = $user['id'];
|
||||
|
||||
// $params = [];
|
||||
// $my = $this->request->get('my/d', 0); //我的评价
|
||||
// if($my && $user_id){
|
||||
// $params['user_id'] = $user_id;
|
||||
// }
|
||||
// $page = $this->request->get('page/d', 1); //页数
|
||||
// $limit = $this->request->get('limit/d', 1000); //条数
|
||||
// $params["key"] = $this->request->get('key/s', ''); //搜索关键字
|
||||
// $params["session_key"] = $this->request->get('session_key/s', ''); //搜索关键字
|
||||
|
||||
|
||||
try{
|
||||
//当前申请状态
|
||||
$res = $this->model->getSeesionlist($user_id);
|
||||
// if($user_id =='670153'){
|
||||
// file_put_contents("ceshi66.txt",(new AppointmentOrder())->getLastSql());
|
||||
// }
|
||||
}catch (\Exception $e){
|
||||
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success('查询成功', $res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @ApiTitle( 提问记录记录)
|
||||
* @ApiSummary(提问记录)
|
||||
* @ApiMethod(GET)
|
||||
* @ApiParams(name = "page", type = "string",required=true,description = "页数")
|
||||
* @ApiParams(name = "limit", type = "string",required=true,description = "条数")
|
||||
* @ApiParams(name = "session_key", type = "string",required=false,description = "会话id")
|
||||
* @ApiReturn({
|
||||
*
|
||||
*})
|
||||
*/
|
||||
public function question_list()
|
||||
{
|
||||
$user_id = 0;
|
||||
$user = $this->auth->getUser();//登录用户
|
||||
if($user)$user_id = $user['id'];
|
||||
|
||||
$params = [];
|
||||
// $my = $this->request->get('my/d', 0); //我的评价
|
||||
if($user_id){
|
||||
$params['user_id'] = $user_id;
|
||||
}
|
||||
$page = $this->request->get('page/d', 1); //页数
|
||||
$limit = $this->request->get('limit/d', 10); //条数
|
||||
$params["session_key"] = $this->request->get('session_key/s', ''); //搜索关键字
|
||||
|
||||
|
||||
try{
|
||||
//当前申请状态
|
||||
$res = $this->model::questionList($page, $limit,$params);
|
||||
// if($user_id =='670153'){
|
||||
// file_put_contents("ceshi66.txt",(new AppointmentOrder())->getLastSql());
|
||||
// }
|
||||
}catch (\Exception $e){
|
||||
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success('查询成功', $res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @ApiTitle( 删除会话)
|
||||
* @ApiSummary(删除会话)
|
||||
* @ApiMethod(GET)
|
||||
* @ApiParams(name = "session_key", type = "string",required=false,description = "会话id")
|
||||
* @ApiReturn({
|
||||
*
|
||||
*})
|
||||
*/
|
||||
public function delete_session()
|
||||
{ $user_id = 0;
|
||||
$user = $this->auth->getUser();//登录用户
|
||||
if($user)$user_id = $user['id'];
|
||||
|
||||
$session_key = $this->request->get('session_key/s', ''); //搜索关键字
|
||||
|
||||
|
||||
try{
|
||||
//当前申请状态
|
||||
$res = $this->model->session_del($session_key,true);
|
||||
// if($user_id =='670153'){
|
||||
// file_put_contents("ceshi66.txt",(new AppointmentOrder())->getLastSql());
|
||||
// }
|
||||
}catch (\Exception $e){
|
||||
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success('查询成功', $res);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -86,6 +86,33 @@ class Api
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected $needUrlLock = [];
|
||||
|
||||
protected function setUrlLock($url_key="",$url_suffix="",$model=null){
|
||||
if(($this->request->isPost() || (!empty($this->needUrlLock) && in_array($this->request->action(),$this->needUrlLock))) && (!empty($this->model) || $model)){
|
||||
$user_id = 0;
|
||||
$user = $this->auth->getUser();//登录用户
|
||||
if($user)$user_id = $user['id'];
|
||||
|
||||
$modulename = $this->request->module();
|
||||
$controllername = Loader::parseName($this->request->controller());
|
||||
$actionname = strtolower($this->request->action());
|
||||
$path = $modulename . '/' . str_replace('.', '/', $controllername) . '/' . $actionname;
|
||||
if(!$model){
|
||||
$this->model::$url_lock_key = $url_key ?: $user_id;
|
||||
$this->model::$url_lock_suffix = $url_suffix ?: $path."lock-suffix";
|
||||
$this->model::$url_lock = true;
|
||||
}else{
|
||||
$model::$url_lock_key = $url_key ?: $user_id;
|
||||
$model::$url_lock_suffix = $url_suffix ?: $path."lock-suffix";
|
||||
$model::$url_lock = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化操作
|
||||
* @access protected
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace app\common\controller;
|
||||
|
||||
use app\admin\library\Auth;
|
||||
use app\admin\model\Admin;
|
||||
use think\Config;
|
||||
use think\Controller;
|
||||
use think\Hook;
|
||||
@ -114,6 +115,75 @@ class Backend extends Controller
|
||||
*/
|
||||
use \app\admin\library\traits\Backend;
|
||||
|
||||
protected $qSwitch = false;
|
||||
protected $qFields = [];
|
||||
|
||||
protected function checkAssemblyParameters(){
|
||||
if(!$this->qSwitch)return false;
|
||||
//得到所有get参数
|
||||
$get = $this->request->get();
|
||||
//得到当前model所有字段
|
||||
|
||||
|
||||
$fields = $this->model->getTableFields();
|
||||
|
||||
// $commonFields = (new Field())->getCommonFields();
|
||||
// var_dump($commonFields);
|
||||
$fieldLists = $fields;
|
||||
// foreach ($commonFields as $commonField) {
|
||||
// if (!in_array($commonField['column_name'], $fields)) {
|
||||
// $fieldLists[] = $commonField;
|
||||
// }
|
||||
// }
|
||||
$q_fields = [];
|
||||
|
||||
foreach ($get as $kay=>$getField) {
|
||||
if (in_array($kay, $fieldLists)) {
|
||||
$q_fields[$kay] = $getField;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//将q_fields塞入模板中
|
||||
foreach ($q_fields as $k=>$v) {
|
||||
//渲染站点配置
|
||||
$this->assign('q_'.$k, $v);
|
||||
}
|
||||
|
||||
foreach ($this->qFields as $k) {
|
||||
//渲染站点配置
|
||||
if(!isset($q_fields[$k]))$this->assign('q_'.$k, "");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected $needUrlLock = [];
|
||||
|
||||
public function setUrlLock($url_key="",$url_suffix="",$model=null){
|
||||
if(($this->request->isPost() || (!empty($this->needUrlLock) && in_array($this->request->action(),$this->needUrlLock))) && (!empty($this->model) || $model)){
|
||||
$user_id = $this->auth->id ?? 0;
|
||||
// $user = $this->auth->getUser();//登录用户
|
||||
// if($user)$user_id = $user['id'];
|
||||
|
||||
$modulename = $this->request->module();
|
||||
$controllername = Loader::parseName($this->request->controller());
|
||||
$actionname = strtolower($this->request->action());
|
||||
$path = $modulename . '/' . str_replace('.', '/', $controllername) . '/' . $actionname;
|
||||
if(!$model){
|
||||
$this->model::$url_lock_key = $url_key ?: $user_id;
|
||||
$this->model::$url_lock_suffix = $url_suffix ?: $path."lock-suffix";
|
||||
$this->model::$url_lock = true;
|
||||
}else{
|
||||
$model::$url_lock_key = $url_key ?: $user_id;
|
||||
$model::$url_lock_suffix = $url_suffix ?: $path."lock-suffix";
|
||||
$model::$url_lock = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
$modulename = $this->request->module();
|
||||
@ -228,6 +298,8 @@ class Backend extends Controller
|
||||
$this->assign('auth', $this->auth);
|
||||
//渲染管理员对象
|
||||
$this->assign('admin', Session::get('admin'));
|
||||
|
||||
$this->checkAssemblyParameters();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,7 +331,7 @@ class Backend extends Controller
|
||||
* @param boolean $relationSearch 是否关联查询
|
||||
* @return array
|
||||
*/
|
||||
protected function buildparams($searchfields = null, $relationSearch = null)
|
||||
protected function buildparams($searchfields = null, $relationSearch = null,$excludefields = [])
|
||||
{
|
||||
$searchfields = is_null($searchfields) ? $this->searchFields : $searchfields;
|
||||
$relationSearch = is_null($relationSearch) ? $this->relationSearch : $relationSearch;
|
||||
@ -281,6 +353,7 @@ class Backend extends Controller
|
||||
$op = (array)json_decode($op, true);
|
||||
$filter = $filter ? $filter : [];
|
||||
$where = [];
|
||||
$excludearray = [];
|
||||
$alias = [];
|
||||
$bind = [];
|
||||
$name = '';
|
||||
@ -314,6 +387,19 @@ class Backend extends Controller
|
||||
continue;
|
||||
}
|
||||
$sym = $op[$k] ?? '=';
|
||||
//忽略的查询条件出现在忽略数组中 2022年9月6日18:55:17
|
||||
if(in_array($k, $excludefields)){
|
||||
$excludearray[$k]['value'] = $v;
|
||||
$excludearray[$k]['op'] = $sym;
|
||||
|
||||
if (stripos($k, ".") === false) {
|
||||
$excludearray[$k]['alias'] = $aliasName;
|
||||
}
|
||||
unset($filter[$k]);
|
||||
unset($op[$k]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stripos($k, ".") === false) {
|
||||
$k = $aliasName . $k;
|
||||
}
|
||||
@ -368,8 +454,8 @@ class Backend extends Controller
|
||||
case 'NOT BETWEEN':
|
||||
$arr = array_slice(explode(',', $v), 0, 2);
|
||||
if (stripos($v, ',') === false || !array_filter($arr, function ($v) {
|
||||
return $v != '' && $v !== false && $v !== null;
|
||||
})) {
|
||||
return $v != '' && $v !== false && $v !== null;
|
||||
})) {
|
||||
continue 2;
|
||||
}
|
||||
//当出现一边为空时改变操作符
|
||||
@ -434,7 +520,7 @@ class Backend extends Controller
|
||||
}
|
||||
}
|
||||
};
|
||||
return [$where, $sort, $order, $offset, $limit, $page, $alias, $bind];
|
||||
return [$where, $sort, $order, $offset, $limit, $page, $alias, $bind,$excludearray];
|
||||
}
|
||||
|
||||
/**
|
||||
|
350
application/common/model/deepseek/Question.php
Normal file
350
application/common/model/deepseek/Question.php
Normal file
@ -0,0 +1,350 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model\deepseek;
|
||||
|
||||
use app\common\model\BaseModel;
|
||||
use think\Model;
|
||||
|
||||
|
||||
class Question extends BaseModel
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'deepseek_question';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
'endtime_text',
|
||||
'reasoning_text',
|
||||
'answer_text'
|
||||
];
|
||||
|
||||
|
||||
public function getReasoningTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['id']) ? $data['id'] : '');
|
||||
//Stream model拼接所有question_id=$value =list中的所有content字段成完整字符串文本
|
||||
$contents = Stream::where('question_id', $value)->where('reasoning', 1)->order('created_time asc,reasoning desc,id asc')->column("content");
|
||||
return implode("", $contents);
|
||||
}
|
||||
|
||||
public function getAnswerTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['id']) ? $data['id'] : '');
|
||||
$contents = Stream::where('question_id', $value)->where('reasoning', 0)->order('created_time asc,reasoning desc,id asc')->column("content");
|
||||
return implode("", $contents);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function getEndtimeTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['endtime']) ? $data['endtime'] : '');
|
||||
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
|
||||
}
|
||||
|
||||
protected function setEndtimeAttr($value)
|
||||
{
|
||||
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
|
||||
}
|
||||
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('app\common\model\User', 'user_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
public function question($messages, $user_id, $key,$session_key,$trans = false)
|
||||
{
|
||||
if (!$messages) throw new \Exception('缺少必要参数1');
|
||||
if (!$key) throw new \Exception('缺少必要参数2');
|
||||
|
||||
$self = self::where('key', $key)->find();
|
||||
if($self) throw new \Exception('key已被消耗');
|
||||
//解析json成属数组
|
||||
$messages = json_decode($messages, true);
|
||||
if (!$messages) throw new \Exception('json解析失败');
|
||||
//messages的json格式为{"role": "user", "content": "中原算力是一个什么样的公司"},{"role": "assistant", "content": "</think>"}
|
||||
//messages得到最后一个role名为assistant的对象并向上一个role为user的对象
|
||||
|
||||
//得到官网请求地址
|
||||
$deepseek_web_url = config("site.deepseek_web_url");
|
||||
//得到官网请求密钥
|
||||
$deepseek_key = "Bearer " . config("site.deepseek_key");
|
||||
//得到本地部署的请求地址
|
||||
$deepseek_local_url = config("site.deepseek_local_url");
|
||||
//得到切换开关
|
||||
$deepseek_switch = config("site.deepseek_switch");
|
||||
$reasoning =true;
|
||||
$last = end($messages);
|
||||
if ($last['role'] == 'assistant') {
|
||||
$last = prev($messages);
|
||||
if ($last['role'] != 'user') {
|
||||
throw new \Exception('messages参数错误!');
|
||||
}
|
||||
}
|
||||
|
||||
//访问deepseek脚本存在超时可能会超时,所以需要设置超时时间为10分钟
|
||||
set_time_limit(6000);
|
||||
|
||||
//组转json请求参数准备请求deepseekapi :{
|
||||
//"model": "qwen",
|
||||
//"messages": [
|
||||
//{"role": "user", "content": "中原算力是一个什么样的公司"},{"role": "assistant", "content": "</think>"}
|
||||
//],
|
||||
//"stream": true,
|
||||
//"temperature":0.6
|
||||
//}
|
||||
$data = [
|
||||
'model' => $deepseek_switch ? 'qwen':'deepseek-reasoner',
|
||||
'messages' => $messages,
|
||||
'stream' => true,
|
||||
'temperature' => 0.6,
|
||||
];
|
||||
|
||||
// var_dump($data);die;
|
||||
|
||||
|
||||
|
||||
//判断逻辑
|
||||
if ($trans) {
|
||||
self::beginTrans();
|
||||
}
|
||||
$res = true;
|
||||
try {
|
||||
|
||||
//保存本次请求model
|
||||
$datas = [
|
||||
'user_id' => $user_id,
|
||||
'content' => $last["content"],
|
||||
"key"=>$key,
|
||||
"session_key" => $session_key,
|
||||
];
|
||||
//保存数据库并得自增id
|
||||
$self = self::create($datas);
|
||||
// var_dump($self);die;
|
||||
$question_id = $self->id;
|
||||
|
||||
|
||||
// 判断逻辑
|
||||
$url = $deepseek_switch ? $deepseek_local_url : $deepseek_web_url;
|
||||
$headers = $deepseek_switch ? [] : ['Authorization:' . $deepseek_key];
|
||||
|
||||
|
||||
// 发送curl post json格式的 stream式请求
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge(['Content-Type: application/json'], $headers));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $data) use (&$response,$question_id,$deepseek_switch,&$reasoning,$session_key) {
|
||||
// var_dump($data);
|
||||
|
||||
if (!$data) {
|
||||
return 0; // 结束流式请求
|
||||
}
|
||||
|
||||
// var_dump($data);
|
||||
$data = htmlspecialchars_decode($data);
|
||||
// 处理每一部分数据
|
||||
// $lines = explode("\n", trim($data));
|
||||
$lines = explode("\n",$data);
|
||||
foreach ($lines as $line) {
|
||||
if (strpos($line, "data: ") === 0) {
|
||||
$json = substr($line, 6);
|
||||
$chunk = json_decode($json, true);
|
||||
|
||||
|
||||
if (isset($chunk['choices'][0]['delta']['reasoning_content'])) {
|
||||
$chunk['choices'][0]['delta']['reasoning_content'] = htmlspecialchars_decode($chunk['choices'][0]['delta']['reasoning_content']);
|
||||
|
||||
// 将数据写入数据库
|
||||
// 假设有一个方法 saveStreamData 用于保存数据
|
||||
$this->saveStreamData($chunk['choices'][0]['delta']['reasoning_content'],$chunk,$question_id,true,$session_key);
|
||||
}
|
||||
|
||||
if (isset($chunk['choices'][0]['delta']['content'])) {
|
||||
|
||||
$chunk['choices'][0]['delta']['content'] = htmlspecialchars_decode($chunk['choices'][0]['delta']['content']);
|
||||
|
||||
if($deepseek_switch){
|
||||
//本地部署</think>为结尾
|
||||
if(strpos($chunk['choices'][0]['delta']['content'],'</think>')!==false){
|
||||
$reasoning = false;
|
||||
}else{
|
||||
$this->saveStreamData($chunk['choices'][0]['delta']['content'],$chunk,$question_id,$reasoning,$session_key);
|
||||
}
|
||||
|
||||
}else{
|
||||
//官方调用
|
||||
|
||||
|
||||
// 将数据写入数据库
|
||||
// 假设有一个方法 saveStreamData 用于保存数据
|
||||
$this->saveStreamData($chunk['choices'][0]['delta']['content'],$chunk,$question_id,false,$session_key);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理每一部分数据
|
||||
// $json = $data;
|
||||
// $chunk = json_decode($json, true);
|
||||
// if (isset($chunk['choices'][0]['delta']['content'])) {
|
||||
// // 将数据写入数据库
|
||||
// // 假设有一个方法 saveStreamData 用于保存数据
|
||||
// $this->saveStreamData($chunk['choices'][0]['delta']['content'],$chunk,$question_id);
|
||||
// }
|
||||
|
||||
return strlen($data);
|
||||
});
|
||||
|
||||
curl_exec($ch);
|
||||
$curl_error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($curl_error) {
|
||||
throw new \Exception('Curl error: ' . $curl_error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($trans) {
|
||||
self::commitTrans();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
if ($trans) {
|
||||
self::rollbackTrans();
|
||||
}
|
||||
throw new \Exception($e->getMessage() . $e->getFile() . $e->getLine());
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
// 假设有一个方法 saveStreamData 用于保存数据
|
||||
protected function saveStreamData($content,$chunk,$question_id,$reasoning = false,$session_key)
|
||||
{
|
||||
// 实现保存数据到数据库的逻辑
|
||||
$data = [
|
||||
'question_id' => $question_id,
|
||||
'assistant_id' => $chunk["id"],
|
||||
'object' => $chunk["object"],
|
||||
"created_time" => $chunk["created"],
|
||||
"model" => $chunk["model"],
|
||||
"usage_json" => isset($chunk["usage"])? htmlspecialchars_decode(json_encode( $chunk["usage"])) : '',
|
||||
"choices_json" => isset($chunk["choices"])? htmlspecialchars_decode(json_encode($chunk["choices"])): '',
|
||||
"content" => $content,
|
||||
"reasoning" => $reasoning,
|
||||
"session_key" =>$session_key
|
||||
];
|
||||
Stream::create($data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function getSeesionlist($user_id=0){
|
||||
//用当前模型查询问题qusetion列表,返回每个会话session_key下的最后一个问题,组成列表返回
|
||||
$list = self::where("user_id",$user_id)->group("session_key")->order("createtime desc")->select();
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**得到基础条件
|
||||
* @param $status
|
||||
* @param null $model
|
||||
* @param string $alisa
|
||||
*/
|
||||
public static function getBaseWhere($whereData = [], $model = null, $alisa = '',$with = false)
|
||||
{
|
||||
|
||||
if (!$model) {
|
||||
$model = new static;
|
||||
if ($alisa&&!$with) $model = $model->alias($alisa);
|
||||
}
|
||||
if ($alisa) $alisa = $alisa . '.';
|
||||
$tableFields = (new static)->getTableFields();
|
||||
foreach ($tableFields as $fields)
|
||||
{
|
||||
// if(in_array($fields, ['key']))continue;
|
||||
// if (isset($whereData[$fields]) && $whereData[$fields]) $model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]);
|
||||
|
||||
if (isset($whereData[$fields]) && $whereData[$fields]){
|
||||
if(is_array($whereData[$fields])){
|
||||
$model = $model->where("{$alisa}{$fields}", $whereData[$fields][0], $whereData[$fields][1]);
|
||||
}else{
|
||||
$model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (isset($whereData['time'])&&$whereData['time']){
|
||||
$model = $model->time(["{$alisa}createtime",$whereData['time']]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
|
||||
public static function questionList($page, $limit,$params=[]){
|
||||
$with_field = [
|
||||
'base'=>['*'],
|
||||
];
|
||||
// $alisa = (new self)->getWithAlisaName();
|
||||
$sort = "id asc";
|
||||
$serch_where = [];
|
||||
$serch_where = array_merge($serch_where,$params);
|
||||
return (new self)->getBaseList($serch_where, $page, $limit,$sort,$with_field);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function session_del($session_key,$trans=false){
|
||||
//判断逻辑
|
||||
if($trans){
|
||||
self::beginTrans();
|
||||
}
|
||||
$res = true;
|
||||
try{
|
||||
//根据session_key删除问题
|
||||
$question_list = self::where("session_key",$session_key)->delete();
|
||||
//根据session_key删除stream
|
||||
$stream_list = Stream::where("session_key",$session_key)->delete();
|
||||
|
||||
if($trans){
|
||||
self::commitTrans();
|
||||
}
|
||||
}catch (\Exception $e){
|
||||
if($trans){
|
||||
self::rollbackTrans();
|
||||
}
|
||||
throw new \Exception($e->getMessage().$e->getFile().$e->getLine());
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
133
application/common/model/deepseek/Stream.php
Normal file
133
application/common/model/deepseek/Stream.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model\deepseek;
|
||||
|
||||
use app\common\model\BaseModel;
|
||||
use think\Model;
|
||||
|
||||
|
||||
class Stream extends BaseModel
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 表名
|
||||
protected $name = 'deepseek_stream';
|
||||
|
||||
// 自动写入时间戳字段
|
||||
protected $autoWriteTimestamp = 'integer';
|
||||
|
||||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
protected $deleteTime = false;
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
'created_time_text'
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function getCreatedTimeTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['created_time']) ? $data['created_time'] : '');
|
||||
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
|
||||
}
|
||||
|
||||
protected function setCreatedTimeAttr($value)
|
||||
{
|
||||
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
|
||||
}
|
||||
|
||||
|
||||
public function question()
|
||||
{
|
||||
return $this->belongsTo('Question', 'question_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
|
||||
public function getUsageJsonAttr($value, $data)
|
||||
{
|
||||
return $value === '' ? [] : json_decode($value, true);
|
||||
}
|
||||
|
||||
|
||||
public function getChoicesJsonAttr($value, $data)
|
||||
{
|
||||
return $value === '' ? [] : json_decode($value, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**得到基础条件
|
||||
* @param $status
|
||||
* @param null $model
|
||||
* @param string $alisa
|
||||
*/
|
||||
public static function getBaseWhere($whereData = [], $model = null, $alisa = '',$with = false)
|
||||
{
|
||||
|
||||
if (!$model) {
|
||||
$model = new static;
|
||||
if ($alisa&&!$with) $model = $model->alias($alisa);
|
||||
}
|
||||
if ($alisa) $alisa = $alisa . '.';
|
||||
$tableFields = (new static)->getTableFields();
|
||||
foreach ($tableFields as $fields)
|
||||
{
|
||||
if(in_array($fields, ['key']))continue;
|
||||
// if (isset($whereData[$fields]) && $whereData[$fields]) $model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]);
|
||||
|
||||
if (isset($whereData[$fields]) && $whereData[$fields]){
|
||||
if(is_array($whereData[$fields])){
|
||||
$model = $model->where("{$alisa}{$fields}", $whereData[$fields][0], $whereData[$fields][1]);
|
||||
}else{
|
||||
$model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (isset($whereData['key'])&&$whereData['key']){
|
||||
$question = Question::where("id|key", '=', $whereData['key'])->find();
|
||||
if(!$question){
|
||||
$model = $model->where("{$alisa}question_id", '=', -1);
|
||||
}else{
|
||||
$model = $model->where("{$alisa}question_id", '=', $question["id"]);
|
||||
}
|
||||
|
||||
}
|
||||
if (isset($whereData['time'])&&$whereData['time']){
|
||||
$model = $model->time(["{$alisa}created_time",$whereData['time']]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
|
||||
public static function answerList($page, $limit,$params=[]){
|
||||
$with_field = [
|
||||
'base'=>['*'],
|
||||
];
|
||||
// $alisa = (new self)->getWithAlisaName();
|
||||
$sort = "created_time asc,reasoning desc,id asc";
|
||||
$serch_where = [];
|
||||
$serch_where = array_merge($serch_where,$params);
|
||||
return (new self)->getBaseList($serch_where, $page, $limit,$sort,$with_field);
|
||||
}
|
||||
|
||||
}
|
@ -18,7 +18,7 @@ return [
|
||||
// 应用命名空间
|
||||
'app_namespace' => 'app',
|
||||
// 应用调试模式
|
||||
'app_debug' => Env::get('app.debug', false),
|
||||
'app_debug' => Env::get('app.debug', true),
|
||||
// 应用Trace
|
||||
'app_trace' => Env::get('app.trace', false),
|
||||
// 应用模式状态
|
||||
@ -159,7 +159,7 @@ return [
|
||||
// 错误显示信息,非调试模式有效
|
||||
'error_message' => '你所浏览的页面暂时无法访问',
|
||||
// 显示错误信息
|
||||
'show_error_msg' => false,
|
||||
'show_error_msg' => true,
|
||||
// 异常处理handle类 留空使用 \think\exception\Handle
|
||||
'exception_handle' => '',
|
||||
// +----------------------------------------------------------------------
|
||||
@ -306,4 +306,13 @@ return [
|
||||
//API接口地址
|
||||
'api_url' => 'https://api.fastadmin.net',
|
||||
],
|
||||
//增加 redis 配置
|
||||
'redis' => [
|
||||
'host' => '127.0.0.1', // redis 主机地址
|
||||
'password' => '', // redis 密码
|
||||
'port' => 6379, // redis 端口
|
||||
'select' => 3, // redis 数据库
|
||||
'timeout' => 0, // redis 超时时间
|
||||
'persistent' => false, // redis 持续性,连接复用
|
||||
]
|
||||
];
|
||||
|
57
public/assets/js/backend/deepseek/question.js
Normal file
57
public/assets/js/backend/deepseek/question.js
Normal file
@ -0,0 +1,57 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'deepseek/question/index' + location.search,
|
||||
add_url: 'deepseek/question/add',
|
||||
edit_url: 'deepseek/question/edit',
|
||||
del_url: 'deepseek/question/del',
|
||||
multi_url: 'deepseek/question/multi',
|
||||
import_url: 'deepseek/question/import',
|
||||
table: 'deepseek_question',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'id',
|
||||
columns: [
|
||||
[
|
||||
{checkbox: true},
|
||||
{field: 'id', title: __('Id')},
|
||||
{field: 'user_id', title: __('User_id')},
|
||||
{field: 'content', title: __('Content'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
|
||||
{field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
|
||||
{field: 'endtime', title: __('Endtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
|
||||
{field: 'user.nickname', title: __('User.nickname'), operate: 'LIKE'},
|
||||
{field: 'user.mobile', title: __('User.mobile'), operate: 'LIKE'},
|
||||
{field: 'user.avatar', title: __('User.avatar'), operate: 'LIKE', events: Table.api.events.image, formatter: Table.api.formatter.image},
|
||||
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
58
public/assets/js/backend/deepseek/stream.js
Normal file
58
public/assets/js/backend/deepseek/stream.js
Normal file
@ -0,0 +1,58 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'deepseek/stream/index' + location.search,
|
||||
add_url: 'deepseek/stream/add',
|
||||
edit_url: 'deepseek/stream/edit',
|
||||
del_url: 'deepseek/stream/del',
|
||||
multi_url: 'deepseek/stream/multi',
|
||||
import_url: 'deepseek/stream/import',
|
||||
table: 'deepseek_stream',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'id',
|
||||
columns: [
|
||||
[
|
||||
{checkbox: true},
|
||||
{field: 'id', title: __('Id')},
|
||||
{field: 'question_id', title: __('Question_id')},
|
||||
{field: 'assistant_id', title: __('Assistant_id'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
|
||||
{field: 'object', title: __('Object'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
|
||||
{field: 'created_time', title: __('Created_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
|
||||
{field: 'model', title: __('Model'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
|
||||
{field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
|
||||
{field: 'question.user_id', title: __('Question.user_id')},
|
||||
{field: 'question.content', title: __('Question.content'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
|
||||
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user