From 02f86f93d2ea61f65108e6ac7c583285b8bbcd52 Mon Sep 17 00:00:00 2001 From: zhangzhiyong Date: Mon, 27 Nov 2023 11:48:02 +0800 Subject: [PATCH 1/4] update --- .../openai/src/main/java/run/mone/openai/OpenaiCall.java | 2 +- .../src/test/java/run/mone/openapi/OpenApiTest.java | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) 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 2c65952ee..8f4fafa1d 100644 --- a/jcommon/openai/src/main/java/run/mone/openai/OpenaiCall.java +++ b/jcommon/openai/src/main/java/run/mone/openai/OpenaiCall.java @@ -265,7 +265,7 @@ public void onClosed(EventSource eventSource) { @Override public void onFailure(EventSource eventSource, @Nullable Throwable t, @Nullable Response response) { - log.error("on failure error:" + t, t); + log.error("on failure error:" + response, t); } }); } 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 c37f33d55..1c25e6a22 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.Response; import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.sse.EventSource; import okhttp3.sse.EventSourceListener; @@ -168,7 +169,7 @@ private OpenAiClient client() { public void testCallStream() { String key = System.getenv("open_api_key"); CountDownLatch latch = new CountDownLatch(1); - OpenaiCall.callStream(key, null, "天空为什么是蓝色的", new String[]{}, new StreamListener() { + OpenaiCall.callStream(key, "", "天空为什么是蓝色的", new String[]{}, new StreamListener() { @Override public void onEvent(String str) { System.out.println(str); @@ -178,6 +179,11 @@ public void onEvent(String str) { public void end() { latch.countDown(); } + + @Override + public void onFailure(Throwable t, Response response) { + System.out.println(t + "" + response); + } }); latch.await(); } From 45628ab39a7c3f94beb930b9c5f7092a5dbac689 Mon Sep 17 00:00:00 2001 From: zhangzhiyong Date: Sun, 10 Mar 2024 10:20:11 +0800 Subject: [PATCH 2/4] The vertices of the graph support the map data structure clsoe(#810) --- jcommon/ai/pom.xml | 24 ++++ jcommon/ai/src/main/resources/prompt.txt | 80 ++++++++++++ jcommon/ai/src/main/resources/prompt2.txt | 46 +++++++ jcommon/ai/src/main/resources/prompt3.txt | 1 + jcommon/ai/zhipu/pom.xml | 38 ++++++ .../ai/zhipu/src/main/java/run/mone/Main.java | 57 +++++++++ .../java/com/xiaomi/youpin/docean/Ioc.java | 23 ++++ .../youpin/docean/anno/IocConfiguration.java | 16 +++ .../xiaomi/youpin/docean/test/TestRun.java | 21 ++++ .../main/java/run/mone/openai/OpenaiCall.java | 6 +- .../java/run/mone/openapi/OpenApiTest.java | 31 +++++ jcommon/pom.xml | 1 + .../com/xiaomi/data/push/graph/Graph.java | 12 ++ .../com/xiaomi/data/push/graph/Graph2.java | 114 ++++++++++++++++++ .../java/run/mone/struct/test/GraphTest.java | 22 ++++ 15 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 jcommon/ai/pom.xml create mode 100644 jcommon/ai/src/main/resources/prompt.txt create mode 100644 jcommon/ai/src/main/resources/prompt2.txt create mode 100644 jcommon/ai/src/main/resources/prompt3.txt create mode 100644 jcommon/ai/zhipu/pom.xml create mode 100644 jcommon/ai/zhipu/src/main/java/run/mone/Main.java create mode 100644 jcommon/docean/src/main/java/com/xiaomi/youpin/docean/anno/IocConfiguration.java create mode 100644 jcommon/docean/src/test/java/com/xiaomi/youpin/docean/test/TestRun.java create mode 100644 jcommon/struct/src/main/java/com/xiaomi/data/push/graph/Graph2.java 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); From 0cf16dd7d58230f5a901e399ebd6956641c675f8 Mon Sep 17 00:00:00 2001 From: zhangzhiyong Date: Fri, 12 Apr 2024 19:39:12 +0800 Subject: [PATCH 3/4] ai support Use local LLM(claude3) close #827 --- jcommon/ai/aws/pom.xml | 38 ++ .../aws/src/main/java/run/mone/AwsClient.java | 51 ++ .../aws/src/main/java/run/mone/Content.java | 19 + .../ai/aws/src/main/java/run/mone/Key.java | 19 + .../aws/src/main/java/run/mone/ModelEnum.java | 20 + .../main/java/run/mone/ResponsePayload.java | 39 ++ .../ai/aws/src/main/java/run/mone/Usage.java | 19 + .../mone/aws/client/test/AwsClientTest.java | 34 ++ jcommon/ai/google/pom.xml | 28 +- .../java/run/mone/ai/google/CloudeClient.java | 26 +- jcommon/ai/pom.xml | 26 + jcommon/ai/zhipu/pom.xml | 2 + jcommon/pom.xml | 519 +++++++++--------- .../com/xiaomi/data/push/graph/Graph2.java | 16 + .../java/run/mone/struct/test/GraphTest.java | 5 + 15 files changed, 596 insertions(+), 265 deletions(-) create mode 100644 jcommon/ai/aws/pom.xml create mode 100644 jcommon/ai/aws/src/main/java/run/mone/AwsClient.java create mode 100644 jcommon/ai/aws/src/main/java/run/mone/Content.java create mode 100644 jcommon/ai/aws/src/main/java/run/mone/Key.java create mode 100644 jcommon/ai/aws/src/main/java/run/mone/ModelEnum.java create mode 100644 jcommon/ai/aws/src/main/java/run/mone/ResponsePayload.java create mode 100644 jcommon/ai/aws/src/main/java/run/mone/Usage.java create mode 100644 jcommon/ai/aws/src/test/java/run/mone/aws/client/test/AwsClientTest.java diff --git a/jcommon/ai/aws/pom.xml b/jcommon/ai/aws/pom.xml new file mode 100644 index 000000000..55c70c2de --- /dev/null +++ b/jcommon/ai/aws/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + run.mone + ai + 1.4-jdk20-SNAPSHOT + + + aws + + + 21 + 21 + UTF-8 + + + + + + software.amazon.awssdk + bedrockruntime + 2.25.29 + + + + org.json + json + 20240303 + + + + + + + \ No newline at end of file diff --git a/jcommon/ai/aws/src/main/java/run/mone/AwsClient.java b/jcommon/ai/aws/src/main/java/run/mone/AwsClient.java new file mode 100644 index 000000000..9b68db744 --- /dev/null +++ b/jcommon/ai/aws/src/main/java/run/mone/AwsClient.java @@ -0,0 +1,51 @@ +package run.mone; + +import com.google.gson.Gson; +import org.json.JSONObject; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; +import software.amazon.awssdk.identity.spi.IdentityProvider; +import software.amazon.awssdk.identity.spi.ResolveIdentityRequest; +import software.amazon.awssdk.identity.spi.internal.DefaultAwsCredentialsIdentity; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.bedrockruntime.BedrockRuntimeClient; +import software.amazon.awssdk.services.bedrockruntime.model.InvokeModelRequest; +import software.amazon.awssdk.services.bedrockruntime.model.InvokeModelResponse; + +import java.util.concurrent.CompletableFuture; + +/** + * @author goodjava@qq.com + * @date 2024/4/12 13:35 + */ +public class AwsClient { + + private static final Gson gson = new Gson(); + + + public static ResponsePayload call(JSONObject payload, Region region, String modelId, Key key) { + BedrockRuntimeClient client = BedrockRuntimeClient.builder() + .credentialsProvider(new IdentityProvider<>() { + @Override + public Class identityType() { + return AwsCredentialsIdentity.class; + } + + public CompletableFuture resolveIdentity(ResolveIdentityRequest request) { + return CompletableFuture.completedFuture(DefaultAwsCredentialsIdentity.builder().accessKeyId(key.getKeyId()).secretAccessKey(key.getKey()).build()); + } + }) + .region(region) + .build(); + + InvokeModelRequest request = InvokeModelRequest.builder() + .contentType("application/json") + .body(SdkBytes.fromUtf8String(payload.toString())) + .modelId(modelId) + .build(); + + InvokeModelResponse resp = client.invokeModel(request); + String str = new String(resp.body().asByteArray()); + return gson.fromJson(str, ResponsePayload.class); + } +} \ No newline at end of file diff --git a/jcommon/ai/aws/src/main/java/run/mone/Content.java b/jcommon/ai/aws/src/main/java/run/mone/Content.java new file mode 100644 index 000000000..0788f5447 --- /dev/null +++ b/jcommon/ai/aws/src/main/java/run/mone/Content.java @@ -0,0 +1,19 @@ +package run.mone; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +/** + * @author goodjava@qq.com + * @date 2024/4/9 16:43 + */ +@Data +public class Content { + + @SerializedName("type") + private String type; + + @SerializedName("text") + private String text; + +} diff --git a/jcommon/ai/aws/src/main/java/run/mone/Key.java b/jcommon/ai/aws/src/main/java/run/mone/Key.java new file mode 100644 index 000000000..c909c5bd8 --- /dev/null +++ b/jcommon/ai/aws/src/main/java/run/mone/Key.java @@ -0,0 +1,19 @@ +package run.mone; + +import lombok.Builder; +import lombok.Data; + +/** + * @author goodjava@qq.com + * @date 2024/4/12 15:04 + */ +@Data +@Builder +public class Key { + + private String keyId; + + private String key; + + +} diff --git a/jcommon/ai/aws/src/main/java/run/mone/ModelEnum.java b/jcommon/ai/aws/src/main/java/run/mone/ModelEnum.java new file mode 100644 index 000000000..056788248 --- /dev/null +++ b/jcommon/ai/aws/src/main/java/run/mone/ModelEnum.java @@ -0,0 +1,20 @@ +package run.mone; + +/** + * @author goodjava@qq.com + * @date 2024/4/12 14:59 + */ +public enum ModelEnum { + + + Sonnet("anthropic.claude-3-sonnet-20240229-v1:0"), + Haiku("anthropic.claude-3-haiku-20240307-v1:0"); + + + public String modelName; + + ModelEnum(String name) { + this.modelName = name; + } + +} diff --git a/jcommon/ai/aws/src/main/java/run/mone/ResponsePayload.java b/jcommon/ai/aws/src/main/java/run/mone/ResponsePayload.java new file mode 100644 index 000000000..85b2c1a2e --- /dev/null +++ b/jcommon/ai/aws/src/main/java/run/mone/ResponsePayload.java @@ -0,0 +1,39 @@ +package run.mone; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.util.List; + +/** + * @author goodjava@qq.com + * @date 2024/4/9 16:41 + */ +@Data +public class ResponsePayload { + + @SerializedName("id") + private String id; + + @SerializedName("type") + private String type; + + @SerializedName("role") + private String role; + + @SerializedName("content") + private List content; + + @SerializedName("model") + private String model; + + @SerializedName("stop_reason") + private String stopReason; + + @SerializedName("stop_sequence") + private Object stopSequence; // Use Object if the value can be null or of different types + + @SerializedName("usage") + private Usage usage; + +} diff --git a/jcommon/ai/aws/src/main/java/run/mone/Usage.java b/jcommon/ai/aws/src/main/java/run/mone/Usage.java new file mode 100644 index 000000000..c597b6385 --- /dev/null +++ b/jcommon/ai/aws/src/main/java/run/mone/Usage.java @@ -0,0 +1,19 @@ +package run.mone; + +import com.google.gson.annotations.SerializedName; + +/** + * @author goodjava@qq.com + * @date 2024/4/9 16:42 + */ +public class Usage { + + + @SerializedName("input_tokens") + private int inputTokens; + + @SerializedName("output_tokens") + private int outputTokens; + + +} diff --git a/jcommon/ai/aws/src/test/java/run/mone/aws/client/test/AwsClientTest.java b/jcommon/ai/aws/src/test/java/run/mone/aws/client/test/AwsClientTest.java new file mode 100644 index 000000000..574b14faf --- /dev/null +++ b/jcommon/ai/aws/src/test/java/run/mone/aws/client/test/AwsClientTest.java @@ -0,0 +1,34 @@ +package run.mone.aws.client.test; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Test; +import run.mone.AwsClient; +import run.mone.Key; +import run.mone.ModelEnum; +import run.mone.ResponsePayload; +import software.amazon.awssdk.regions.Region; + +/** + * @author goodjava@qq.com + * @date 2024/4/12 14:57 + */ +public class AwsClientTest { + + + @Test + public void test1() { + JSONObject payload = new JSONObject() + .put("anthropic_version", "bedrock-2023-05-31") + .put("max_tokens", 1000) + .put("messages", new JSONArray() + .put(new JSONObject().put("role", "user") + .put("content", "天空为什么是蓝色的?" + ) + ) + ); + ResponsePayload res = AwsClient.call(payload, Region.EU_WEST_3, ModelEnum.Haiku.modelName, Key.builder().keyId("").key("").build()); + System.out.println(res.getContent().get(0).getText()); + } + +} diff --git a/jcommon/ai/google/pom.xml b/jcommon/ai/google/pom.xml index af5c82b69..6213e1dbc 100644 --- a/jcommon/ai/google/pom.xml +++ b/jcommon/ai/google/pom.xml @@ -10,10 +10,11 @@ google + 1.4-jdk8-SNAPSHOT - 21 - 21 + 8 + 8 UTF-8 @@ -41,4 +42,27 @@ + + + + + + maven-compiler-plugin + 3.11.0 + + 8 + 8 + true + UTF-8 + + ${project.basedir}/src/main/java + + + + + + + + + \ No newline at end of file diff --git a/jcommon/ai/google/src/main/java/run/mone/ai/google/CloudeClient.java b/jcommon/ai/google/src/main/java/run/mone/ai/google/CloudeClient.java index 871f05495..63f71c457 100644 --- a/jcommon/ai/google/src/main/java/run/mone/ai/google/CloudeClient.java +++ b/jcommon/ai/google/src/main/java/run/mone/ai/google/CloudeClient.java @@ -2,22 +2,28 @@ import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; import com.google.gson.Gson; import lombok.Data; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import okhttp3.*; +import run.mone.ai.google.bo.Content; import run.mone.ai.google.bo.RequestPayload; import run.mone.ai.google.bo.ResponsePayload; import java.io.FileInputStream; import java.io.IOException; import java.util.Collections; +import java.util.concurrent.TimeUnit; /** * @author goodjava@qq.com * @date 2024/4/9 15:59 */ @Data +@Slf4j public class CloudeClient { private String url = "https://us-central1-aiplatform.googleapis.com/v1/projects/"; @@ -30,6 +36,8 @@ public class CloudeClient { private String token; + private static Gson gson = new Gson(); + @SneakyThrows public String token() { @@ -46,7 +54,7 @@ public String token() { public ResponsePayload call(String token, RequestPayload requestPayload) { - OkHttpClient client = new OkHttpClient(); + OkHttpClient client = new OkHttpClient.Builder().readTimeout(5, TimeUnit.MINUTES).build(); MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); RequestBody body = RequestBody.create(mediaType, new Gson().toJson(requestPayload)); Request request = new Request.Builder() @@ -57,11 +65,21 @@ public ResponsePayload call(String token, RequestPayload requestPayload) { .build(); try (Response response = client.newCall(request).execute()) { + if (response.code() == 429) { + ResponsePayload res = new ResponsePayload(); + Content content = new Content(); + content.setText(gson.toJson(ImmutableMap.of("message", "被claude3限流了", "code", "429"))); + log.info("claude res:{}", content.getText()); + res.setContent(Lists.newArrayList(content)); + return res; + } if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); // Handle the response - return new Gson().fromJson(response.body().string(), ResponsePayload.class); - } catch (Exception e) { - e.printStackTrace(); + String res = response.body().string(); + log.info("claude3 res:{}", res); + return new Gson().fromJson(res, ResponsePayload.class); + } catch (Throwable e) { + log.error(e.getMessage(), e); } return null; } diff --git a/jcommon/ai/pom.xml b/jcommon/ai/pom.xml index 97a16315e..0c71cad63 100644 --- a/jcommon/ai/pom.xml +++ b/jcommon/ai/pom.xml @@ -15,6 +15,7 @@ zhipu moonshot google + aws @@ -23,4 +24,29 @@ UTF-8 + + + + org.projectlombok + lombok + 1.18.30 + provided + + + + + + + + central + maven-release-virtual + https://pkgs.d.xiaomi.net/artifactory/maven-release-virtual + + + snapshots + maven-snapshot-virtual + https://pkgs.d.xiaomi.net/artifactory/maven-snapshot-virtual + + + \ No newline at end of file diff --git a/jcommon/ai/zhipu/pom.xml b/jcommon/ai/zhipu/pom.xml index 5bebe7c32..ce2c33045 100644 --- a/jcommon/ai/zhipu/pom.xml +++ b/jcommon/ai/zhipu/pom.xml @@ -19,6 +19,8 @@ + + cn.bigmodel.openapi oapi-java-sdk diff --git a/jcommon/pom.xml b/jcommon/pom.xml index f95e07618..bd8a0c84c 100644 --- a/jcommon/pom.xml +++ b/jcommon/pom.xml @@ -1,271 +1,272 @@ - - 4.0.0 - run.mone - jcommon - 1.6.0-jdk21-SNAPSHOT - pom - ${project.artifactId} - The parent project of jcommon - https://github.com/XiaoMi/mone - 2020 - - - Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0 - repo - - - - aliyun - log - common - annotation - antlr - rpc - redis - http - monitor - struct - gitlab - api - nacos - mongodb - coloregg - ks3 - test - docker - codegen - jmonitor - codecheck - cron - nginx - dbLocking - aop - crypto - catPlugin - feishu - sre - mistarter - health - docean - rcurve - micloud - docean-plugin - ssh - es - file - k8s - grpc - easy - df - monespring - graalvm - mquic - prometheus - buddy - hera - mv-plugin - teambition - spider - disruptor - pool - raft - event - geth - docean-plugin/docean-plugin-sidecar - sidecar-api - schedule - infra-result - rpc-codes - mybatis-plugins - processor - openai - excel - match - infra-common - docean-spring-starter - ai - + + 4.0.0 + run.mone + jcommon + 1.6.0-jdk21-SNAPSHOT + pom + ${project.artifactId} + The parent project of jcommon + https://github.com/XiaoMi/mone + 2020 + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + repo + + + + aliyun + log + common + annotation + antlr + rpc + redis + http + monitor + struct + gitlab + api + nacos + mongodb + coloregg + ks3 + test + docker + codegen + jmonitor + codecheck + cron + nginx + dbLocking + aop + crypto + catPlugin + feishu + sre + mistarter + health + docean + rcurve + micloud + docean-plugin + ssh + es + file + k8s + grpc + easy + df + monespring + graalvm + mquic + prometheus + buddy + hera + mv-plugin + teambition + spider + disruptor + pool + raft + event + geth + docean-plugin/docean-plugin-sidecar + sidecar-api + schedule + infra-result + rpc-codes + mybatis-plugins + processor + openai + excel + match + infra-common + docean-spring-starter + ai + - - - - - - - - - - + + + + + + + + + + - - - central - maven-release-virtual - https://pkgs.d.xiaomi.net/artifactory/maven-release-virtual - - - snapshots - maven-snapshot-virtual - https://pkgs.d.xiaomi.net/artifactory/maven-snapshot-virtual - - + + + central + maven-release-virtual + https://pkgs.d.xiaomi.net/artifactory/maven-release-virtual + + + snapshots + maven-snapshot-virtual + https://pkgs.d.xiaomi.net/artifactory/maven-snapshot-virtual + + - - ~/ - 8 - 8 - 1.6.0-jdk21-SNAPSHOT - - - - junit - junit - 4.12 - test - - - com.google.code.gson - gson - 2.8.5 - - - org.projectlombok - lombok - 1.18.30 - - - ch.qos.logback - logback-classic - 1.1.2 - provided - - - ch.qos.logback - logback-core - 1.1.2 - provided - - - com.google.guava - guava - 25.1-jre - - - org.springframework - spring-core - 5.0.6.RELEASE - provided - - - org.springframework - spring-context - 5.0.6.RELEASE - provided - - - - - - maven-resources-plugin - 3.2.0 - - - copy-license - prepare-package - - copy-resources - - - target/classes/META-INF - - - ${maven.jcommonDirectory} - - LICENSE.txt - - - - - - - + + ~/ + 8 + 8 + 1.6.0-jdk21-SNAPSHOT + + + + junit + junit + 4.12 + test + + + com.google.code.gson + gson + 2.8.5 + + + org.projectlombok + lombok + 1.18.30 + + + ch.qos.logback + logback-classic + 1.1.2 + provided + + + ch.qos.logback + logback-core + 1.1.2 + provided + + + com.google.guava + guava + 25.1-jre + + + org.springframework + spring-core + 5.0.6.RELEASE + provided + + + org.springframework + spring-context + 5.0.6.RELEASE + provided + + + + + + maven-resources-plugin + 3.2.0 + + + copy-license + prepare-package + + copy-resources + + + target/classes/META-INF + + + ${maven.jcommonDirectory} + + LICENSE.txt + + + + + + + - - org.codehaus.mojo - build-helper-maven-plugin - 3.4.0 - + + org.codehaus.mojo + build-helper-maven-plugin + 3.4.0 + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - maven-compiler-plugin - 3.11.0 - - 20 - 20 - true - UTF-8 - - ${project.basedir}/src/main/java - - - + + maven-compiler-plugin + 3.11.0 + + 20 + 20 + true + UTF-8 + + ${project.basedir}/src/main/java + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - + + 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 index c601477f2..b92aab971 100644 --- 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 @@ -58,6 +58,22 @@ public D getVertexData(int id) { return vertexMap.get(id); } + //获取当前节点(vertex)的前置节点列表(class) + public List getPredecessors(int vertex) { + // Check if the vertex exists in the graph + if (!vertexMap.containsKey(vertex)) { + throw new IllegalArgumentException("Vertex does not exist."); + } + List predecessors = new ArrayList<>(); + // Iterate over the adjacency map to find all vertices that point to the current vertex + for (Map.Entry> entry : adjMap.entrySet()) { + if (entry.getValue().contains(vertex)) { + predecessors.add(entry.getKey()); + } + } + return predecessors; + } + //帮我实现下拓扑排序(class) public List topologicalSort() { 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 f523339a5..803077f90 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 @@ -26,12 +26,17 @@ public void test1() { graph.addEdge(33,44); graph.addEdge(44,22); graph.addEdge(22,88); + graph.addEdge(44,88); // graph.removeVertex(44); List list = graph.topologicalSort(); System.out.println(list); + + + System.out.println(graph.getPredecessors(88)); + } @Test From 145a8bf7b7153b92ce6d62ad2cc8bd674f30fb9c Mon Sep 17 00:00:00 2001 From: zhangzhiyong Date: Fri, 19 Apr 2024 14:39:19 +0800 Subject: [PATCH 4/4] Official and Stable ORM Framework for MongoDB close(#829) --- .../aws/src/main/java/run/mone/ModelEnum.java | 3 +- .../docean-plugin-mongodb/pom.xml | 11 +++++ .../youpin/docean/plugin/mongodb/MongoDb.java | 37 +++++++-------- .../docean/plugin/mongodb/MongodbPlugin.java | 21 ++++++++- jcommon/docean/pom.xml | 1 - .../java/com/xiaomi/youpin/docean/Mvc.java | 45 +++++++++++++++++-- .../youpin/docean/mvc/HttpRequestMethod.java | 3 ++ .../youpin/docean/common/MethodInvoker.java | 4 ++ .../com/xiaomi/data/push/mongodb/MongoDb.java | 10 +++++ 9 files changed, 110 insertions(+), 25 deletions(-) diff --git a/jcommon/ai/aws/src/main/java/run/mone/ModelEnum.java b/jcommon/ai/aws/src/main/java/run/mone/ModelEnum.java index 056788248..ac0a2523a 100644 --- a/jcommon/ai/aws/src/main/java/run/mone/ModelEnum.java +++ b/jcommon/ai/aws/src/main/java/run/mone/ModelEnum.java @@ -8,7 +8,8 @@ public enum ModelEnum { Sonnet("anthropic.claude-3-sonnet-20240229-v1:0"), - Haiku("anthropic.claude-3-haiku-20240307-v1:0"); + Haiku("anthropic.claude-3-haiku-20240307-v1:0"), + Opus("anthropic.claude-3-opus-20240229-v1:0"); public String modelName; diff --git a/jcommon/docean-plugin/docean-plugin-mongodb/pom.xml b/jcommon/docean-plugin/docean-plugin-mongodb/pom.xml index a5a6ce68a..95876db84 100644 --- a/jcommon/docean-plugin/docean-plugin-mongodb/pom.xml +++ b/jcommon/docean-plugin/docean-plugin-mongodb/pom.xml @@ -10,19 +10,30 @@ docean-plugin-mongodb 1.5.0-jdk21-SNAPSHOT + run.mone docean-plugin-config + org.mongodb mongo-java-driver 3.8.0 + run.mone catPlugin 1.6.0-jdk21-SNAPSHOT + + + dev.morphia.morphia + morphia-core + 2.4.13 + + + diff --git a/jcommon/docean-plugin/docean-plugin-mongodb/src/main/java/com/xiaomi/youpin/docean/plugin/mongodb/MongoDb.java b/jcommon/docean-plugin/docean-plugin-mongodb/src/main/java/com/xiaomi/youpin/docean/plugin/mongodb/MongoDb.java index 858616b92..9efde4904 100644 --- a/jcommon/docean-plugin/docean-plugin-mongodb/src/main/java/com/xiaomi/youpin/docean/plugin/mongodb/MongoDb.java +++ b/jcommon/docean-plugin/docean-plugin-mongodb/src/main/java/com/xiaomi/youpin/docean/plugin/mongodb/MongoDb.java @@ -25,6 +25,7 @@ import com.mongodb.client.MongoDatabase; import com.xiaomi.youpin.cat.CatPlugin; import org.bson.Document; +import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -73,6 +74,10 @@ public MongoCollection getCollection(String collectionName) { return db.getCollection(collectionName); } + public MongoCollection getCollection(String collectionName, Class clazz) { + return db.getCollection(collectionName, clazz); + } + public void insert(String collectionName, Document doc) { CatPlugin cat = new CatPlugin("insert", catEnabled, CAT_TYPE); boolean success = true; @@ -111,29 +116,25 @@ public void insertMany(String collectionName, List docList) { } public Document findFirst(String collectionName) { - CatPlugin cat = new CatPlugin("findFirst", catEnabled, CAT_TYPE); - boolean success = true; - cat.before(null); - try { - MongoCollection collection = this.getCollection(collectionName); - return collection.find().first(); - } catch (MongoException e) { - success = false; - logger.error(e.getMessage(), e); - } catch (Exception e) { - success = false; - logger.error(e.getMessage(), e); - } finally { - cat.after(success); - } - return null; + MongoCollection collection = this.getCollection(collectionName); + return collection.find().first(); + } + + public Document findFirst(String collectionName, Bson filter) { + MongoCollection collection = this.getCollection(collectionName); + return collection.find(filter).first(); + } + + public T findFirst(String collectionName, Bson filter, Class clazz) { + MongoCollection collection = this.getCollection(collectionName, clazz); + return collection.find(filter).first(); } - public List findAll(String collectionName, Document doc) { + public List findAll(String collectionName, Bson filter) { try { MongoCollection collection = this.getCollection(collectionName); List res = new ArrayList<>(); - for (Document cur : collection.find(doc)) { + for (Document cur : collection.find(filter)) { res.add(cur); } return res; diff --git a/jcommon/docean-plugin/docean-plugin-mongodb/src/main/java/com/xiaomi/youpin/docean/plugin/mongodb/MongodbPlugin.java b/jcommon/docean-plugin/docean-plugin-mongodb/src/main/java/com/xiaomi/youpin/docean/plugin/mongodb/MongodbPlugin.java index 41cf013ea..23983b8f8 100644 --- a/jcommon/docean-plugin/docean-plugin-mongodb/src/main/java/com/xiaomi/youpin/docean/plugin/mongodb/MongodbPlugin.java +++ b/jcommon/docean-plugin/docean-plugin-mongodb/src/main/java/com/xiaomi/youpin/docean/plugin/mongodb/MongodbPlugin.java @@ -16,10 +16,16 @@ package com.xiaomi.youpin.docean.plugin.mongodb; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; import com.xiaomi.youpin.docean.Ioc; import com.xiaomi.youpin.docean.anno.DOceanPlugin; import com.xiaomi.youpin.docean.plugin.IPlugin; import com.xiaomi.youpin.docean.plugin.config.Config; +import dev.morphia.Datastore; +import dev.morphia.Morphia; +import dev.morphia.mapping.Mapper; +import dev.morphia.mapping.MapperOptions; import lombok.extern.slf4j.Slf4j; import java.util.Set; @@ -42,10 +48,23 @@ public void init(Set> classSet, Ioc ioc) { mongoDb.setCatEnabled(config.get("mongodb.cat.enabled", "false").equals("true")); mongoDb.init(); ioc.putBean(mongoDb); + + + MongoClient mongoClient = MongoClients.create(mongoDb.getMongoDbClient()); + Datastore datastore = Morphia.createDatastore(mongoClient, mongoDb.getMongoDatabase()); + + + String packagePath = config.get("mongodb.package", "run.mone.bo"); + datastore.getMapper().mapPackage(packagePath); + datastore.ensureIndexes(); + + + ioc.putBean(Datastore.class.getName(), datastore); } @Override public String version() { - return "0.0.1:2020-07-04:zheng.xucn@outlook.com"; + return "0.0.1:2020-07-04:goodjava@qq.com"; } + } diff --git a/jcommon/docean/pom.xml b/jcommon/docean/pom.xml index a69a6d573..0574d9b39 100644 --- a/jcommon/docean/pom.xml +++ b/jcommon/docean/pom.xml @@ -17,7 +17,6 @@ run.mone easy 1.6.0-jdk21-SNAPSHOT - cglib diff --git a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Mvc.java b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Mvc.java index 68f697e41..6df887eaf 100644 --- a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Mvc.java +++ b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/Mvc.java @@ -16,6 +16,7 @@ package com.xiaomi.youpin.docean; +import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.xiaomi.youpin.docean.anno.RequestMapping; @@ -41,10 +42,12 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; -import java.util.Arrays; -import java.util.Locale; -import java.util.Optional; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.*; import java.util.concurrent.*; +import java.util.stream.Collectors; /** * @author goodjava@qq.com @@ -138,11 +141,32 @@ private void registerControllerMethods(Bean bean) { hrm.setObj(bean.getObj()); hrm.setMethod(m); hrm.setHttpMethod(rm.method()); + hrm.setGenericSuperclassTypeArguments(getGenericSuperclassTypeArguments(bean.getClazz())); ioc.publishEvent(new Event(EventType.initController, path)); requestMethodMap.put(path, hrm); })); } + public static Map getGenericSuperclassTypeArguments(Class clazz) { + List list = Arrays.stream(clazz.getSuperclass().getTypeParameters()).map(it -> it.getName()).collect(Collectors.toList()); + if (list.size() == 0) { + return Maps.newHashMap(); + } + Map map = new HashMap<>(); + Type genericSuperclass = clazz.getGenericSuperclass(); + if (genericSuperclass instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; + Type[] typeArguments = parameterizedType.getActualTypeArguments(); + for (int i = 0; i < typeArguments.length; i++) { + Type argument = typeArguments[i]; + if (argument instanceof Class) { + map.put(list.get(i), (Class) argument); + } + } + } + return map; + } + private static final class LazyHolder { private static final Mvc ins = new Mvc(Ioc.ins()); @@ -187,6 +211,16 @@ public void callService(MvcContext context, MvcRequest request, MvcResponse resp response.writeAndFlush(context, new Gson().toJson(mr)); } + public List mapMethodParametersToClasses(Method method, Map map) { + return Arrays.stream(method.getParameters()).map(it -> { + String name = it.getParameterizedType().getTypeName(); + if ((it.getType() instanceof Object) && map.containsKey(name)) { + return map.get(name); + } + return it.getType(); + }).collect(Collectors.toList()); + } + public void callMethod(MvcContext context, MvcRequest request, MvcResponse response, MvcResult result, HttpRequestMethod method) { Safe.run(() -> { Object[] params = new Object[]{null}; @@ -199,7 +233,10 @@ public void callMethod(MvcContext context, MvcRequest request, MvcResponse respo params[0] = context; } else { try { - params = methodInvoker.getMethodParams(method.getMethod(), args); + //可能方法中有泛型,这里给fix调,用实际的Class + List list = mapMethodParametersToClasses(method.getMethod(), method.getGenericSuperclassTypeArguments()); + Class[] types = list.toArray(new Class[]{}); + params = methodInvoker.getMethodParams(args, types); } catch (Exception e) { log.error("getMethodParams error,path:{},params:{},method:{}", context.getPath(), GsonUtils.gson.toJson(context.getParams()), request.getMethod().toLowerCase(Locale.ROOT), e); diff --git a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/HttpRequestMethod.java b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/HttpRequestMethod.java index 3a540b3fd..70756ec32 100644 --- a/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/HttpRequestMethod.java +++ b/jcommon/docean/src/main/java/com/xiaomi/youpin/docean/mvc/HttpRequestMethod.java @@ -19,6 +19,7 @@ import lombok.Data; import java.lang.reflect.Method; +import java.util.Map; /** * @author goodjava@qq.com @@ -36,5 +37,7 @@ public class HttpRequestMethod { private long timeout; + private Map genericSuperclassTypeArguments; + } diff --git a/jcommon/easy/src/main/java/com/xiaomi/youpin/docean/common/MethodInvoker.java b/jcommon/easy/src/main/java/com/xiaomi/youpin/docean/common/MethodInvoker.java index 804a4d6c6..31b6d5ec4 100644 --- a/jcommon/easy/src/main/java/com/xiaomi/youpin/docean/common/MethodInvoker.java +++ b/jcommon/easy/src/main/java/com/xiaomi/youpin/docean/common/MethodInvoker.java @@ -166,6 +166,10 @@ public Object[] getMethodParams(Object obj, String methodName, JsonElement param public Object[] getMethodParams(Method method, JsonElement params) { Class[] types = method.getParameterTypes(); + return getMethodParams(params, types); + } + + public Object[] getMethodParams(JsonElement params, Class[] types) { if (types.length == 0) { return new Object[]{}; } diff --git a/jcommon/mongodb/src/main/java/com/xiaomi/data/push/mongodb/MongoDb.java b/jcommon/mongodb/src/main/java/com/xiaomi/data/push/mongodb/MongoDb.java index 60bf99257..ff4cfe682 100644 --- a/jcommon/mongodb/src/main/java/com/xiaomi/data/push/mongodb/MongoDb.java +++ b/jcommon/mongodb/src/main/java/com/xiaomi/data/push/mongodb/MongoDb.java @@ -80,8 +80,13 @@ public MongoCollection getCollection(String collectionName) { return db.getCollection(collectionName); } + public MongoCollection getCollection(String collectionName, Class clazz) { + return db.getCollection(collectionName, clazz); + } + /** * Inserts a document under the specified collection + * * @param collectionName * @param doc */ @@ -106,6 +111,7 @@ public void insert(String collectionName, Document doc) { /** * Inserts a list of documents under the specified collection + * * @param collectionName * @param docList */ @@ -129,6 +135,7 @@ public void insertMany(String collectionName, List docList) { /** * Finds the first document under the specified collection + * * @param collectionName * @return */ @@ -153,6 +160,7 @@ public Document findFirst(String collectionName) { /** * Finds all documents under the specified collection according to the criteria + * * @param collectionName * @param doc * @return @@ -184,6 +192,7 @@ public List findAll(String collectionName, Document doc) { /** * Deletes a document under a specified collection under specified conditions + * * @param collectionName * @param doc */ @@ -207,6 +216,7 @@ public void delete(String collectionName, Document doc) { /** * Returns the number of documents under the specified collection + * * @param collectionName * @return */