a
Some checks failed
Flask 提示词大师 - CI/CD 流水线 / 代码质量检查 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 单元测试 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 集成测试 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 构建Docker镜像 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 部署到测试环境 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 部署到生产环境 (push) Has been cancelled
Flask 提示词大师 - CI/CD 流水线 / 部署监控系统 (push) Has been cancelled

This commit is contained in:
rjb
2026-03-01 23:24:53 +08:00
parent 34e3ee213e
commit 90f3103de3
28 changed files with 985 additions and 74 deletions

29
exampleAiApp01/README.md Normal file
View File

@@ -0,0 +1,29 @@
# 提示词智能优化 Android App
调用提示词大师 3 号专家接口,实现智能提示词生成。
## 环境
- Android Studio推荐使用 AGP 8.7+、Gradle 8.9
- minSdk 24targetSdk 34
- Java 17
## 接口
- 地址:`POST http://101.43.95.130:5002/api/open/expert-generate-3`
- 参数:`input_text`(必填)、`temperature``max_tokens``timeout``uid`
## 构建
```bash
cd exampleAiApp01
./gradlew assembleDebug
```
或在 Android Studio 中打开 `exampleAiApp01` 目录,直接运行到真机或模拟器。
## 注意事项
- 需配置网络权限,并允许明文 HTTP101.43.95.130 为 HTTP
- 确保设备可访问 `101.43.95.130:5002`
- 如缺少启动图标,可在 Android Studio 中通过 `File > New > Image Asset` 生成

View File

@@ -0,0 +1,46 @@
plugins {
id("com.android.application")
}
android {
namespace = "com.example.promptoptimizer"
compileSdk = 34
defaultConfig {
applicationId = "com.example.promptoptimizer"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
// Retrofit
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
}

3
exampleAiApp01/app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,3 @@
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.example.promptoptimizer.api.** { *; }

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PromptOptimizer"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.PromptOptimizer">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,146 @@
package com.example.promptoptimizer;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.promptoptimizer.api.ExpertGenerate3Api;
import com.example.promptoptimizer.model.ExpertGenerate3Request;
import com.example.promptoptimizer.model.ExpertGenerate3Response;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.card.MaterialCardView;
import java.util.Arrays;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* 提示词智能优化 - 主界面
*/
public class MainActivity extends AppCompatActivity {
private EditText etInput;
private MaterialButton btnGenerate;
private ProgressBar progressBar;
private TextView tvLoading;
private MaterialCardView cardResult;
private TextView tvIntent;
private TextView tvPrompt;
private MaterialButton btnCopy;
private boolean isSubmitting = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etInput = findViewById(R.id.etInput);
btnGenerate = findViewById(R.id.btnGenerate);
progressBar = findViewById(R.id.progressBar);
tvLoading = findViewById(R.id.tvLoading);
cardResult = findViewById(R.id.cardResult);
tvIntent = findViewById(R.id.tvIntent);
tvPrompt = findViewById(R.id.tvPrompt);
btnCopy = findViewById(R.id.btnCopy);
btnGenerate.setOnClickListener(v -> doGenerate());
btnCopy.setOnClickListener(v -> copyPrompt());
}
private void doGenerate() {
if (isSubmitting) return;
String input = etInput.getText() != null ? etInput.getText().toString().trim() : "";
if (input.isEmpty()) {
Toast.makeText(this, R.string.error_empty, Toast.LENGTH_SHORT).show();
return;
}
isSubmitting = true;
progressBar.setVisibility(View.VISIBLE);
tvLoading.setVisibility(View.VISIBLE);
btnGenerate.setEnabled(false);
cardResult.setVisibility(View.GONE);
ExpertGenerate3Request request = new ExpertGenerate3Request(input);
ExpertGenerate3Api api = RetrofitClient.getApi();
api.generate(request).enqueue(new Callback<ExpertGenerate3Response>() {
@Override
public void onResponse(Call<ExpertGenerate3Response> call,
Response<ExpertGenerate3Response> response) {
isSubmitting = false;
progressBar.setVisibility(View.GONE);
tvLoading.setVisibility(View.GONE);
btnGenerate.setEnabled(true);
if (response.isSuccessful() && response.body() != null) {
ExpertGenerate3Response body = response.body();
if (body.getCode() == 200 && body.getData() != null) {
showResult(body);
} else {
Toast.makeText(MainActivity.this,
body.getMessage() != null ? body.getMessage() : getString(R.string.error_network),
Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(MainActivity.this, R.string.error_network, Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call<ExpertGenerate3Response> call, Throwable t) {
isSubmitting = false;
progressBar.setVisibility(View.GONE);
tvLoading.setVisibility(View.GONE);
btnGenerate.setEnabled(true);
Toast.makeText(MainActivity.this, R.string.error_network + ": " + t.getMessage(),
Toast.LENGTH_LONG).show();
}
});
}
private void showResult(ExpertGenerate3Response response) {
ExpertGenerate3Response.ResponseData data = response.getData();
if (data == null) return;
StringBuilder intentSb = new StringBuilder();
ExpertGenerate3Response.IntentAnalysis ia = data.getIntentAnalysis();
if (ia != null) {
intentSb.append("核心意图:").append(ia.getCoreIntent()).append("\n");
intentSb.append("专业领域:").append(ia.getDomain()).append("\n");
intentSb.append("预期输出:").append(ia.getExpectedOutput()).append("\n");
if (ia.getKeyRequirements() != null && ia.getKeyRequirements().length > 0) {
intentSb.append("关键需求:\n").append(Arrays.toString(ia.getKeyRequirements())).append("\n");
}
if (ia.getConstraints() != null && ia.getConstraints().length > 0) {
intentSb.append("约束条件:\n").append(Arrays.toString(ia.getConstraints()));
}
}
tvIntent.setText(intentSb.toString());
tvPrompt.setText(data.getGeneratedPrompt() != null ? data.getGeneratedPrompt() : "");
cardResult.setVisibility(View.VISIBLE);
}
private void copyPrompt() {
String text = tvPrompt.getText() != null ? tvPrompt.getText().toString() : "";
if (text.isEmpty()) return;
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
if (cm != null) {
cm.setPrimaryClip(ClipData.newPlainText("prompt", text));
Toast.makeText(this, R.string.toast_copied, Toast.LENGTH_SHORT).show();
}
}
}

View File

@@ -0,0 +1,46 @@
package com.example.promptoptimizer;
import com.example.promptoptimizer.api.ExpertGenerate3Api;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import java.util.concurrent.TimeUnit;
public class RetrofitClient {
private static final String BASE_URL = "http://101.43.95.130:5002/";
private static Retrofit retrofit;
private static ExpertGenerate3Api api;
public static ExpertGenerate3Api getApi() {
if (api == null) {
api = getRetrofit().create(ExpertGenerate3Api.class);
}
return api;
}
private static Retrofit getRetrofit() {
if (retrofit == null) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(90, TimeUnit.SECONDS)
.readTimeout(90, TimeUnit.SECONDS)
.writeTimeout(90, TimeUnit.SECONDS)
.addInterceptor(interceptor)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}

View File

@@ -0,0 +1,17 @@
package com.example.promptoptimizer.api;
import com.example.promptoptimizer.model.ExpertGenerate3Response;
import com.example.promptoptimizer.model.ExpertGenerate3Request;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;
/**
* 智能提示词优化3号专家 API
*/
public interface ExpertGenerate3Api {
@POST("api/open/expert-generate-3")
Call<ExpertGenerate3Response> generate(@Body ExpertGenerate3Request request);
}

View File

@@ -0,0 +1,71 @@
package com.example.promptoptimizer.model;
import com.google.gson.annotations.SerializedName;
/**
* 请求体
*/
public class ExpertGenerate3Request {
@SerializedName("input_text")
private String inputText;
@SerializedName("temperature")
private Float temperature;
@SerializedName("max_tokens")
private Integer maxTokens;
@SerializedName("timeout")
private Integer timeout;
@SerializedName("uid")
private Integer uid;
public ExpertGenerate3Request(String inputText) {
this.inputText = inputText;
this.temperature = 0.7f;
this.maxTokens = 1000;
this.timeout = 60;
}
public String getInputText() {
return inputText;
}
public void setInputText(String inputText) {
this.inputText = inputText;
}
public Float getTemperature() {
return temperature;
}
public void setTemperature(Float temperature) {
this.temperature = temperature;
}
public Integer getMaxTokens() {
return maxTokens;
}
public void setMaxTokens(Integer maxTokens) {
this.maxTokens = maxTokens;
}
public Integer getTimeout() {
return timeout;
}
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
}

View File

@@ -0,0 +1,120 @@
package com.example.promptoptimizer.model;
import com.google.gson.annotations.SerializedName;
/**
* 响应体
*/
public class ExpertGenerate3Response {
private int code;
private String message;
@SerializedName("data")
private ResponseData data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public ResponseData getData() {
return data;
}
public void setData(ResponseData data) {
this.data = data;
}
public static class ResponseData {
@SerializedName("intent_analysis")
private IntentAnalysis intentAnalysis;
@SerializedName("generated_prompt")
private String generatedPrompt;
public IntentAnalysis getIntentAnalysis() {
return intentAnalysis;
}
public void setIntentAnalysis(IntentAnalysis intentAnalysis) {
this.intentAnalysis = intentAnalysis;
}
public String getGeneratedPrompt() {
return generatedPrompt;
}
public void setGeneratedPrompt(String generatedPrompt) {
this.generatedPrompt = generatedPrompt;
}
}
public static class IntentAnalysis {
@SerializedName("core_intent")
private String coreIntent;
@SerializedName("domain")
private String domain;
@SerializedName("key_requirements")
private String[] keyRequirements;
@SerializedName("expected_output")
private String expectedOutput;
@SerializedName("constraints")
private String[] constraints;
public String getCoreIntent() {
return coreIntent;
}
public void setCoreIntent(String coreIntent) {
this.coreIntent = coreIntent;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String[] getKeyRequirements() {
return keyRequirements;
}
public void setKeyRequirements(String[] keyRequirements) {
this.keyRequirements = keyRequirements;
}
public String getExpectedOutput() {
return expectedOutput;
}
public void setExpectedOutput(String expectedOutput) {
this.expectedOutput = expectedOutput;
}
public String[] getConstraints() {
return constraints;
}
public void setConstraints(String[] constraints) {
this.constraints = constraints;
}
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<corners android:radius="4dp"/>
<stroke android:width="1dp" android:color="#E2E8F0"/>
</shape>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#1E3A8A"
android:pathData="M54,40 L68,54 L54,68 L40,54 Z" />
</vector>

View File

@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="#F8FAFC">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="提示词智能优化"
android:textSize="22sp"
android:textStyle="bold"
android:textColor="#1E3A8A"
android:layout_marginBottom="16dp" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardCornerRadius="8dp"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请描述您的需求"
android:textSize="14sp"
android:textColor="#333333"
android:layout_marginBottom="8dp" />
<EditText
android:id="@+id/etInput"
android:layout_width="match_parent"
android:layout_height="120dp"
android:gravity="top|start"
android:padding="12dp"
android:background="@drawable/edit_bg"
android:inputType="textMultiLine"
android:minLines="3"
android:hint="@string/hint_input" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnGenerate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/btn_generate" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
android:layout_marginVertical="24dp" />
<TextView
android:id="@+id/tvLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/loading"
android:visibility="gone"
android:layout_marginBottom="24dp" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardResult"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:cardCornerRadius="8dp"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_result"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="12dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_intent"
android:textSize="14sp"
android:textStyle="bold"
android:layout_marginBottom="4dp" />
<TextView
android:id="@+id/tvIntent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:background="#F1F5F9"
android:textSize="13sp"
android:lineSpacingExtra="4dp"
android:layout_marginBottom="12dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_prompt"
android:textSize="14sp"
android:textStyle="bold"
android:layout_marginBottom="4dp" />
<TextView
android:id="@+id/tvPrompt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:background="#F1F5F9"
android:textSize="13sp"
android:lineSpacingExtra="4dp"
android:fontFamily="monospace" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnCopy"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/btn_copy" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#F8FAFC</color>
<color name="primary">#1E3A8A</color>
</resources>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">提示词智能优化</string>
<string name="hint_input">请描述您的需求,系统将进行专业分析并生成高质量提示词</string>
<string name="btn_generate">生成专家提示词</string>
<string name="label_result">生成结果</string>
<string name="label_intent">需求分析</string>
<string name="label_prompt">生成的专家提示词</string>
<string name="btn_copy">复制提示词</string>
<string name="toast_copied">已复制到剪贴板</string>
<string name="loading">正在分析需求并生成专业提示词…</string>
<string name="error_network">网络请求失败,请检查网络后重试</string>
<string name="error_empty">请输入您的需求</string>
</resources>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.PromptOptimizer" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">#1E3A8A</item>
<item name="colorPrimaryVariant">#3B82F6</item>
<item name="colorOnPrimary">#FFFFFF</item>
</style>
</resources>

View File

@@ -0,0 +1,3 @@
plugins {
id("com.android.application") version "8.7.3" apply false
}

View File

@@ -0,0 +1,4 @@
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
kotlin.code.style=official
android.nonTransitiveRClass=true

View File

@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -0,0 +1,17 @@
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "PromptOptimizer"
include(":app")