生成封面客户端
package com.litongjava.manim.services;
import java.util.List;
import org.junit.Test;
import com.litongjava.db.activerecord.Db; import com.litongjava.jfinal.aop.Aop; import com.litongjava.manim.config.AdminAppConfig; import com.litongjava.tio.boot.testing.TioBootTest; import com.litongjava.tio.utils.environment.EnvUtils;
public class ManimImageServiceTest {
@Test public void test() { EnvUtils.load(); String url = Aop.get(ManimImageService.class).index("How Does ChatGPT Work?", "English", null); System.out.println(url); } }
package com.litongjava.manim.services;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.jfinal.kit.Kv;
import com.litongjava.gemini.GeminiChatRequestVo;
import com.litongjava.gemini.GeminiChatResponseVo;
import com.litongjava.gemini.GeminiClient;
import com.litongjava.gemini.GeminiGenerationConfigVo;
import com.litongjava.gemini.GoogleGeminiModels;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.linux.ProcessResult;
import com.litongjava.openai.chat.ChatMessage;
import com.litongjava.template.PromptEngine;
import com.litongjava.tio.core.ChannelContext;
import com.litongjava.tio.core.Tio;
import com.litongjava.tio.http.common.sse.SsePacket;
import com.litongjava.tio.utils.hutool.FileUtil;
import com.litongjava.tio.utils.hutool.ResourceUtil;
import com.litongjava.tio.utils.json.FastJson2Utils;
import com.litongjava.tio.utils.json.JsonUtils;
import com.litongjava.tio.utils.snowflake.SnowflakeIdUtils;
import com.litongjava.vo.ToolVo;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ManimImageService {
private static final boolean debug = false;
private LinuxService linuxService = Aop.get(LinuxService.class);
public String index(String topic, String language, ChannelContext channelContext) {
String systemPrompt = FileUtil.readURLAsString(ResourceUtil.getResource("prompts/generate_manim_image_code_system_prompt.txt")).toString();
Kv kv = Kv.by("topic", topic).set("language", language);
String prompt = PromptEngine.renderToString("manim_image_code_prompt.txt", kv);
ChatMessage chatMessage = new ChatMessage("user", prompt);
List<ChatMessage> messages = new ArrayList<>();
messages.add(chatMessage);
GeminiChatRequestVo geminiChatRequestVo = new GeminiChatRequestVo();
GeminiGenerationConfigVo geminiGenerationConfigVo = new GeminiGenerationConfigVo();
geminiGenerationConfigVo.setTemperature(0d);
geminiChatRequestVo.setGenerationConfig(geminiGenerationConfigVo);
geminiChatRequestVo.setSystemPrompt(systemPrompt);
geminiChatRequestVo.setChatMessages(messages);
if (debug) {
log.info(JsonUtils.toSkipNullJson(geminiChatRequestVo));
}
String code = genCdoe(geminiChatRequestVo);
messages.add(new ChatMessage("model", code));
if (code == null) {
return null;
}
ProcessResult processResult = linuxService.runManimImageCode(code, channelContext);
for (int i = 0; i < 10; i++) {
if (processResult != null && processResult.getOutput() != null) {
return processResult.getOutput();
} else {
code = this.fixCode(i, processResult.getStdErr(), messages, geminiChatRequestVo, channelContext);
messages.add(new ChatMessage("model", code));
processResult = linuxService.runManimImageCode(code, channelContext);
}
}
return null;
}
private String fixCode(int i, String stdErr, List<ChatMessage> messages, GeminiChatRequestVo geminiChatRequestVo, ChannelContext channelContext) {
String code = null;
// 初始错误日志和 SSE 提示
String message = "Python code: execution manim image failed:" + i;
log.error(message + ":{}", stdErr);
if (channelContext != null) {
byte[] jsonBytes = FastJson2Utils.toJSONBytes(Kv.by("progress", message));
Tio.bSend(channelContext, new SsePacket("progress", jsonBytes));
}
//log.info("fix request {}: {}", attempt, JsonUtils.toSkipNullJson(geminiChatRequestVo));
String info = "start fix manim image code " + i;
log.info(info);
if (channelContext != null) {
byte[] jsonBytes = FastJson2Utils.toJSONBytes(Kv.by("info", info));
Tio.bSend(channelContext, new SsePacket("progress", jsonBytes));
}
String codeFixPrompt = PromptEngine.renderToString("code_fix_prompt.txt", Kv.by("error", stdErr));
messages.add(new ChatMessage("user", codeFixPrompt));
geminiChatRequestVo.setChatMessages(messages);
if (debug) {
log.info("messages:{}", JsonUtils.toSkipNullJson(messages));
}
code = this.genCdoe(geminiChatRequestVo);
return code;
}
private String genCdoe(GeminiChatRequestVo geminiChatRequestVo) {
GeminiChatResponseVo chatResponse = null;
try {
//chatResponse = GeminiClient.generate(GoogleGeminiModels.GEMINI_2_5_PRO_EXP_03_25, geminiChatRequestVo);
chatResponse = GeminiClient.generate(GoogleGeminiModels.GEMINI_2_5_PRO_PREVIEW_03_25, geminiChatRequestVo);
} catch (Exception e) {
log.error("Faile to generate manim image code:{}", JsonUtils.toJson(geminiChatRequestVo), e);
return null;
}
String generatedText = chatResponse.getCandidates().get(0).getContent().getParts().get(0).getText();
String code = null;
int indexOf = generatedText.indexOf("```python");
if (indexOf == -1) {
if (generatedText.startsWith("{") && generatedText.endsWith("}")) {
code = generatedText;
ToolVo toolVo = null;
try {
toolVo = JsonUtils.parse(code.trim(), ToolVo.class);
} catch (Exception e) {
log.error("Failed to parse Json:{}", code);
return null;
}
return toolVo.getCode();
} else if ("done".contentEquals(generatedText)) {
return generatedText;
} else if (generatedText.startsWith("# -*- coding: utf-8 -*-")) {
return generatedText;
} else {
log.error("No code data found in the output:{}", generatedText);
return null;
}
} else {
int lastIndexOf = generatedText.lastIndexOf("```");
log.info("index:{},{}", indexOf, lastIndexOf);
if (lastIndexOf > 9) {
try {
code = generatedText.substring(indexOf + 9, lastIndexOf);
} catch (Exception e) {
log.error("generated text:{}", generatedText, e);
return null;
}
} else {
try {
code = generatedText.substring(indexOf + 9);
} catch (Exception e) {
log.error("generated text:{}", generatedText, e);
return null;
}
}
if (code != null) {
code = code.replaceAll("^(\\s*\\R)+", "").replaceAll("(\\R\\s*)+$", "");
code.trim();
new File("script").mkdirs();
try {
String path = "script/" + SnowflakeIdUtils.id() + ".py";
log.info("code file:{}", path);
FileUtil.writeString(code, path, "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
}
return code;
}
}
}
package com.litongjava.manim.services;
import com.jfinal.kit.Kv;
import com.litongjava.linux.LinuxClient;
import com.litongjava.linux.ProcessResult;
import com.litongjava.tio.core.ChannelContext;
import com.litongjava.tio.core.Tio;
import com.litongjava.tio.http.common.sse.SsePacket;
import com.litongjava.tio.utils.json.FastJson2Utils;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class LinuxService {
// private static final String apiBase = "http://192.168.50.61";
private static final String apiBase = "http://13.216.69.13";
private static final String api_key = "123456";
public final static boolean debug = false;
public ProcessResult startMainmSession() {
return LinuxClient.startMainmSession(apiBase, api_key);
}
public ProcessResult finish(long sessionIdPrt, String m3u8Path, String videos) {
return LinuxClient.finishMainmSession(apiBase, "123456", sessionIdPrt, m3u8Path, videos);
}
/**
* run code
* @param code
* @return
*/
public ProcessResult executeCode(String code) {
return LinuxClient.executeMainmCode(apiBase, "123456", code);
}
public ProcessResult executeCode(String code, long sessionPrt, String m3u8_path) {
return LinuxClient.executeMainmCode(apiBase, "123456", code, sessionPrt, m3u8_path);
}
public ProcessResult runManimCode(String code, long sessionIdPrt, String m3u8Path, ChannelContext channelContext) {
ProcessResult executeMainmCode = null;
try {
executeMainmCode = executeCode(code, sessionIdPrt, m3u8Path);
} catch (Exception e) {
String message = e.getMessage();
byte[] jsonBytes = FastJson2Utils.toJSONBytes(Kv.by("info ", message));
Tio.bSend(channelContext, new SsePacket("progress", jsonBytes));
try {
executeMainmCode = executeCode(code, sessionIdPrt, m3u8Path);
} catch (Exception e2) {
message = e2.getMessage();
jsonBytes = FastJson2Utils.toJSONBytes(Kv.by("info ", message));
Tio.bSend(channelContext, new SsePacket("progress", jsonBytes));
try {
executeMainmCode = executeCode(code, sessionIdPrt, m3u8Path);
} catch (Exception e3) {
message = e2.getMessage();
jsonBytes = FastJson2Utils.toJSONBytes(Kv.by("info ", message));
Tio.bSend(channelContext, new SsePacket("error", jsonBytes));
log.error(e.getMessage(), e);
return null;
}
}
}
return executeMainmCode;
}
public ProcessResult runManimImageCode(String code, ChannelContext channelContext) {
ProcessResult processResult = null;
for (int i = 0; i < 3; i++) {
try {
processResult = LinuxClient.manimImage(apiBase, api_key, code);
break;
} catch (Exception e) {
String message = "count:" + i + " " + e.getMessage();
if (channelContext != null) {
byte[] jsonBytes = FastJson2Utils.toJSONBytes(Kv.by("info ", message));
Tio.bSend(channelContext, new SsePacket("progress", jsonBytes));
}
log.error(message);
}
}
return processResult;
}
}
output /media/images/501229158053711872/Main_ManimCE_v0.19.0.png
1.润色为一篇完整的文档 2.增加必要的解释和说明方便读者理解 3.润色过程中不要省略任何代码