ð Prompt OptimizerïŒè·šå¹³å° AI æç€ºè¯äŒåå·¥å ·åŒæºå享
äžäžªåºäº Flutter + Riverpod çåŒæºé¡¹ç®ïŒçš MVI æ¶æäŒé å°è§£å³æç€ºè¯äŒåå®äŸ
å®çœå ¥å£
ð¯åšçº¿äœéªïŒprompt.jiulang9.com
ðAndroid/PC端äžèœœå°å app.jiulang9.com
ðGithubåŒæºå°åïŒJIULANG9/PromptOptimizer:
ææ¡ä»¶ç䜿çšèªå·±ç Api key åïŒ
åŠæè¿äžªé¡¹ç®å¯¹äœ æåž®å©ïŒè¯·äžèŠå¿è®°ç»äžª â Star æ¯æäžäžïŒè¿å¯¹ææ¥è¯Žæä¹é倧ïŒä¹æ¯ææç»æŽæ°çåšå
ð 䞺ä»ä¹èŠåè¿äžªé¡¹ç®ïŒ
- ð€ æç€ºè¯ææäžçæ³ â åæ ·çéæ±ïŒäžåç衚述æ¹åŒïŒAI çåç莚éå·®åŒå·šå€§
- ð æåšäŒåäœæ â åå€è°æŽæç€ºè¯ïŒæµªè޹倧鿶éŽ
- ð æ°æ®å®å šé¡Ÿè â API å¯é¥åŠäœå®å šååšïŒåå²è®°åœåŠäœä¿æ€ïŒ
PromptOptimizer å°±æ¯äžºäºè§£å³è¿äºçç¹èççïŒ
| æ žå¿åèœ | å ·äœäœç° |
|---|---|
| ð¯ ææå·¥å · | äžé®äŒåæç€ºè¯ïŒæ¯æå€ç§äŒåæš¡æ¿ïŒå®æ¶é¢è§ç»æ |
| ð è·šå¹³å°äœéª | Android / iOS / Web / Windows / macOS / Linux æ çŒåæ¢ |
| ð æ°æ®å®å š | AES-256 å å¯ååš API å¯é¥ïŒæ¬å°æ°æ®åºç®¡ç |
| ð§ åŒåå奜 | åŒæºä»£ç ïŒæž æ°æ¶æïŒæäºäºæ¬¡åŒååå®å¶ |
| ð° å®å šå 莹 | æ ä»è޹åèœïŒæ 广åïŒæ æ°æ®äžäŒ |
ð± 项ç®é¢è§
âïž æµ è²æš¡åŒ
ð æ·±è²æš¡åŒ
ð åèœåŠäœå®ç°ïŒ
äžãåèœè®Ÿè®¡ â ä»çšæ·éæ±åºå
äžºäž€ç§æš¡åŒ
- çšæ·æç€ºè¯äŒå â äŒåäœ åç» AI çæä»€ïŒè®© AI æŽçè§£äœ çéæ±
- ç³»ç»æç€ºè¯äŒå â äŒå AI çç³»ç»è§è²è®Ÿå®ïŒè®© AI æŽå¥œå°æ®æŒç¹å®èº«ä»œ
ð å€ API æ¯æ
æ¯æ å€äžªäž»æµ AI æäŸåïŒ
| æäŸå | API å°å | é»è®€æš¡å | éçšåºæ¯ |
|---|---|---|---|
| ðµ OpenAI | api.openai.com | gpt-4o | éçšãé«èŽšé |
| ð DashScopeïŒé¿éïŒ | dashscope.aliyuncs.com | qwen-max | åœå çšæ·éŠé |
| ð£ DeepSeek | api.deepseek.com | deepseek-chat | æ§ä»·æ¯é« |
| ð MoonshotïŒæä¹æé¢ïŒ | api.moonshot.cn | moonshot-v1-8k | é¿ææ¬å€ç |
| ð§ Zhipu AIïŒæºè°±ïŒ | open.bigmodel.cn | glm-4 | äžæäŒå |
| ð BaiduïŒæå¿äžèšïŒ | aip.baidubce.com | ernie-4.0-8k | åœå æå¡ |
| ð¯ TencentïŒæ··å ïŒ | hunyuan.tencentcloudapi.com | hunyuan-lite | è Ÿè®¯çæ |
| ð OpenRouterïŒèåïŒ | openrouter.ai | llama-3.1-8b | æš¡åäž°å¯ |
å ³é®ç¹æ§ïŒ
- â æ¯æ OpenAI å Œå®¹æ¥å£ïŒèªå®ä¹ API 端ç¹ïŒ
- â AES-256 å å¯ååš API å¯é¥
- â äžé®åæ¢ API é çœ®ïŒæ ééå¯åºçš
ð æš¡æ¿ç®¡çç³»ç»
å
眮 4 䞪äžäžæš¡æ¿ïŒ
âââ ð æ åäŒåæš¡æ¿
âââ ð åŠæ¯è®ºææš¡æ¿
âââ ðŒ åå¡ææ¡æš¡æ¿
âââ ð¬ ææ¯ææ¡£æš¡æ¿
+ èªå®ä¹æš¡æ¿æ¯æ
âââ äœ¿çš {{originalPrompt}} å äœç¬Š
æš¡æ¿ç€ºäŸïŒ
ãæ åäŒåæš¡æ¿ã
请äŒåä»¥äžæç€ºè¯ïŒäœ¿å
¶æŽæž
æ°ãæŽå
·äœãæŽå®¹æè¢« AI çè§£ïŒ
{{originalPrompt}}
äŒåèŠæ±ïŒ
1. æç¡®ç®æ å颿èŸåº
2. æäŸå¿
èŠçèæ¯ä¿¡æ¯
3. æå®èŸåºæ ŒåŒ
4. æ·»å çºŠææ¡ä»¶
ðŸ æ°æ®å¯Œå ¥å¯Œåº
äžé®å€ä»œïŒ
âââ API é
眮
âââ èªå®ä¹æš¡æ¿
âââ äŒååå²
âââ UI å奜讟眮
æ¯ææ ŒåŒïŒ
âââ PC ç«¯ïŒæä»¶å€¹éæ©
âââ ç§»åšç«¯ïŒç³»ç»å享
äºãææ¯æ¶æ â åŠäœäŒé å°å®ç°è¿äºåèœ
ðïž MVI æ¶æ + ååæ°æ®æµ
ââââââââââââââââ
â UI Layer â â çšæ·äº€äºïŒç¹å»ãèŸå
¥ïŒ
â (Widget) â
ââââââââ¬ââââââââ
â åé Intent
â
ââââââââââââââââââââââââ
â Intent Handler â â äžå¡é»èŸå€ç
â (Notifier) â
ââââââââ¬ââââââââââââââââ
â æŽæ° State
â
ââââââââââââââââââââââââ
â Model (State) â â æ°æ®æš¡å
â (Freezed) â
ââââââââ¬ââââââââââââââââ
â éç¥ UI æŽæ°
â
ââââââââââââââââ
â UI Layer â â éæ°æž²æ
â (Widget) â
ââââââââââââââââ
䞺ä»ä¹éæ© MVIïŒ
| ç¹ç¹ | äŒå¿ |
|---|---|
| ååæ°æ®æµ | æ°æ®æµåæž æ°ïŒæäºè°è¯ |
| Intent æç¡® | æ¯äžªçšæ·æäœéœæå¯¹åºç Intent |
| State äžå¯å | äœ¿çš FreezedïŒé¿å æå€ä¿®æ¹ |
| æäºæµè¯ | Intent â State çæ å°æäºåå æµè¯ |
ð Riverpod ç¶æç®¡ç
// å®ä¹äžäžªäŒå Intent
class OptimizeIntent {
final String originalPrompt;
final String templateId;
final String apiConfigId;
}
// Notifier å€ç Intent
class OptimizationNotifier extends StateNotifier<OptimizationState> {
OptimizationNotifier() : super(OptimizationState.initial());
// å€çäŒå Intent
Future<void> optimize(OptimizeIntent intent) async {
state = state.copyWith(isLoading: true);
try {
final result = await _apiService.optimize(intent);
state = state.copyWith(
result: result,
isLoading: false,
);
} catch (e) {
state = state.copyWith(error: e.toString(), isLoading: false);
}
}
}
// UI å±çå¬ç¶æ
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.watch(optimizationProvider);
return state.when(
loading: () => LoadingWidget(),
data: (result) => ResultWidget(result),
error: (error) => ErrorWidget(error),
);
}
Riverpod çäŒå¿ïŒ
- â çŒè¯æ¶å®å š â äŸèµæ³šå ¥åšçŒè¯ææ£æ¥
- â
èªåšä»£ç çæ â 䜿çš
@riverpod泚解 - â çµæŽ»çäŸèµç®¡ç â æ¯æ overrideãwatchãselect
- â æ§èœäŒå â 粟ç»åçé建æ§å¶
ðïž æ°æ®åºè®Ÿè®¡ â Drift + Hive
âââââââââââââââââââââââââââââââââââââââ
â æ°æ®ååšå± â
âââââââââââââââââââââââââââââââââââââââ€
â Drift (SQLite) â
â âââ api_configs 衚 â
â âââ prompt_templates 衚 â
â âââ optimization_histories 衚 â
â â
â Hive (KV ååš) â
â âââ app_settings Box â
â â âââ themeMode â
â â âââ locale â
â âââ å
¶ä»å奜讟眮 â
âââââââââââââââââââââââââââââââââââââââ
䞺ä»ä¹è¿æ ·è®Ÿè®¡ïŒ
| ååšæ¹æ¡ | çšé | åå |
|---|---|---|
| Drift | API é çœ®ãæš¡æ¿ãåå² | ç»æåæ°æ®ïŒéèŠå€ææ¥è¯¢ |
| Hive | UI å奜讟眮 | ç®å KV æ°æ®ïŒå¿«é读å |
ð AES-256 å å¯
API å¯é¥ååšæµçšïŒ
ââââââââââââââââââââ
â çšæ·èŸå
¥å¯é¥ â
ââââââââââ¬ââââââââââ
â
â
ââââââââââââââââââââ
â AES-256 å å¯ â
â (256-bit key) â
ââââââââââ¬ââââââââââ
â
â
ââââââââââââââââââââ
â Base64 çŒç â
ââââââââââ¬ââââââââââ
â
â
ââââââââââââââââââââ
â ååšå°æ°æ®åº â
ââââââââââââââââââââ
äœ¿çšæ¶ååè§£å¯ïŒ
æ°æ®åº â Base64 è§£ç â AES-256 è§£å¯ â è·åŸåå§å¯é¥
AesCryptoServiceïŒ
class AesCryptoService {
static const String _encryptionKey = 'your-256-bit-key-here';
// å å¯
static String encrypt(String plaintext) {
final key = Key.fromUtf8(_encryptionKey);
final iv = IV.fromSecureRandom(16);
final cipher = Encrypter(AES(key, mode: AESMode.cbc));
final encrypted = cipher.encrypt(plaintext, iv: iv);
return '${iv.base64}:${encrypted.base64}';
}
// è§£å¯
static String decrypt(String encrypted) {
final parts = encrypted.split(':');
final iv = IV.fromBase64(parts[0]);
final cipher = Encrypter(AES(Key.fromUtf8(_encryptionKey), mode: AESMode.cbc));
return cipher.decrypt64(parts[1], iv: iv);
}
}
ð GitHub Actions å·¥äœæµ CI/CD æµçš
âââââââââââââââââââââââââââââââââââââââ
â Git æšé â
âââââââââââââââââââââââââââââââââââââââ€
â 忝æšé (main) â
â âââ 代ç åæ + Debug æå»º â
â â
â Tag æšé (v1.0.0) â
â âââ å®æŽæå»º + èªåšååž â
â âââ Android (APK + AAB) â
â âââ Windows (ZIP) â
â âââ macOS (ZIP) â
â âââ Linux (TAR.GZ) â
â âââ Web (TAR.GZ) â
âââââââââââââââââââââââââââââââââââââââ
ð¡æ žå¿ææ¯äº®ç¹
1ïžâ£ ååæ°æ®æµçäŒé å®ç°
é®é¢ïŒ äŒ ç» setState 容æå¯ŒèŽç¶ææ··ä¹±ïŒéŸä»¥è¿œèžªæ°æ®åå
è§£å³æ¹æ¡ïŒ MVI æ¶æ + Riverpod
Intent (çšæ·æäœ)
â Notifier (äžå¡é»èŸ)
â State (æ°æ®æš¡å)
â UI (éæ°æž²æ)
äŒå¿ïŒ
- æ°æ®æµåäžç®äºç¶
- æäºè°è¯åæµè¯
- æ¯ææ¶éŽæ è¡è°è¯ïŒDevToolsïŒ
2ïžâ£ æµåŒååºç髿å€ç
é®é¢ïŒ 倧å AI ååºå¯èœåŸé¿ïŒäžæ¬¡æ§å 蜜äŒå¡é¡¿
è§£å³æ¹æ¡ïŒ SSE æµåŒå€ç + å¢éæŽæ°
// æ¥æ¶ SSE æµ
final stream = _apiService.optimizeStream(prompt);
// é token å€ç
await for (final token in stream) {
state = state.copyWith(
result: state.result + token, // å¢éæŒæ¥
);
}
3ïžâ£ è·šå¹³å°æ°æ®åæ¥
å®ç°åšå€äžªè®Ÿå€éŽåæ¢ïŒé 眮åå岿°æ®äžåæ¥
// å¯Œåºæ°æ®
Future<void> exportData() async {
final data = {
'apiConfigs': await _apiConfigDao.getAllConfigs(),
'templates': await _templateDao.getAllTemplates(),
'histories': await _historyDao.getAllHistories(),
'settings': await _settingsService.getSettings(),
};
final json = jsonEncode(data);
// ä¿åå°æä»¶æå享
}
// 富å
¥æ°æ®
Future<void> importData(String jsonData) async {
final data = jsonDecode(jsonData);
await _apiConfigDao.insertConfigs(data['apiConfigs']);
await _templateDao.insertTemplates(data['templates']);
await _historyDao.insertHistories(data['histories']);
await _settingsService.updateSettings(data['settings']);
}
èŽæ¬
linshenkx 倧䜬åŒåçæç€ºè¯äŒååš
åŒæºå°å
linshenkx/prompt-optimizer: äžæ¬Ÿæç€ºè¯äŒååšïŒå©åäºçŒåé«èŽšéçæç€ºè¯