diff --git a/jcommon/ai/neo4j/src/main/java/run/mone/neo4j/BotCall.java b/jcommon/ai/neo4j/src/main/java/run/mone/neo4j/BotCall.java new file mode 100644 index 000000000..0930633ac --- /dev/null +++ b/jcommon/ai/neo4j/src/main/java/run/mone/neo4j/BotCall.java @@ -0,0 +1,64 @@ +package run.mone.neo4j; + +import com.google.gson.JsonObject; +import lombok.Setter; +import okhttp3.*; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * @author goodjava@qq.com + * @date 2024/8/21 13:50 + */ +public class BotCall { + + //调用bot的地址 + @Setter + private static String url = ""; + + + public static String call(String desc, String input) { + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .build(); + + // 使用 Gson 的 JsonObject 构建请求体 + JsonObject mainObject = new JsonObject(); + mainObject.addProperty("userName", ""); + mainObject.addProperty("botId", ""); + mainObject.addProperty("input", ""); + + JsonObject paramsObject = new JsonObject(); + paramsObject.addProperty("desc", desc); + paramsObject.addProperty("input", input); + mainObject.add("params", paramsObject); + + // 将 JsonObject 转换为字符串 + String jsonBody = mainObject.toString(); + + RequestBody body = RequestBody.create(MediaType.parse("application/json"), jsonBody); + + Request request = new Request.Builder() + .url(url) + .post(body) + .addHeader("Accept", "application/json, text/plain, */*") + .addHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8") + .addHeader("Cache-Control", "no-cache") + .addHeader("Connection", "keep-alive") + .addHeader("Content-Type", "application/json") + .addHeader("Authorization", "") + .build(); + + try { + Response response = client.newCall(request).execute(); + return response.body().string(); + } catch (IOException e) { + e.printStackTrace(); + } + return ""; + } + +} diff --git a/jcommon/ai/neo4j/src/main/java/run/mone/neo4j/MoneCodeParser.java b/jcommon/ai/neo4j/src/main/java/run/mone/neo4j/MoneCodeParser.java index db7acf099..aa83443de 100644 --- a/jcommon/ai/neo4j/src/main/java/run/mone/neo4j/MoneCodeParser.java +++ b/jcommon/ai/neo4j/src/main/java/run/mone/neo4j/MoneCodeParser.java @@ -8,6 +8,7 @@ import com.github.javaparser.ast.comments.Comment; import com.github.javaparser.ast.comments.JavadocComment; import com.github.javaparser.ast.expr.AnnotationExpr; +import com.github.javaparser.ast.nodeTypes.NodeWithName; import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.JsonArray; @@ -21,9 +22,10 @@ import org.neo4j.driver.*; import org.neo4j.driver.types.Node; -import java.io.File; -import java.io.IOException; +import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.stream.Collectors; @Slf4j @Data @@ -34,13 +36,18 @@ public class MoneCodeParser { private String NEO4J_USER = "neo4j"; - private String NEO4J_PASSWORD = ""; + private String password = ""; private String embeddingUrl = ""; + public MoneCodeParser setPassword(String password) { + this.password = password; + return this; + } + public void queryEntityClasses() { - try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, NEO4J_PASSWORD)); + try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, password)); Session session = driver.session()) { // 查询 type 为 'entity' 的所有 Class 节点 String query = "MATCH (c:Class {type: 'entity'}) RETURN c"; @@ -61,10 +68,15 @@ public void queryEntityClasses() { } } + //获取session(class) + public Session getSession() { + return GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, password)).session(); + } + //查询所有Comment的信息(使用neo4j),返回是个List(class) public List> getAllComments() { - try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, NEO4J_PASSWORD)); + try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, password)); Session session = driver.session()) { List> comments = new ArrayList<>(); Result result = session.run("MATCH (comment:Comment) RETURN comment, id(comment) as commentId"); @@ -102,7 +114,7 @@ public List> queryCommentsByTextVector(String text) { // 替换为你的查询向量 double[] queryVector = getTextVectorFromHttp(text); - try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, NEO4J_PASSWORD)); + try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, password)); Session session = driver.session()) { // 执行查询 @@ -186,7 +198,7 @@ public void fillCommentTextVectors() { //把Comment的修改,刷新回neo4j(class) public void updateCommentsInNeo4j(List> comments) { - try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, NEO4J_PASSWORD)); + try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, password)); Session session = driver.session()) { for (Map comment : comments) { Long commentId = (Long) comment.get("commentId"); @@ -271,7 +283,7 @@ public static List getJavaFilesInDirectory(String directoryPath) { //删除所有节点(class) public void deleteAllNodes() { - try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, NEO4J_PASSWORD)); + try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, password)); Session session = driver.session()) { session.run("MATCH (n) DETACH DELETE n"); } @@ -288,7 +300,7 @@ private void writeToNeo4j(String filePath) { // 替换成你的 Java 文件路径 String projectName = "MyProject"; - try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, NEO4J_PASSWORD)); + try (Driver driver = GraphDatabase.driver(NEO4J_URI, AuthTokens.basic(NEO4J_USER, password)); Session session = driver.session()) { // 解析 Java 文件 @@ -311,6 +323,31 @@ private static void createProjectNode(Session session, String projectName) { session.run("MERGE (p:Project {name: $name})", projectParams); } + /** + * 查找具有指定注解的类 + * + * @param session 数据库会话 + * @param annotationToFind 要查找的注解 + * @return 具有指定注解的类的列表,每个类以Map形式表示 + */ + public List> findClassesWithAnnotation(Session session, String annotationToFind) { + Map params = new HashMap<>(); + params.put("annotation", annotationToFind); + Result result = session.run( + "MATCH (c:Class) " + + "WHERE ANY(anno IN c.anno WHERE anno = $annotation) " + + "RETURN c", + params + ); + List> list = new ArrayList<>(); + while (result.hasNext()) { + Record record = result.next(); + System.out.println(record.get("c").asMap()); + list.add(record.get("c").asMap()); + } + return list; + } + private static void createFileNode(Session session, String projectName, String filePath) { Map fileParams = new HashMap<>(); @@ -341,6 +378,7 @@ public Visitor(Session session, String projectName, String filePath) { this.filePath = filePath; } + @Override public void visit(ClassOrInterfaceDeclaration n, Void arg) { // 创建 Class/Interface 节点 @@ -360,13 +398,20 @@ public void visit(ClassOrInterfaceDeclaration n, Void arg) { classParams.put("code", code); - System.out.println(classParams); + //获取ClassOrInterfaceDeclaration中的注解 + List annoList = n.getAnnotations().stream().peek(annotation -> { + System.out.println("Annotation: " + annotation.getNameAsString()); + }).map(NodeWithName::getNameAsString).toList(); + //注解 + classParams.put("annotations", annoList); + + System.out.println(classParams); session.run( "MERGE (c:Class {name: $name}) " + - "ON CREATE SET c.full_name = $fullName, c.type = $type, c.code = $code " + - "ON MATCH SET c.full_name = $fullName, c.type = $type, c.code = $code", + "ON CREATE SET c.full_name = $fullName, c.type = $type, c.code = $code, c.anno = $annotations " + + "ON MATCH SET c.full_name = $fullName, c.type = $type, c.code = $code, c.anno = $annotations", classParams ); @@ -394,7 +439,7 @@ public void visit(ClassOrInterfaceDeclaration n, Void arg) { dependsOnParams.put("fieldName", fieldName); - session.run("MERGE (c:Class {name: $name})", ImmutableMap.of("name",fieldType)); + session.run("MERGE (c:Class {name: $name})", ImmutableMap.of("name", fieldType)); session.run("MATCH (c:Class {name: $className}) " + "MATCH (s:Class {name: $serviceName}) " + @@ -405,7 +450,6 @@ public void visit(ClassOrInterfaceDeclaration n, Void arg) { }); - super.visit(n, arg); } @@ -489,5 +533,17 @@ private static String getControllerType(ClassOrInterfaceDeclaration n) { return type; } + //读取resource下某个文件的文本内容(class) + public String readResourceFileContent(String fileName) { + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(fileName); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + return reader.lines().collect(Collectors.joining(System.lineSeparator())); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + } diff --git a/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/MoneCodeParserTest.java b/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/MoneCodeParserTest.java index 057a02e35..64577800a 100644 --- a/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/MoneCodeParserTest.java +++ b/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/MoneCodeParserTest.java @@ -1,7 +1,32 @@ package run.mone.neo4j.test; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; import org.junit.Test; +import org.neo4j.driver.Record; +import org.neo4j.driver.Result; +import org.neo4j.driver.Session; +import org.neo4j.driver.internal.InternalRecord; +import org.neo4j.driver.internal.InternalResult; +import org.neo4j.driver.internal.InternalSession; +import run.mone.neo4j.BotCall; import run.mone.neo4j.MoneCodeParser; +import run.mone.neo4j.test.MoneCodeParserTest; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + /** * @author goodjava@qq.com @@ -10,17 +35,68 @@ public class MoneCodeParserTest { + @Test public void testWriteCatServiceToNeo4j() { // new MoneCodeParser().writeJavaFilesToNeo4j("/Users/zhangzhiyong/IdeaProjects/ai/m78/m78-service/src/main/java/run/mone/m78/service"); // MoneCodeParser.writeJavaFilesToNeo4j("/Users/zhangzhiyong/IdeaProjects/ai/m78/m78-service/src/main/java/run/mone/m78/service/database"); // MoneCodeParser.writeJavaFilesToNeo4j("/Users/zhangzhiyong/IdeaProjects/ai/m78/m78-service/src/main/java/run/mone/m78/service/database/SqlParseUtil.java"); // new MoneCodeParser().writeJavaFilesToNeo4j("/Users/zhangzhiyong/IdeaProjects/goodjava/mone/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/A.java"); - new MoneCodeParser().writeJavaFilesToNeo4j("/Users/zhangzhiyong/IdeaProjects/goodjava/mone/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m"); + new MoneCodeParser().setPassword(System.getenv("password")).writeJavaFilesToNeo4j("/Users/zhangzhiyong/IdeaProjects/goodjava/mone/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m"); } @Test public void test1() { new MoneCodeParser().queryEntityClasses(); } + + + + + @Test + public void testFindClassesWithAnnotation() { + MoneCodeParser moneCodeParser = new MoneCodeParser().setPassword(System.getenv("password")); + List> actual = moneCodeParser.findClassesWithAnnotation(moneCodeParser.getSession(), "Table"); + System.out.println(actual); + +// String xuqiu = "获取狗的主人"; + String xuqiu = "管理宠物鸟"; + String res = BotCall.call(moneCodeParser.readResourceFileContent("entity.md") + xuqiu, new Gson().toJson(actual)); + System.out.println(res); + } + + + + @Test + public void testFindClassesWithAnnotation2() { + MoneCodeParser moneCodeParser = new MoneCodeParser().setPassword(System.getenv("password")); + List> actual = moneCodeParser.findClassesWithAnnotation(moneCodeParser.getSession(), "RestController"); + System.out.println(actual); + + String xuqiu = "获取狗的主人"; +// String xuqiu = "管理宠物鸟"; + String res = BotCall.call(moneCodeParser.readResourceFileContent("service.md") + xuqiu, new Gson().toJson(actual)); + System.out.println(res); + } + + + @Test + public void testJson() { + Map m = ImmutableMap.of("input", "a+b=?"); + System.out.println(new Gson().toJson(m)); + } + + + @Test + public void testReadResourceFileContent() { + String fileName = "entity.md"; + // Assuming the test resource file is already placed in the resources directory + String actualContent = new MoneCodeParser().readResourceFileContent(fileName); + + assertNotNull(actualContent); + } + + + + } diff --git a/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/anno/Service.java b/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/anno/Service.java new file mode 100644 index 000000000..b76563edf --- /dev/null +++ b/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/anno/Service.java @@ -0,0 +1,8 @@ +package run.mone.neo4j.test.anno; + +/** + * @author goodjava@qq.com + * @date 2024/8/21 16:06 + */ +public @interface Service { +} diff --git a/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/CatService.java b/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/CatService.java index 92ed980cb..623cf6578 100644 --- a/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/CatService.java +++ b/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/CatService.java @@ -1,6 +1,7 @@ package run.mone.neo4j.test.m; import run.mone.neo4j.test.anno.RestController; +import run.mone.neo4j.test.anno.Service; import java.util.HashMap; import java.util.Map; @@ -9,7 +10,7 @@ * @author goodjava@qq.com * @date 2024/8/19 18:21 */ -@RestController +@Service public class CatService { private Map data = new HashMap<>(); diff --git a/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/Dog.java b/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/Dog.java index 2811cc06d..4b5dc12c3 100644 --- a/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/Dog.java +++ b/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/Dog.java @@ -8,4 +8,7 @@ */ @Table public class Dog { + + private int id; + } diff --git a/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/PersonService.java b/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/PersonService.java index 65794057e..a94ae0dfa 100644 --- a/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/PersonService.java +++ b/jcommon/ai/neo4j/src/test/java/run/mone/neo4j/test/m/PersonService.java @@ -2,13 +2,13 @@ import run.mone.neo4j.test.anno.Resource; import run.mone.neo4j.test.anno.RestController; +import run.mone.neo4j.test.anno.Service; /** * @author goodjava@qq.com * @date 2024/8/16 10:16 - * AAA */ -@RestController +@Service public class PersonService { diff --git a/jcommon/ai/neo4j/src/test/resources/entity.md b/jcommon/ai/neo4j/src/test/resources/entity.md new file mode 100644 index 000000000..0b8529b60 --- /dev/null +++ b/jcommon/ai/neo4j/src/test/resources/entity.md @@ -0,0 +1,15 @@ +我有这些表映射类,你帮我分析.我给你一个新功能,你看看能不能满足. +不满足的原因: +1.缺少相应的字段 +2.就没有这个类 + +如果不满足,你需要按如下规定返回: +1.缺少字段 satisfies:false reason:missing_fields code:返回缺少字段的代码 (example: private String name;) +2.缺少某个类 satisfies:false reason:missing_class code:返回缺少的类的代码 + +一些规则: +1.缺少字段的时候,尽量不要添加类字段,尽量引用那个类的id即可. +2.如果缺少类,你要帮我尽量补全这个类中缺少的字段. +3.生成的字段或者类尽量添加合适的中文注释 + +需求: \ No newline at end of file diff --git a/jcommon/ai/neo4j/src/test/resources/service.md b/jcommon/ai/neo4j/src/test/resources/service.md new file mode 100644 index 000000000..0670fbd6e --- /dev/null +++ b/jcommon/ai/neo4j/src/test/resources/service.md @@ -0,0 +1,16 @@ +我有这些表映射类和service类的信息,然后我给你一个新功能,你分析下看看能不能满足. + +不满足的原因: +1.缺少相应的方法 +2.缺少某个service类 + +如果不满足,你需要按如下规定返回: +1.缺少字段 satisfies:false reason:missing_methods code:返回缺少方法的代码 (example: private String name;) +2.缺少某个service类 satisfies:false reason:missing_class code:返回缺少的类的代码 + +一些规则: +1.缺少method的时候,生成的方法只需要给方法定义即可. +2.如果缺少类,你要帮我生成这个类,类中的方法也只需要生成接口定义. +3.生成的方法或者类尽量添加合适的中文注释 + +需求: \ No newline at end of file