diff --git a/jcommon/ai/pom.xml b/jcommon/ai/pom.xml new file mode 100644 index 000000000..1fe47397e --- /dev/null +++ b/jcommon/ai/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + run.mone + jcommon + 1.4-jdk20-SNAPSHOT + + + ai + pom + + zhipu + + + + 21 + 21 + UTF-8 + + + \ No newline at end of file diff --git a/jcommon/ai/src/main/resources/prompt.txt b/jcommon/ai/src/main/resources/prompt.txt new file mode 100644 index 000000000..51956345a --- /dev/null +++ b/jcommon/ai/src/main/resources/prompt.txt @@ -0,0 +1,80 @@ +你是一名高级groovy工程师. +你要完成的好,我会给你100$小费. +我会给你提供一些代码只是和业务需求,请帮我生成相应的$code(groovy代码)代码和$params和$out. +你只需要返回一个方法和参数列表,方法的名字统一叫execute,参数: 第一个是 + JsonObject input, 第二个是Object context +JsonObject必须用Gson中的库 +不要生成任何测试代码 +不要生成任何说明,只需要返回一个json结构的内容即可 +你要生成一些必要的import +你给我返回的是一个JsonObject(Gson中的类) +你的返回结果里决不能用任何markdown格式包裹(比如:```json ``` ```groovy ```) +不要输出换行符 比如 \n \r等 +$code就是你要生成的代码内容 +$params就是参数名列表 +$outs就是返回结果的列表 + +最终你产生的结果 +{"code":$code,"params":$params,"outs":$outs} + +$params的格式举例:[{"name":"a","tpye":"int"}] +$outs的格式举例:[{"name":"sum","type":"int"}] + +一些工具库使用,你可以借鉴: + + +DbUtils里边有些工具方法可以操作数据库 + + /** + * 将提供的键值对数据插入到指定的数据库表中。 + */ + public Long insert(String tableName, Map data) + + /** + * 更新指定表的指定ID的记录,通过传入的键值对映射来设置新的列值 + */ + public void update(String tableName, String primaryKeyName, Map data) + + // 根据id列表批量删除 + public void deleteByIds(String tableName, String idName, List ids) + + +你尽量使用我给你提供的工具类,DbUtils 直接可以从context中获取 context.getDbUtils + + +我给你一个例子: + +需求: +计算两数和 + + +返回: +{ + "code": "def execute(JsonObject input, Object context) {\n if (!input.has('a') || !input.has('b')) {\n throw new IllegalArgumentException(\"JSON对象必须包含键'a'和'b'。\");\n }\n int a = input.get('a').getAsInt();\n int b = input.get('b').getAsInt();\n int sum = a + b;\n JsonObject result = new JsonObject();\n result.addProperty(\"sum\", sum);\n return result;\n}", + "params": [ + { + "name": "a", + "type": "int" + }, + { + "name": "b", + "type": "int" + } + ], + "outs": [ + { + "name": "sum", + "type": "int" + } + ] +} + +例子结束 + + + +需求: +给定一个List,返回这个list中的最大值和最小值 + +返回: + diff --git a/jcommon/ai/src/main/resources/prompt2.txt b/jcommon/ai/src/main/resources/prompt2.txt new file mode 100644 index 000000000..995f150f7 --- /dev/null +++ b/jcommon/ai/src/main/resources/prompt2.txt @@ -0,0 +1,46 @@ +你是一名高级groovy工程师. +你要完成的好,我会给你100$小费. +我会给你提供一个groovy方法,你帮我生成这个方法的描述(必须少于15个字). +你的返回结果永远是一个json格式的数据. +你的返回结果里决不能用任何markdown格式包裹(比如:```groovy ```) +不要生成任何说明,只需要返回一个json结构的内容即可 + +$comment就是你生成的注释 + +{"comment":"$comment"} + + + + +我给你一个例子: + +code: +def execute(JsonObject input, Object context) { + if (!input.has('a') || !input.has('b')) { + throw new IllegalArgumentException("JSON对象必须包含键'a'和'b'。"); + } + int a = input.get('a').getAsInt(); + int b = input.get('b').getAsInt(); + int sum = a + b; + JsonObject result = new JsonObject(); + result.addProperty("result", sum); + return result; +} + + +你返回的: +{"comment":"计算两数和"} + + + +例子结束 + + + + + + +code: +int a(int a, int b) { return a * b; } + +你的返回: diff --git a/jcommon/ai/src/main/resources/prompt3.txt b/jcommon/ai/src/main/resources/prompt3.txt new file mode 100644 index 000000000..3713b852e --- /dev/null +++ b/jcommon/ai/src/main/resources/prompt3.txt @@ -0,0 +1 @@ +李清照最好的6首词,并且给我解读 \ No newline at end of file diff --git a/jcommon/ai/zhipu/pom.xml b/jcommon/ai/zhipu/pom.xml new file mode 100644 index 000000000..5bebe7c32 --- /dev/null +++ b/jcommon/ai/zhipu/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + run.mone + ai + 1.4-jdk20-SNAPSHOT + + + zhipu + + + 21 + 21 + UTF-8 + + + + + + cn.bigmodel.openapi + oapi-java-sdk + release-V4-2.0.0 + + + + com.google.code.gson + gson + 2.8.5 + + + + + + + \ No newline at end of file diff --git a/jcommon/ai/zhipu/src/main/java/run/mone/Main.java b/jcommon/ai/zhipu/src/main/java/run/mone/Main.java new file mode 100644 index 000000000..c0800b973 --- /dev/null +++ b/jcommon/ai/zhipu/src/main/java/run/mone/Main.java @@ -0,0 +1,57 @@ +package run.mone; + +import com.zhipu.oapi.ClientV4; +import com.zhipu.oapi.Constants; +import com.zhipu.oapi.service.v4.model.ChatCompletionRequest; +import com.zhipu.oapi.service.v4.model.ChatMessage; +import com.zhipu.oapi.service.v4.model.ChatMessageRole; +import com.zhipu.oapi.service.v4.model.ModelApiResponse; +import lombok.SneakyThrows; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +/** + * @author goodjava@qq.com + * @date 2024/3/10 07:55 + */ +public class Main { + + private static final String requestIdTemplate = "myoz-%d"; + + + private static final String KEY = System.getenv("zhipu"); + + private static final String API_KEY = KEY.split("\\.")[0]; + + private static final String API_SECRET = KEY.split("\\.")[1]; + + private static final ClientV4 client = new ClientV4.Builder(API_KEY, API_SECRET).build(); + + + @SneakyThrows + public static void main(String[] args) { + List messages = new ArrayList<>(); + + String promptName = "prompt.txt"; + + String content = Files.readString(Paths.get("/Users/zhangzhiyong/IdeaProjects/goodjava/mone/jcommon/ai/zhipu/src/main/resources/" + promptName)); + + ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), content); + messages.add(chatMessage); + String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); + ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() + .model(Constants.ModelChatGLM4) + .stream(Boolean.FALSE) + .invokeMethod(Constants.invokeMethod) + .messages(messages) + .requestId(requestId) + .build(); + ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest); + String resContent = invokeModelApiResp.getData().getChoices().get(0).getMessage().getContent().toString(); + System.out.println(resContent); +// System.out.println("model output:"+ new Gson().toJson(invokeModelApiResp)); + } +} \ No newline at end of file diff --git a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Ioc.java b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Ioc.java index 308737084..e02212203 100644 --- a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Ioc.java +++ b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Ioc.java @@ -26,6 +26,7 @@ import com.google.gson.reflect.TypeToken; import com.xiaomi.youpin.docean.anno.Component; import com.xiaomi.youpin.docean.anno.Controller; +import com.xiaomi.youpin.docean.anno.IocConfiguration; import com.xiaomi.youpin.docean.anno.Service; import com.xiaomi.youpin.docean.bo.Bean; import com.xiaomi.youpin.docean.common.*; @@ -69,6 +70,9 @@ public class Ioc { @Getter private String[] scanPackages; + @Getter + private Class primarySource; + /** * It needs to be used when interacting with containers like spring */ @@ -357,6 +361,25 @@ public Ioc classLoader(ClassLoader classLoader) { return this; } + public static Ioc run(Class primarySource, String... args) { + IocConfiguration configuration = primarySource.getAnnotation(IocConfiguration.class); + Ioc ioc = Ioc.ins(); + ioc.primarySource = primarySource; + parseArgumentsAndPopulateIoc(args, ioc); + return ioc.init(configuration.basePackage()); + } + + private static void parseArgumentsAndPopulateIoc(String[] args, Ioc ioc) { + //Determine if args is an even number; if so, place it into a map. + Map argsMap = new HashMap<>(); + if (args.length % 2 == 0) { + for (int i = 0; i < args.length; i += 2) { + argsMap.put(args[i], args[i + 1]); + } + } + argsMap.entrySet().forEach(entry -> ioc.putBean("$" + entry.getKey(), entry.getValue())); + } + public Ioc init(String... scanPackages) { this.scanPackages = scanPackages; this.publishEvent(new Event(EventType.initBegin)); diff --git a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/anno/IocConfiguration.java b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/anno/IocConfiguration.java new file mode 100644 index 000000000..e2c51adaf --- /dev/null +++ b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/anno/IocConfiguration.java @@ -0,0 +1,16 @@ +package com.xiaomi.youpin.docean.anno; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author goodjava@qq.com + * @date 2024/3/3 09:19 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) // 应用于类 +public @interface IocConfiguration { + String[] basePackage(); +} diff --git a/jcommon/docean/src/test/java/com/xiaomi/youpin/docean/test/TestRun.java b/jcommon/docean/src/test/java/com/xiaomi/youpin/docean/test/TestRun.java new file mode 100644 index 000000000..1d168dc94 --- /dev/null +++ b/jcommon/docean/src/test/java/com/xiaomi/youpin/docean/test/TestRun.java @@ -0,0 +1,21 @@ +package com.xiaomi.youpin.docean.test; + +import com.xiaomi.youpin.docean.Ioc; +import com.xiaomi.youpin.docean.anno.IocConfiguration; +import com.xiaomi.youpin.docean.test.demo.DemoDao; + +/** + * @author goodjava@qq.com + * @date 2024/3/5 14:47 + *

+ * Evaluating the efficacy of @IocConfiguration. + */ +@IocConfiguration(basePackage = {"com.xiaomi.youpin.docean.test.demo"}) +public class TestRun { + + public static void main(String[] args) { + DemoDao demoA = Ioc.run(TestRun.class, args).getBean(DemoDao.class); + System.out.println(demoA.get()); + } + +} diff --git a/jcommon/openai/src/main/java/run/mone/openai/OpenaiCall.java b/jcommon/openai/src/main/java/run/mone/openai/OpenaiCall.java index 8f4fafa1d..8644f7415 100644 --- a/jcommon/openai/src/main/java/run/mone/openai/OpenaiCall.java +++ b/jcommon/openai/src/main/java/run/mone/openai/OpenaiCall.java @@ -270,6 +270,9 @@ public void onFailure(EventSource eventSource, @Nullable Throwable t, @Nullable }); } + public static void callStream2(String req, StreamListener sl, ReqConfig config) { + callStream2(req, sl, config, null); + } /** * 原生的调用,底层只依赖okhttp @@ -278,10 +281,11 @@ public void onFailure(EventSource eventSource, @Nullable Throwable t, @Nullable * @param sl * @param config */ - public static void callStream2(String req, StreamListener sl, ReqConfig config) { + public static void callStream2(String req, StreamListener sl, ReqConfig config, Headers headers) { MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); Request request = new Request.Builder() + .headers(headers) .url(config.getAskUrl()) .post(RequestBody.create(mediaType, req.getBytes(Charset.forName("utf8")))) .build(); diff --git a/jcommon/openai/src/test/java/run/mone/openapi/OpenApiTest.java b/jcommon/openai/src/test/java/run/mone/openapi/OpenApiTest.java index 1c25e6a22..dcb862c5b 100644 --- a/jcommon/openai/src/test/java/run/mone/openapi/OpenApiTest.java +++ b/jcommon/openai/src/test/java/run/mone/openapi/OpenApiTest.java @@ -26,6 +26,7 @@ import io.reactivex.disposables.Disposable; import lombok.Data; import lombok.SneakyThrows; +import okhttp3.Headers; import okhttp3.Response; import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.sse.EventSource; @@ -298,6 +299,36 @@ public void test4() { System.out.println(res.getChoices().get(0).getMessage().getContent()); } + @SneakyThrows + @Test + public void testMoonshot() { + Stopwatch stopwatch = Stopwatch.createStarted(); + String question = Files.readString(Paths.get("/Users/zhangzhiyong/IdeaProjects/goodjava/mone/jcommon/ai/src/main/resources/prompt.txt")); + OpenAiClient client = OpenaiCall.client(System.getenv("moonshot_token"), "https://api.moonshot.cn/"); + ChatCompletionResponse res = client.chatCompletion(ChatCompletion.builder().model("moonshot-v1-8k").messages(Lists.newArrayList(Message.builder() + .role(Message.Role.USER).content(question) + .build())).build()); + System.out.println(res.getChoices().get(0).getMessage().getContent()); + System.out.println("use time:" + stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } + + @SneakyThrows + @Test + public void testMoonshot2() { + String question = Files.readString(Paths.get("/Users/zhangzhiyong/IdeaProjects/goodjava/mone/jcommon/ai/src/main/resources/prompt3.txt")); + ChatCompletion completion = ChatCompletion.builder().stream(true).model("moonshot-v1-8k").messages(Lists.newArrayList(Message.builder() + .role(Message.Role.USER).content(question) + .build())).build(); + + OpenaiCall.callStream2(new Gson().toJson(completion), new StreamListener() { + @Override + public void onEvent(String str) { + System.out.println(str); + } + }, ReqConfig.builder().model("moonshot-v1-8k").askUrl("https://api.moonshot.cn/v1/chat/completions").build(), Headers.of("Authorization", "Bearer " + System.getenv("moonshot_token"))); + System.in.read(); + } + /** * 测试使用Azure的openai * POST https://b2c-mione-gpt35.openai.azure.com/openai/deployments/gpt-35-turbo/completions?api-version=2023-05-15 diff --git a/jcommon/pom.xml b/jcommon/pom.xml index 5cdfcac09..e96e2bf0c 100644 --- a/jcommon/pom.xml +++ b/jcommon/pom.xml @@ -86,6 +86,7 @@ match infra-common docean-spring-starter + ai diff --git a/jcommon/struct/src/main/java/com/xiaomi/data/push/graph/Graph.java b/jcommon/struct/src/main/java/com/xiaomi/data/push/graph/Graph.java index 548604199..b14bb9cec 100644 --- a/jcommon/struct/src/main/java/com/xiaomi/data/push/graph/Graph.java +++ b/jcommon/struct/src/main/java/com/xiaomi/data/push/graph/Graph.java @@ -62,6 +62,18 @@ public void addVertex(Vertex vertex) { this.vertexMap.put(vertex.getV(), vertex.getData()); } + //删除这个顶点,且删除和它相关的所有边(class) + public void removeVertex(int v) { + // 删除顶点数据 + vertexMap.remove(v); + // 删除所有出边 + adj[v].clear(); + // 删除所有入边 + for (List edges : adj) { + edges.removeIf(edge -> edge == v); + } + } + public List dependList(int v) { List result = Lists.newArrayList(); diff --git a/jcommon/struct/src/main/java/com/xiaomi/data/push/graph/Graph2.java b/jcommon/struct/src/main/java/com/xiaomi/data/push/graph/Graph2.java new file mode 100644 index 000000000..c601477f2 --- /dev/null +++ b/jcommon/struct/src/main/java/com/xiaomi/data/push/graph/Graph2.java @@ -0,0 +1,114 @@ +package com.xiaomi.data.push.graph; + +import com.google.common.collect.Maps; + +import java.util.*; + +/** + * @author goodjava@qq.com + * @date 2024/3/12 14:49 + */ +public class Graph2 { + + + //存储顶点的map + private Map vertexMap = Maps.newHashMap(); + + //存储边 + private Map> adjMap = Maps.newHashMap(); + + + /** + * 添加顶点 + * + * @param vertex + */ + public void addVertex(Vertex vertex) { + this.vertexMap.put(vertex.getV(), vertex.getData()); + } + + public void addEdge(int u, int v) { + //添加边 + if (!adjMap.containsKey(u)) { + adjMap.put(u, new ArrayList<>()); + } + adjMap.get(u).add(v); + } + + //删除这个顶点,且删除和它相关的所有边(class) + public void removeVertex(int vertex) { + // Remove the vertex from vertexMap + if (!vertexMap.containsKey(vertex)) { + throw new IllegalArgumentException("Vertex does not exist."); + } + vertexMap.remove(vertex); + + // Remove all edges associated with this vertex from adjMap + if (adjMap.containsKey(vertex)) { + adjMap.remove(vertex); + } + + // Remove the vertex from all adjacency lists + for (List edges : adjMap.values()) { + edges.removeIf(edge -> edge.equals(vertex)); + } + } + + public D getVertexData(int id) { + return vertexMap.get(id); + } + + + //帮我实现下拓扑排序(class) + public List topologicalSort() { + List result = new ArrayList<>(); + Map inDegree = new HashMap<>(); + Queue queue = new LinkedList<>(); + + // Initialize in-degree of all vertices + for (Integer v : vertexMap.keySet()) { + inDegree.put(v, 0); + } + + // Calculate in-degree of each vertex + for (List edges : adjMap.values()) { + for (Integer edge : edges) { + inDegree.put(edge, inDegree.get(edge) + 1); + } + } + + // Find all vertices with in-degree 0 + for (Map.Entry entry : inDegree.entrySet()) { + if (entry.getValue() == 0) { + queue.add(entry.getKey()); + } + } + + // Process vertices with in-degree 0 + while (!queue.isEmpty()) { + Integer vertex = queue.poll(); + result.add(vertex); + + // Decrease in-degree by 1 for all adjacent vertices + if (adjMap.containsKey(vertex)) { + for (Integer adjVertex : adjMap.get(vertex)) { + inDegree.put(adjVertex, inDegree.get(adjVertex) - 1); + + // If in-degree becomes 0, add it to the queue + if (inDegree.get(adjVertex) == 0) { + queue.add(adjVertex); + } + } + } + } + + // Check if there was a cycle + if (result.size() != vertexMap.size()) { + throw new IllegalStateException("Graph has a cycle, topological sort not possible"); + } + + return result; + } + + +} diff --git a/jcommon/struct/src/test/java/run/mone/struct/test/GraphTest.java b/jcommon/struct/src/test/java/run/mone/struct/test/GraphTest.java index 92fd594ca..f523339a5 100644 --- a/jcommon/struct/src/test/java/run/mone/struct/test/GraphTest.java +++ b/jcommon/struct/src/test/java/run/mone/struct/test/GraphTest.java @@ -1,6 +1,7 @@ package run.mone.struct.test; import com.xiaomi.data.push.graph.Graph; +import com.xiaomi.data.push.graph.Graph2; import com.xiaomi.data.push.graph.Vertex; import org.junit.Test; @@ -12,6 +13,27 @@ */ public class GraphTest { + + @Test + public void test1() { + Graph2 graph = new Graph2<>(); + + graph.addVertex(new Vertex<>(44, VertexData.builder().data("执行").id(0).build())); + graph.addVertex(new Vertex<>(88, VertexData.builder().data("aaa").id(0).build())); + graph.addVertex(new Vertex<>(33, VertexData.builder().data("开始").id(0).build())); + graph.addVertex(new Vertex<>(22, VertexData.builder().data("结束").id(0).build())); + + graph.addEdge(33,44); + graph.addEdge(44,22); + graph.addEdge(22,88); + + +// graph.removeVertex(44); + + List list = graph.topologicalSort(); + System.out.println(list); + } + @Test public void initializeAndTopologicallySortGraph() { Graph graph = new Graph<>(5);