diff --git a/app/Filament/Actions/PreviewPromptAction.php b/app/Filament/Actions/PreviewPromptAction.php new file mode 100644 index 0000000..32d1031 --- /dev/null +++ b/app/Filament/Actions/PreviewPromptAction.php @@ -0,0 +1,91 @@ +label('预览提示词') + ->icon('heroicon-o-eye') + ->color('info') + ->modalHeading('提示词预览') + ->modalDescription('查看变量替换后的实际提示词内容') + ->modalWidth(MaxWidth::FourExtraLarge) + ->modalSubmitAction(false) + ->modalCancelActionLabel('关闭') + ->form(function ($record, $livewire) { + $service = app(PromptTemplateService::class); + + // 获取当前表单数据 + $data = $livewire->data ?? []; + $promptTemplate = $data['prompt']['prompt_template'] ?? ''; + + if (empty($promptTemplate)) { + return [ + Placeholder::make('empty') + ->label('') + ->content('请先输入提示词模板内容'), + ]; + } + + // 如果是编辑模式,使用记录的终端信息 + // 如果是创建模式,使用表单数据创建临时终端对象 + if ($record) { + $terminal = $record; + } else { + // 创建临时终端对象用于预览 + $terminal = new \App\Models\Terminal([ + 'name' => $data['name'] ?? '新终端', + 'code' => $data['code'] ?? 'TEMP-001', + 'station_id' => $data['station_id'] ?? null, + ]); + } + + // 替换变量 + $previewContent = $service->replaceVariables($promptTemplate, $terminal); + + // 验证变量 + $invalidVariables = $service->validateVariables($promptTemplate); + + return [ + Placeholder::make('original') + ->label('原始模板') + ->content(function () use ($promptTemplate) { + return view('filament.components.prompt-preview-original', [ + 'content' => $promptTemplate, + ]); + }), + + Placeholder::make('preview') + ->label('预览结果') + ->content(function () use ($previewContent) { + return view('filament.components.prompt-preview-result', [ + 'content' => $previewContent, + ]); + }), + + Placeholder::make('validation') + ->label('变量验证') + ->content(function () use ($invalidVariables) { + return view('filament.components.prompt-preview-validation', [ + 'invalidVariables' => $invalidVariables, + ]); + }) + ->visible(fn () => !empty($invalidVariables)), + ]; + }); + } +} diff --git a/app/Models/TerminalPrompt.php b/app/Models/TerminalPrompt.php index ca9e75b..df1ea63 100644 --- a/app/Models/TerminalPrompt.php +++ b/app/Models/TerminalPrompt.php @@ -2,13 +2,14 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Spatie\Activitylog\Traits\LogsActivity; use Spatie\Activitylog\LogOptions; class TerminalPrompt extends Model { - use LogsActivity; + use HasFactory, LogsActivity; /** * 可批量赋值的属性 * diff --git a/app/Services/PromptTemplateService.php b/app/Services/PromptTemplateService.php new file mode 100644 index 0000000..23776b3 --- /dev/null +++ b/app/Services/PromptTemplateService.php @@ -0,0 +1,168 @@ +getTemplates(); + + foreach ($templates as $template) { + if ($template['id'] === $templateId) { + return $template; + } + } + + return null; + } + + /** + * 应用模板到终端 + * + * @param Terminal $terminal + * @param string $templateId + * @return string + */ + public function applyTemplate(Terminal $terminal, string $templateId): string + { + $template = $this->getTemplate($templateId); + + if (!$template) { + throw new \InvalidArgumentException("模板不存在: {$templateId}"); + } + + return $template['content']; + } + + /** + * 替换模板中的变量 + * + * @param string $template + * @param Terminal $terminal + * @param array $additionalVars + * @return string + */ + public function replaceVariables(string $template, Terminal $terminal, array $additionalVars = []): string + { + $variables = $this->getVariableValues($terminal, $additionalVars); + + foreach ($variables as $key => $value) { + // 处理数组类型的变量 + if (is_array($value)) { + $value = implode(', ', $value); + } + + $template = str_replace('{' . $key . '}', $value, $template); + } + + return $template; + } + + /** + * 获取变量的实际值 + * + * @param Terminal $terminal + * @param array $additionalVars + * @return array + */ + public function getVariableValues(Terminal $terminal, array $additionalVars = []): array + { + $user = Auth::user(); + $now = now(); + + $variables = [ + 'user' => $user?->name ?? '访客', + 'user_id' => $user?->id ?? 0, + 'user_role' => $user?->roles?->first()?->name ?? '未知', + 'department' => $user?->department ?? '未知部门', + + 'station' => $terminal->station_id ? "工作站 {$terminal->station_id}" : '未绑定工作站', + 'station_id' => $terminal->station_id ?? '未绑定', + + 'terminal_name' => $terminal->name, + 'terminal_code' => $terminal->code, + + 'time' => $now->format('Y-m-d H:i:s'), + 'date' => $now->format('Y-m-d'), + 'time_only' => $now->format('H:i:s'), + 'shift' => $this->getCurrentShift($now), + + 'knowledge_bases' => $terminal->knowledgeBases->pluck('name')->toArray(), + + 'company_name' => config('app.name', '公司名称'), + ]; + + return array_merge($variables, $additionalVars); + } + + /** + * 根据时间判断当前班次 + * + * @param \Illuminate\Support\Carbon $time + * @return string + */ + protected function getCurrentShift($time): string + { + $hour = $time->hour; + + if ($hour >= 8 && $hour < 16) { + return '早班'; + } elseif ($hour >= 16 && $hour < 24) { + return '中班'; + } else { + return '夜班'; + } + } + + /** + * 预览模板(替换变量后的结果) + * + * @param string $template + * @param Terminal $terminal + * @return string + */ + public function preview(string $template, Terminal $terminal): string + { + return $this->replaceVariables($template, $terminal); + } + + /** + * 验证模板中的变量是否都是有效的 + * + * @param string $template + * @return array 返回无效的变量列表 + */ + public function validateVariables(string $template): array + { + $validVariables = array_column(config('prompt_variables.variables', []), 'name'); + + // 提取模板中的所有变量 + preg_match_all('/\{([a-z_]+)\}/', $template, $matches); + $usedVariables = $matches[1] ?? []; + + // 找出无效的变量 + $invalidVariables = array_diff($usedVariables, $validVariables); + + return array_values(array_unique($invalidVariables)); + } +} diff --git a/config/prompt_templates.php b/config/prompt_templates.php new file mode 100644 index 0000000..5ec3020 --- /dev/null +++ b/config/prompt_templates.php @@ -0,0 +1,222 @@ + [ + [ + 'id' => 'general_assistant', + 'name' => '通用助手', + 'description' => '适用于一般性问答和操作指导的AI助手', + 'category' => 'general', + 'content' => <<<'TEMPLATE' +# AI助手角色定义 + +你是一个专业的工业生产助手,为 {company_name} 的员工提供帮助。 + +## 当前上下文 +- 用户:{user}({user_role}) +- 工作站:{station} +- 终端:{terminal_name} +- 时间:{time} +- 班次:{shift} + +## 你的职责 +1. 回答用户关于生产流程、设备操作的问题 +2. 提供安全操作指导 +3. 协助查找相关文档和资料 +4. 记录和反馈异常情况 + +## 知识库 +你可以参考以下知识库:{knowledge_bases} + +## 回答原则 +- 使用简洁、专业的语言 +- 优先考虑安全性 +- 如果不确定,建议咨询专业人员 +- 保持友好和耐心的态度 +TEMPLATE + ], + + [ + 'id' => 'safety_focused', + 'name' => '安全专员', + 'description' => '专注于安全操作指导和风险提示的AI助手', + 'category' => 'safety', + 'content' => <<<'TEMPLATE' +# 安全专员AI助手 + +你是 {company_name} 的安全专员助手,负责确保 {station} 的安全生产。 + +## 当前信息 +- 操作员:{user} +- 工作站:{station} +- 当前时间:{time} + +## 核心职责 +1. **安全第一**:所有建议都必须符合安全规范 +2. **风险识别**:主动识别和提示潜在风险 +3. **应急指导**:提供紧急情况的处理步骤 +4. **合规检查**:确保操作符合安全标准 + +## 参考资料 +安全知识库:{knowledge_bases} + +## 回答要求 +- 每次回答前先评估安全风险 +- 使用警示性语言强调重要安全事项 +- 提供具体的安全操作步骤 +- 遇到高风险操作,必须建议停止并联系主管 + +⚠️ 安全提示:如有任何疑问,请立即停止操作并联系安全主管! +TEMPLATE + ], + + [ + 'id' => 'troubleshooting', + 'name' => '故障诊断', + 'description' => '专门用于设备故障诊断和问题排查的AI助手', + 'category' => 'maintenance', + 'content' => <<<'TEMPLATE' +# 故障诊断AI助手 + +你是 {company_name} 的设备维护助手,帮助 {user} 诊断和解决 {station} 的设备问题。 + +## 当前环境 +- 工作站:{station} +- 终端:{terminal_name} +- 报告时间:{time} +- 操作员:{user} + +## 诊断流程 +1. **问题确认**:详细了解故障现象和发生时间 +2. **初步判断**:基于症状进行初步分析 +3. **排查步骤**:提供系统化的排查方法 +4. **解决方案**:给出可行的解决建议 +5. **预防措施**:提供预防类似问题的建议 + +## 可用资源 +维护知识库:{knowledge_bases} + +## 工作原则 +- 采用结构化的诊断方法 +- 从简单到复杂逐步排查 +- 记录所有诊断步骤和结果 +- 超出能力范围时及时上报 +- 确保维修过程的安全性 + +💡 提示:详细描述故障现象有助于快速定位问题 +TEMPLATE + ], + + [ + 'id' => 'training_coach', + 'name' => '培训教练', + 'description' => '用于新员工培训和操作指导的AI助手', + 'category' => 'training', + 'content' => <<<'TEMPLATE' +# 培训教练AI助手 + +欢迎 {user}!我是你的培训教练,将帮助你熟悉 {station} 的操作。 + +## 培训信息 +- 学员:{user}({user_role}) +- 培训工作站:{station} +- 培训时间:{time} +- 班次:{shift} + +## 培训目标 +1. 掌握基本操作流程 +2. 理解安全操作规范 +3. 熟悉设备功能和特性 +4. 学会常见问题处理 + +## 教学方法 +- **循序渐进**:从基础到高级逐步学习 +- **实践为主**:通过实际操作加深理解 +- **及时反馈**:对操作给予即时指导 +- **重复强化**:重要知识点多次强调 +- **鼓励提问**:营造轻松的学习氛围 + +## 学习资源 +培训资料:{knowledge_bases} + +## 互动方式 +- 随时提问,我会耐心解答 +- 不理解的地方可以要求重复讲解 +- 可以要求演示具体操作步骤 +- 学习过程中遇到困难及时告诉我 + +📚 学习提示:不要着急,每个人都有学习过程,慢慢来! +TEMPLATE + ], + + [ + 'id' => 'quality_inspector', + 'name' => '质量检查', + 'description' => '专注于质量控制和检验指导的AI助手', + 'category' => 'quality', + 'content' => <<<'TEMPLATE' +# 质量检查AI助手 + +你是 {company_name} 的质量控制助手,协助 {user} 进行 {station} 的质量检验工作。 + +## 检验信息 +- 检验员:{user} +- 检验工作站:{station} +- 检验时间:{time} +- 班次:{shift} + +## 质量标准 +参考以下质量文档:{knowledge_bases} + +## 检验流程 +1. **准备工作**:确认检验工具和标准 +2. **外观检查**:检查产品外观质量 +3. **尺寸测量**:测量关键尺寸参数 +4. **功能测试**:验证产品功能性能 +5. **记录结果**:详细记录检验数据 +6. **判定处理**:根据标准做出判定 + +## 工作原则 +- 严格按照质量标准执行 +- 保持客观公正的态度 +- 详细记录检验数据 +- 及时反馈质量问题 +- 持续改进质量意识 + +## 异常处理 +- 发现不合格品立即隔离 +- 记录详细的不合格信息 +- 通知相关责任人 +- 协助分析原因 + +✓ 质量承诺:质量是企业的生命,让我们共同守护! +TEMPLATE + ], + ], + + /* + |-------------------------------------------------------------------------- + | 模板分类 + |-------------------------------------------------------------------------- + | + | 模板的分类标签 + | + */ + + 'categories' => [ + 'general' => '通用', + 'safety' => '安全', + 'maintenance' => '维护', + 'training' => '培训', + 'quality' => '质量', + ], +]; diff --git a/config/prompt_variables.php b/config/prompt_variables.php new file mode 100644 index 0000000..ce1014d --- /dev/null +++ b/config/prompt_variables.php @@ -0,0 +1,146 @@ + [ + [ + 'name' => 'user', + 'label' => '用户名称', + 'description' => '当前登录用户的姓名', + 'example' => '张三', + 'type' => 'string', + 'category' => 'user', + ], + [ + 'name' => 'user_id', + 'label' => '用户ID', + 'description' => '当前登录用户的唯一标识符', + 'example' => '12345', + 'type' => 'integer', + 'category' => 'user', + ], + [ + 'name' => 'user_role', + 'label' => '用户角色', + 'description' => '当前登录用户的角色', + 'example' => '操作员', + 'type' => 'string', + 'category' => 'user', + ], + [ + 'name' => 'station', + 'label' => '工作站名称', + 'description' => '终端所在的工作站名称', + 'example' => '生产线A-工位1', + 'type' => 'string', + 'category' => 'station', + ], + [ + 'name' => 'station_id', + 'label' => '工作站ID', + 'description' => '终端所在的工作站ID', + 'example' => '1001', + 'type' => 'integer', + 'category' => 'station', + ], + [ + 'name' => 'terminal_name', + 'label' => '终端名称', + 'description' => '当前终端的名称', + 'example' => 'TERM-0001', + 'type' => 'string', + 'category' => 'terminal', + ], + [ + 'name' => 'terminal_code', + 'label' => '终端编码', + 'description' => '当前终端的唯一编码', + 'example' => 'TERM-0001', + 'type' => 'string', + 'category' => 'terminal', + ], + [ + 'name' => 'time', + 'label' => '当前时间', + 'description' => '当前的日期和时间', + 'example' => '2024-01-15 14:30:00', + 'type' => 'datetime', + 'category' => 'time', + ], + [ + 'name' => 'date', + 'label' => '当前日期', + 'description' => '当前的日期', + 'example' => '2024-01-15', + 'type' => 'date', + 'category' => 'time', + ], + [ + 'name' => 'time_only', + 'label' => '当前时刻', + 'description' => '当前的时间(不含日期)', + 'example' => '14:30:00', + 'type' => 'time', + 'category' => 'time', + ], + [ + 'name' => 'shift', + 'label' => '当前班次', + 'description' => '当前的工作班次', + 'example' => '早班', + 'type' => 'string', + 'category' => 'time', + ], + [ + 'name' => 'knowledge_bases', + 'label' => '关联知识库', + 'description' => '终端关联的知识库列表', + 'example' => '安全操作规程, 设备维护手册', + 'type' => 'array', + 'category' => 'knowledge', + ], + [ + 'name' => 'company_name', + 'label' => '公司名称', + 'description' => '系统配置的公司名称', + 'example' => 'XX制造有限公司', + 'type' => 'string', + 'category' => 'system', + ], + [ + 'name' => 'department', + 'label' => '部门名称', + 'description' => '用户所属的部门', + 'example' => '生产部', + 'type' => 'string', + 'category' => 'user', + ], + ], + + /* + |-------------------------------------------------------------------------- + | 变量分类 + |-------------------------------------------------------------------------- + | + | 变量的分类标签,用于在UI中分组显示 + | + */ + + 'categories' => [ + 'user' => '用户信息', + 'station' => '工作站信息', + 'terminal' => '终端信息', + 'time' => '时间信息', + 'knowledge' => '知识库信息', + 'system' => '系统信息', + ], +]; diff --git a/database/factories/TerminalPromptFactory.php b/database/factories/TerminalPromptFactory.php new file mode 100644 index 0000000..7258d72 --- /dev/null +++ b/database/factories/TerminalPromptFactory.php @@ -0,0 +1,29 @@ + + */ +class TerminalPromptFactory extends Factory +{ + protected $model = TerminalPrompt::class; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'terminal_id' => Terminal::factory(), + 'prompt_template' => $this->faker->paragraph(5), + 'variables' => ['user', 'station', 'time'], + ]; + } +} diff --git a/resources/views/filament/components/prompt-preview-original.blade.php b/resources/views/filament/components/prompt-preview-original.blade.php new file mode 100644 index 0000000..2cfaaec --- /dev/null +++ b/resources/views/filament/components/prompt-preview-original.blade.php @@ -0,0 +1,9 @@ +
+
+ + + + 原始模板(包含变量) +
+
{{ $content }}
+
diff --git a/resources/views/filament/components/prompt-preview-result.blade.php b/resources/views/filament/components/prompt-preview-result.blade.php new file mode 100644 index 0000000..9c51b2b --- /dev/null +++ b/resources/views/filament/components/prompt-preview-result.blade.php @@ -0,0 +1,12 @@ +
+
+ + + + + 预览结果(变量已替换) +
+
+
{{ $content }}
+
+
diff --git a/resources/views/filament/components/prompt-preview-validation.blade.php b/resources/views/filament/components/prompt-preview-validation.blade.php new file mode 100644 index 0000000..9aeafa8 --- /dev/null +++ b/resources/views/filament/components/prompt-preview-validation.blade.php @@ -0,0 +1,27 @@ +
+
+ + + +
+
+ 发现无效变量 +
+
+ 以下变量未在系统中定义,可能无法正确替换: +
+
    + @foreach($invalidVariables as $variable) +
  • + + {{'{'}}{{ $variable }}{{'}'}} + +
  • + @endforeach +
+
+ 💡 提示:请检查变量名称是否正确,或参考右侧的"变量参考"面板查看所有可用变量。 +
+
+
+
diff --git a/resources/views/filament/components/prompt-template-selector.blade.php b/resources/views/filament/components/prompt-template-selector.blade.php new file mode 100644 index 0000000..ee2af2a --- /dev/null +++ b/resources/views/filament/components/prompt-template-selector.blade.php @@ -0,0 +1,106 @@ +@php + $templates = config('prompt_templates.templates', []); + $categories = config('prompt_templates.categories', []); + $groupedTemplates = collect($templates)->groupBy('category'); +@endphp + +
+

+ 快速模板 +

+ +
+ 选择一个预设模板快速开始,您可以在此基础上进行修改 +
+ +
+ @foreach($groupedTemplates as $category => $temps) +
+

+ + {{ $categories[$category] ?? $category }} +

+
+ @foreach($temps as $template) + + @endforeach +
+
+ @endforeach +
+ +
+
+ + + + 点击模板将自动填充到编辑器中,您可以根据需要进行修改 +
+
+
+ + diff --git a/resources/views/filament/components/prompt-variable-helper.blade.php b/resources/views/filament/components/prompt-variable-helper.blade.php new file mode 100644 index 0000000..90d62f2 --- /dev/null +++ b/resources/views/filament/components/prompt-variable-helper.blade.php @@ -0,0 +1,54 @@ +
+

+ 可用变量 +

+ +
+ 在提示词模板中使用 {变量名} 格式引用变量 +
+ + @php + $variables = config('prompt_variables.variables', []); + $categories = config('prompt_variables.categories', []); + $groupedVariables = collect($variables)->groupBy('category'); + @endphp + +
+ @foreach($groupedVariables as $category => $vars) +
+

+ {{ $categories[$category] ?? $category }} +

+
+ @foreach($vars as $variable) +
+ + {{'{'}}{{ $variable['name'] }}{{'}'}} + +
+
+ {{ $variable['label'] }} +
+
+ {{ $variable['description'] }} +
+
+ 示例: {{ $variable['example'] }} +
+
+
+ @endforeach +
+
+ @endforeach +
+ +
+

使用示例

+
+
你好,{{'{'}}user{{'}'}}!
+
当前时间是 {{'{'}}time{{'}'}},你在 {{'{'}}station{{'}'}}
+
请参考以下知识库:{{'{'}}knowledge_bases{{'}'}}。
+
+
+