744 lines
22 KiB
Dart
744 lines
22 KiB
Dart
import 'package:flutter/material.dart';
|
||
|
||
import '../../../models/prompt_models.dart';
|
||
import '../../../services/api_service/repositories/impl/admin_repository_templates_extension.dart';
|
||
import '../../../services/api_service/repositories/impl/admin_repository_impl.dart';
|
||
import '../../../utils/web_theme.dart';
|
||
import '../../../utils/logger.dart';
|
||
import '../../../widgets/common/dialog_container.dart';
|
||
import '../../../widgets/common/dialog_header.dart';
|
||
|
||
/// 编辑提示词模板对话框
|
||
class EditTemplateDialog extends StatefulWidget {
|
||
final PromptTemplate template;
|
||
final VoidCallback? onSuccess;
|
||
|
||
const EditTemplateDialog({
|
||
Key? key,
|
||
required this.template,
|
||
this.onSuccess,
|
||
}) : super(key: key);
|
||
|
||
@override
|
||
State<EditTemplateDialog> createState() => _EditTemplateDialogState();
|
||
}
|
||
|
||
class _EditTemplateDialogState extends State<EditTemplateDialog> with TickerProviderStateMixin {
|
||
final _formKey = GlobalKey<FormState>();
|
||
late final TextEditingController _nameController;
|
||
late final TextEditingController _descriptionController;
|
||
late final TextEditingController _systemPromptController;
|
||
late final TextEditingController _userPromptController;
|
||
late final TextEditingController _tagsController;
|
||
|
||
late AIFeatureType _featureType;
|
||
late bool _isPublic;
|
||
late bool _isVerified;
|
||
late bool _isDefault;
|
||
bool _isLoading = false;
|
||
bool _isEdited = false;
|
||
|
||
late TabController _tabController;
|
||
|
||
final AdminRepositoryImpl _adminRepository = AdminRepositoryImpl();
|
||
|
||
final List<AIFeatureType> _featureTypes = [
|
||
AIFeatureType.textExpansion,
|
||
AIFeatureType.textRefactor,
|
||
AIFeatureType.textSummary,
|
||
AIFeatureType.sceneToSummary,
|
||
AIFeatureType.summaryToScene,
|
||
AIFeatureType.aiChat,
|
||
AIFeatureType.novelGeneration,
|
||
AIFeatureType.professionalFictionContinuation,
|
||
AIFeatureType.sceneBeatGeneration,
|
||
AIFeatureType.novelCompose,
|
||
AIFeatureType.settingTreeGeneration,
|
||
];
|
||
|
||
final Map<AIFeatureType, String> _featureTypeLabels = {
|
||
AIFeatureType.textExpansion: '文本扩写',
|
||
AIFeatureType.textRefactor: '文本润色',
|
||
AIFeatureType.textSummary: '文本总结',
|
||
AIFeatureType.sceneToSummary: '场景转摘要',
|
||
AIFeatureType.summaryToScene: '摘要转场景',
|
||
AIFeatureType.aiChat: 'AI对话',
|
||
AIFeatureType.novelGeneration: '小说生成',
|
||
AIFeatureType.professionalFictionContinuation: '专业续写',
|
||
AIFeatureType.sceneBeatGeneration: '场景节拍生成',
|
||
AIFeatureType.novelCompose: '设定编排',
|
||
AIFeatureType.settingTreeGeneration: '设定树生成',
|
||
};
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_tabController = TabController(length: 2, vsync: this);
|
||
_initializeControllers();
|
||
}
|
||
|
||
void _initializeControllers() {
|
||
_nameController = TextEditingController(text: widget.template.name);
|
||
_descriptionController = TextEditingController(text: widget.template.description ?? '');
|
||
// 将content拆分为systemPrompt和userPrompt,这里简单处理
|
||
_systemPromptController = TextEditingController(text: '');
|
||
_userPromptController = TextEditingController(text: widget.template.content);
|
||
_tagsController = TextEditingController(text: widget.template.templateTags?.join(', ') ?? '');
|
||
|
||
_featureType = widget.template.featureType;
|
||
_isPublic = widget.template.isPublic;
|
||
_isVerified = widget.template.isVerified;
|
||
_isDefault = widget.template.isDefault;
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_tabController.dispose();
|
||
_nameController.dispose();
|
||
_descriptionController.dispose();
|
||
_systemPromptController.dispose();
|
||
_userPromptController.dispose();
|
||
_tagsController.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return DialogContainer(
|
||
maxWidth: 800,
|
||
height: 700,
|
||
child: Column(
|
||
children: [
|
||
DialogHeader(
|
||
title: '编辑模板 - ${widget.template.name}',
|
||
onClose: () => Navigator.of(context).pop(),
|
||
),
|
||
_buildTopBar(),
|
||
_buildTabBar(),
|
||
Expanded(
|
||
child: TabBarView(
|
||
controller: _tabController,
|
||
children: [
|
||
_buildContentEditor(),
|
||
_buildPropertiesEditor(),
|
||
],
|
||
),
|
||
),
|
||
_buildActions(),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
/// 构建顶部标题栏(参考业务组件)
|
||
Widget _buildTopBar() {
|
||
return Container(
|
||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||
decoration: BoxDecoration(
|
||
color: WebTheme.getSurfaceColor(context),
|
||
border: Border(
|
||
bottom: BorderSide(
|
||
color: WebTheme.getBorderColor(context),
|
||
width: 1.0,
|
||
),
|
||
),
|
||
),
|
||
child: Row(
|
||
children: [
|
||
// 模板标题编辑
|
||
Expanded(
|
||
child: TextField(
|
||
controller: _nameController,
|
||
style: TextStyle(
|
||
fontSize: 18,
|
||
fontWeight: FontWeight.w600,
|
||
color: WebTheme.getTextColor(context),
|
||
height: 1.2,
|
||
),
|
||
decoration: InputDecoration(
|
||
hintText: '输入模板名称...',
|
||
border: InputBorder.none,
|
||
hintStyle: TextStyle(
|
||
color: WebTheme.getSecondaryTextColor(context),
|
||
),
|
||
),
|
||
onChanged: (value) {
|
||
setState(() {
|
||
_isEdited = true;
|
||
});
|
||
},
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
/// 构建标签栏
|
||
Widget _buildTabBar() {
|
||
return Container(
|
||
decoration: BoxDecoration(
|
||
color: WebTheme.getSurfaceColor(context),
|
||
border: Border(
|
||
bottom: BorderSide(
|
||
color: WebTheme.getBorderColor(context),
|
||
width: 1.0,
|
||
),
|
||
),
|
||
),
|
||
child: TabBar(
|
||
controller: _tabController,
|
||
labelColor: WebTheme.getTextColor(context),
|
||
unselectedLabelColor: WebTheme.getSecondaryTextColor(context),
|
||
indicatorColor: WebTheme.getTextColor(context),
|
||
dividerColor: Colors.transparent,
|
||
tabs: const [
|
||
Tab(
|
||
text: '内容编辑',
|
||
icon: Icon(Icons.edit, size: 16),
|
||
),
|
||
Tab(
|
||
text: '属性设置',
|
||
icon: Icon(Icons.settings, size: 16),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
/// 构建内容编辑器(参考 PromptContentEditor)
|
||
Widget _buildContentEditor() {
|
||
return Container(
|
||
color: WebTheme.getSurfaceColor(context),
|
||
padding: const EdgeInsets.all(16),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
// 占位符提示
|
||
_buildPlaceholderChips(),
|
||
|
||
const SizedBox(height: 16),
|
||
|
||
// 系统提示词编辑器
|
||
_buildSystemPromptEditor(),
|
||
|
||
const SizedBox(height: 16),
|
||
|
||
// 用户提示词编辑器
|
||
Expanded(
|
||
child: _buildUserPromptEditor(),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
/// 构建占位符提示
|
||
Widget _buildPlaceholderChips() {
|
||
final placeholders = [
|
||
'content', 'context', 'requirement', 'style', 'length'
|
||
];
|
||
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
'可用占位符',
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.w600,
|
||
color: WebTheme.getTextColor(context),
|
||
),
|
||
),
|
||
const SizedBox(height: 8),
|
||
Wrap(
|
||
spacing: 8,
|
||
runSpacing: 4,
|
||
children: placeholders.map((placeholder) => _buildPlaceholderChip(placeholder)).toList(),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
/// 构建占位符芯片
|
||
Widget _buildPlaceholderChip(String placeholder) {
|
||
final primaryColor = WebTheme.getPrimaryColor(context);
|
||
|
||
return Tooltip(
|
||
message: _getPlaceholderDescription(placeholder),
|
||
child: ActionChip(
|
||
label: Text(
|
||
'{$placeholder}',
|
||
style: TextStyle(
|
||
fontSize: 12,
|
||
color: primaryColor,
|
||
),
|
||
),
|
||
onPressed: () {
|
||
_insertPlaceholder(placeholder);
|
||
},
|
||
backgroundColor: primaryColor.withOpacity(0.1),
|
||
side: BorderSide(
|
||
color: primaryColor.withOpacity(0.3),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
/// 构建系统提示词编辑器
|
||
Widget _buildSystemPromptEditor() {
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
'系统提示词 (System Prompt)',
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.w600,
|
||
color: WebTheme.getTextColor(context),
|
||
),
|
||
),
|
||
const SizedBox(height: 8),
|
||
Container(
|
||
height: 120,
|
||
decoration: BoxDecoration(
|
||
border: Border.all(
|
||
color: WebTheme.getBorderColor(context),
|
||
),
|
||
borderRadius: BorderRadius.circular(8),
|
||
color: WebTheme.getSurfaceColor(context),
|
||
),
|
||
child: TextField(
|
||
controller: _systemPromptController,
|
||
maxLines: null,
|
||
expands: true,
|
||
textAlignVertical: TextAlignVertical.top,
|
||
decoration: InputDecoration(
|
||
hintText: '输入系统提示词...\n\n系统提示词用于设置AI的角色和基本行为规则。',
|
||
hintStyle: TextStyle(
|
||
color: WebTheme.getSecondaryTextColor(context),
|
||
),
|
||
border: InputBorder.none,
|
||
contentPadding: const EdgeInsets.all(12),
|
||
),
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
height: 1.4,
|
||
color: WebTheme.getTextColor(context),
|
||
),
|
||
onChanged: (value) {
|
||
setState(() {
|
||
_isEdited = true;
|
||
});
|
||
},
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
/// 构建用户提示词编辑器
|
||
Widget _buildUserPromptEditor() {
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
'用户提示词 (User Prompt)',
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.w600,
|
||
color: WebTheme.getTextColor(context),
|
||
),
|
||
),
|
||
const SizedBox(height: 8),
|
||
Expanded(
|
||
child: Container(
|
||
decoration: BoxDecoration(
|
||
border: Border.all(
|
||
color: WebTheme.getBorderColor(context),
|
||
),
|
||
borderRadius: BorderRadius.circular(8),
|
||
color: WebTheme.getSurfaceColor(context),
|
||
),
|
||
child: TextField(
|
||
controller: _userPromptController,
|
||
maxLines: null,
|
||
expands: true,
|
||
textAlignVertical: TextAlignVertical.top,
|
||
decoration: InputDecoration(
|
||
hintText: '输入用户提示词...\n\n用户提示词包含具体的任务指令和要求。可以使用占位符来动态插入内容。',
|
||
hintStyle: TextStyle(
|
||
color: WebTheme.getSecondaryTextColor(context),
|
||
),
|
||
border: InputBorder.none,
|
||
contentPadding: const EdgeInsets.all(12),
|
||
),
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
height: 1.4,
|
||
color: WebTheme.getTextColor(context),
|
||
),
|
||
onChanged: (value) {
|
||
setState(() {
|
||
_isEdited = true;
|
||
});
|
||
},
|
||
),
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
/// 构建属性编辑器(参考 PromptPropertiesEditor)
|
||
Widget _buildPropertiesEditor() {
|
||
return Container(
|
||
color: WebTheme.getSurfaceColor(context),
|
||
padding: const EdgeInsets.all(16),
|
||
child: SingleChildScrollView(
|
||
child: Form(
|
||
key: _formKey,
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
_buildBasicInfo(),
|
||
const SizedBox(height: 24),
|
||
_buildSettings(),
|
||
const SizedBox(height: 24),
|
||
_buildMetadata(),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildBasicInfo() {
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
'基础信息',
|
||
style: TextStyle(
|
||
fontSize: 18,
|
||
fontWeight: FontWeight.bold,
|
||
color: WebTheme.getTextColor(context),
|
||
),
|
||
),
|
||
const SizedBox(height: 16),
|
||
TextFormField(
|
||
controller: _nameController,
|
||
decoration: const InputDecoration(
|
||
labelText: '模板名称 *',
|
||
hintText: '请输入模板名称',
|
||
border: OutlineInputBorder(),
|
||
),
|
||
validator: (value) {
|
||
if (value == null || value.trim().isEmpty) {
|
||
return '请输入模板名称';
|
||
}
|
||
return null;
|
||
},
|
||
),
|
||
const SizedBox(height: 16),
|
||
TextFormField(
|
||
controller: _descriptionController,
|
||
decoration: const InputDecoration(
|
||
labelText: '模板描述',
|
||
hintText: '请输入模板描述',
|
||
border: OutlineInputBorder(),
|
||
),
|
||
maxLines: 3,
|
||
onChanged: (value) {
|
||
setState(() {
|
||
_isEdited = true;
|
||
});
|
||
},
|
||
),
|
||
const SizedBox(height: 16),
|
||
DropdownButtonFormField<AIFeatureType>(
|
||
value: _featureType,
|
||
decoration: const InputDecoration(
|
||
labelText: '功能类型 *',
|
||
border: OutlineInputBorder(),
|
||
),
|
||
items: _featureTypes.map((type) {
|
||
return DropdownMenuItem(
|
||
value: type,
|
||
child: Text(_featureTypeLabels[type] ?? type.name),
|
||
);
|
||
}).toList(),
|
||
onChanged: (value) {
|
||
if (value != null) {
|
||
setState(() {
|
||
_featureType = value;
|
||
_isEdited = true;
|
||
});
|
||
}
|
||
},
|
||
),
|
||
const SizedBox(height: 16),
|
||
TextFormField(
|
||
controller: _tagsController,
|
||
decoration: const InputDecoration(
|
||
labelText: '标签',
|
||
hintText: '请输入标签,用逗号分隔',
|
||
border: OutlineInputBorder(),
|
||
),
|
||
onChanged: (value) {
|
||
setState(() {
|
||
_isEdited = true;
|
||
});
|
||
},
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
/// 插入占位符
|
||
void _insertPlaceholder(String placeholder) {
|
||
final currentText = _userPromptController.text;
|
||
final selection = _userPromptController.selection;
|
||
final newText = currentText.replaceRange(
|
||
selection.start,
|
||
selection.end,
|
||
'{$placeholder}',
|
||
);
|
||
_userPromptController.text = newText;
|
||
_userPromptController.selection = TextSelection.fromPosition(
|
||
TextPosition(offset: selection.start + placeholder.length + 2),
|
||
);
|
||
setState(() {
|
||
_isEdited = true;
|
||
});
|
||
}
|
||
|
||
/// 获取占位符描述
|
||
String _getPlaceholderDescription(String placeholder) {
|
||
switch (placeholder) {
|
||
case 'content':
|
||
return '要处理的主要内容';
|
||
case 'context':
|
||
return '上下文信息';
|
||
case 'requirement':
|
||
return '具体要求';
|
||
case 'style':
|
||
return '风格要求';
|
||
case 'length':
|
||
return '长度要求';
|
||
default:
|
||
return '占位符:$placeholder';
|
||
}
|
||
}
|
||
|
||
/// 构建元数据显示
|
||
Widget _buildMetadata() {
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
'元数据',
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.w600,
|
||
color: WebTheme.getTextColor(context),
|
||
),
|
||
),
|
||
const SizedBox(height: 12),
|
||
_buildMetadataRow('创建时间', _formatDateTime(widget.template.createdAt)),
|
||
_buildMetadataRow('更新时间', _formatDateTime(widget.template.updatedAt)),
|
||
_buildMetadataRow('使用次数', widget.template.useCount?.toString() ?? '0'),
|
||
_buildMetadataRow('评分', widget.template.averageRating?.toStringAsFixed(1) ?? '无'),
|
||
],
|
||
);
|
||
}
|
||
|
||
/// 构建元数据行
|
||
Widget _buildMetadataRow(String label, String value) {
|
||
return Padding(
|
||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||
child: Row(
|
||
children: [
|
||
SizedBox(
|
||
width: 80,
|
||
child: Text(
|
||
label,
|
||
style: TextStyle(
|
||
fontSize: 13,
|
||
color: WebTheme.getSecondaryTextColor(context),
|
||
),
|
||
),
|
||
),
|
||
Text(
|
||
value,
|
||
style: TextStyle(
|
||
fontSize: 13,
|
||
fontWeight: FontWeight.w500,
|
||
color: WebTheme.getTextColor(context),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
/// 格式化日期时间
|
||
String _formatDateTime(DateTime dateTime) {
|
||
return '${dateTime.year}-${dateTime.month.toString().padLeft(2, '0')}-${dateTime.day.toString().padLeft(2, '0')} '
|
||
'${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}';
|
||
}
|
||
|
||
Widget _buildSettings() {
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
'设置选项',
|
||
style: TextStyle(
|
||
fontSize: 18,
|
||
fontWeight: FontWeight.bold,
|
||
color: WebTheme.getTextColor(context),
|
||
),
|
||
),
|
||
const SizedBox(height: 16),
|
||
CheckboxListTile(
|
||
title: const Text('公开模板'),
|
||
subtitle: const Text('是否将此模板设为公开可见'),
|
||
value: _isPublic,
|
||
onChanged: (value) {
|
||
setState(() {
|
||
_isPublic = value ?? false;
|
||
_isEdited = true;
|
||
});
|
||
},
|
||
),
|
||
CheckboxListTile(
|
||
title: const Text('官方认证'),
|
||
subtitle: const Text('是否标记为官方认证模板'),
|
||
value: _isVerified,
|
||
onChanged: (value) {
|
||
setState(() {
|
||
_isVerified = value ?? false;
|
||
_isEdited = true;
|
||
});
|
||
},
|
||
),
|
||
CheckboxListTile(
|
||
title: const Text('默认模板'),
|
||
subtitle: const Text('是否设为该功能类型的默认模板'),
|
||
value: _isDefault,
|
||
onChanged: (value) {
|
||
setState(() {
|
||
_isDefault = value ?? false;
|
||
_isEdited = true;
|
||
});
|
||
},
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
Widget _buildActions() {
|
||
return Container(
|
||
padding: const EdgeInsets.all(24),
|
||
decoration: BoxDecoration(
|
||
border: Border(
|
||
top: BorderSide(color: WebTheme.getBorderColor(context)),
|
||
),
|
||
),
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.end,
|
||
children: [
|
||
TextButton(
|
||
onPressed: _isLoading ? null : () => Navigator.of(context).pop(),
|
||
child: const Text('取消'),
|
||
),
|
||
const SizedBox(width: 16),
|
||
if (_isEdited || _isLoading)
|
||
ElevatedButton(
|
||
onPressed: _isLoading ? null : _saveTemplate,
|
||
child: _isLoading
|
||
? const SizedBox(
|
||
width: 16,
|
||
height: 16,
|
||
child: CircularProgressIndicator(strokeWidth: 2),
|
||
)
|
||
: const Text('保存'),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Future<void> _saveTemplate() async {
|
||
if (!_formKey.currentState!.validate()) {
|
||
return;
|
||
}
|
||
|
||
setState(() {
|
||
_isLoading = true;
|
||
});
|
||
|
||
try {
|
||
final tags = _tagsController.text
|
||
.split(',')
|
||
.map((tag) => tag.trim())
|
||
.where((tag) => tag.isNotEmpty)
|
||
.toList();
|
||
|
||
final updatedTemplate = widget.template.copyWith(
|
||
name: _nameController.text.trim(),
|
||
description: _descriptionController.text.trim().isNotEmpty
|
||
? _descriptionController.text.trim()
|
||
: null,
|
||
content: _combinePrompts(),
|
||
featureType: _featureType,
|
||
templateTags: tags,
|
||
isPublic: _isPublic,
|
||
isVerified: _isVerified,
|
||
isDefault: _isDefault,
|
||
updatedAt: DateTime.now(),
|
||
);
|
||
|
||
await _adminRepository.updateTemplate(widget.template.id, updatedTemplate);
|
||
|
||
if (mounted) {
|
||
setState(() {
|
||
_isEdited = false;
|
||
});
|
||
Navigator.of(context).pop();
|
||
widget.onSuccess?.call();
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
const SnackBar(content: Text('模板更新成功')),
|
||
);
|
||
}
|
||
} catch (e) {
|
||
AppLogger.e('EditTemplateDialog', '更新模板失败', e);
|
||
if (mounted) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(content: Text('更新失败: $e')),
|
||
);
|
||
}
|
||
} finally {
|
||
if (mounted) {
|
||
setState(() {
|
||
_isLoading = false;
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 合并系统提示词和用户提示词
|
||
String _combinePrompts() {
|
||
final systemPrompt = _systemPromptController.text.trim();
|
||
final userPrompt = _userPromptController.text.trim();
|
||
|
||
if (systemPrompt.isEmpty) {
|
||
return userPrompt;
|
||
} else if (userPrompt.isEmpty) {
|
||
return systemPrompt;
|
||
} else {
|
||
return '$systemPrompt\n\n$userPrompt';
|
||
}
|
||
}
|
||
} |