3 Commits

Author SHA1 Message Date
a7c13bc449 feat: open-ai 2026-01-18 17:59:10 +08:00
24d189f945 feat: rag-git的api 2026-01-18 16:59:11 +08:00
e042e548f9 feat: rag的api 2026-01-17 23:54:47 +08:00
14 changed files with 1802 additions and 29 deletions

4
.gitignore vendored
View File

@@ -35,4 +35,6 @@ build/
.vscode/ .vscode/
### Mac OS ### ### Mac OS ###
.DS_Store .DS_Store
/ai-rag-app/cloned-repo/
/.idea/

View File

@@ -23,4 +23,6 @@ public interface IAiService {
* @return * @return
*/ */
Flux<ChatResponse> generateStream(String model, String message); Flux<ChatResponse> generateStream(String model, String message);
Flux<ChatResponse> generateStreamRag(String model, String ragTag, String message);
} }

View File

@@ -0,0 +1,36 @@
package com.storm.dev.api;
import com.storm.dev.api.response.Response;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;
import java.util.List;
/**
* @author: lyd
* @date: 2026/1/14 23:41
*/
public interface IRAGService {
/**
* 获取标签列表
*
* @return
*/
Response<List<String>> queryRagTagList();
/**
* 上传知识库
*
* @param ragTag
* @param files
* @return
*/
Response<String> uploadFile(String ragTag, List<MultipartFile> files);
ChatResponse generateStreamRag(String model, String ragTag, String message);
Response<String> analyzeGitRepository(String repoUrl, String userName, String token) throws Exception;
}

View File

@@ -0,0 +1,20 @@
package com.storm.dev.api.response;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Response<T> implements Serializable {
private String code;
private String info;
private T data;
}

View File

@@ -24,10 +24,10 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- <dependency>--> <dependency>
<!-- <groupId>org.springframework.ai</groupId>--> <groupId>org.springframework.ai</groupId>
<!-- <artifactId>spring-ai-openai-spring-boot-starter</artifactId>--> <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<!-- </dependency>--> </dependency>
<dependency> <dependency>
<groupId>org.springframework.ai</groupId> <groupId>org.springframework.ai</groupId>

View File

@@ -4,6 +4,8 @@ import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.ai.ollama.OllamaEmbeddingClient; import org.springframework.ai.ollama.OllamaEmbeddingClient;
import org.springframework.ai.ollama.api.OllamaApi; import org.springframework.ai.ollama.api.OllamaApi;
import org.springframework.ai.ollama.api.OllamaOptions; import org.springframework.ai.ollama.api.OllamaOptions;
import org.springframework.ai.openai.OpenAiEmbeddingClient;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.transformer.splitter.TokenTextSplitter; import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.PgVectorStore; import org.springframework.ai.vectorstore.PgVectorStore;
import org.springframework.ai.vectorstore.SimpleVectorStore; import org.springframework.ai.vectorstore.SimpleVectorStore;
@@ -25,6 +27,11 @@ public class OllamaConfig {
return new OllamaApi(baseUrl); return new OllamaApi(baseUrl);
} }
@Bean
public OpenAiApi openAiApi(@Value("${spring.ai.openai.base-url}") String baseUrl, @Value("${spring.ai.openai.api-key}") String apikey) {
return new OpenAiApi(baseUrl, apikey);
}
@Bean @Bean
public OllamaChatClient ollamaChatClient(OllamaApi ollamaApi) { public OllamaChatClient ollamaChatClient(OllamaApi ollamaApi) {
return new OllamaChatClient(ollamaApi); return new OllamaChatClient(ollamaApi);
@@ -36,17 +43,27 @@ public class OllamaConfig {
} }
@Bean @Bean
public SimpleVectorStore simpleVectorStore(OllamaApi ollamaApi) { public SimpleVectorStore vectorStore(@Value("${spring.ai.rag.embed}") String model, OllamaApi ollamaApi, OpenAiApi openAiApi) {
OllamaEmbeddingClient embeddingClient = new OllamaEmbeddingClient(ollamaApi); if ("nomic-embed-text".equalsIgnoreCase(model)) {
embeddingClient.withDefaultOptions(OllamaOptions.create().withModel("nomic-embed-text")); OllamaEmbeddingClient embeddingClient = new OllamaEmbeddingClient(ollamaApi);
return new SimpleVectorStore(embeddingClient); embeddingClient.withDefaultOptions(OllamaOptions.create().withModel("nomic-embed-text"));
return new SimpleVectorStore(embeddingClient);
} else {
OpenAiEmbeddingClient embeddingClient = new OpenAiEmbeddingClient(openAiApi);
return new SimpleVectorStore(embeddingClient);
}
} }
@Bean @Bean
public PgVectorStore pgVectorStore(OllamaApi ollamaApi, JdbcTemplate jdbcTemplate) { public PgVectorStore pgVectorStore(@Value("${spring.ai.rag.embed}") String model, OllamaApi ollamaApi, OpenAiApi openAiApi, JdbcTemplate jdbcTemplate) {
OllamaEmbeddingClient embeddingClient = new OllamaEmbeddingClient(ollamaApi); if ("nomic-embed-text".equalsIgnoreCase(model)) {
embeddingClient.withDefaultOptions(OllamaOptions.create().withModel("nomic-embed-text")); OllamaEmbeddingClient embeddingClient = new OllamaEmbeddingClient(ollamaApi);
return new PgVectorStore(jdbcTemplate, embeddingClient); embeddingClient.withDefaultOptions(OllamaOptions.create().withModel("nomic-embed-text"));
return new PgVectorStore(jdbcTemplate, embeddingClient);
} else {
OpenAiEmbeddingClient embeddingClient = new OpenAiEmbeddingClient(openAiApi);
return new PgVectorStore(jdbcTemplate, embeddingClient);
}
} }

View File

@@ -15,6 +15,12 @@ spring:
options: options:
num-batch: 512 num-batch: 512
model: nomic-embed-text model: nomic-embed-text
openai:
base-url: xxx
api-key: xxx
embedding-model: text-embedding-ada-002
rag:
embed: nomic-embed-text #nomic-embed-text、text-embedding-ada-002
# Redis # Redis
redis: redis:
sdk: sdk:

View File

@@ -0,0 +1,86 @@
package com.storm.dev.text;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.ai.document.Document;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.PgVectorStore;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.PathResource;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
/**
* @author: lyd
* @date: 2026/1/18 14:55
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class GitTest {
@Resource
private OllamaChatClient ollamaChatClient;
@Resource
private TokenTextSplitter tokenTextSplitter;
@Resource
private SimpleVectorStore simpleVectorStore;
@Resource
private PgVectorStore pgVectorStore;
public final String LOCALPATH = "./cloned-repo";
@Test
public void test() throws Exception {
String repoUrl = "https://gitee.com/liyongde/java-trial.git";
String username = "liyongde";
String password = "a1c280a3bfe97eb5a53f7f04a01e7fca";
log.info("克隆路径:" + new File(LOCALPATH).getAbsolutePath());
FileUtils.deleteDirectory(new File(LOCALPATH));
Git git = Git.cloneRepository()
.setURI(repoUrl)
.setDirectory(new File(LOCALPATH))
.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password))
.call();
git.close();
}
@Test
public void test_file() throws IOException {
Files.walkFileTree(Path.of(LOCALPATH), new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
log.info("文件路径:{}", file.toString());
PathResource resource = new PathResource(file);
TikaDocumentReader reader = new TikaDocumentReader(resource);
List<Document> documents = reader.get();
List<Document> documentSplitterList = tokenTextSplitter.apply(documents);
documents.forEach(doc -> doc.getMetadata().put("knowledge", "java-trial"));
documentSplitterList.forEach(doc -> doc.getMetadata().put("knowledge", "java-trial"));
pgVectorStore.accept(documentSplitterList);
return super.visitFile(file, attrs);
}
});
}
}

View File

@@ -21,6 +21,7 @@ import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.SimpleVectorStore; import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import reactor.core.publisher.Flux;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -61,7 +62,7 @@ public class RAGApiTest {
@Test @Test
public void chat() { public void chat() {
// 构建提问 // 构建提问
String message = "李永德,哪年出生的"; String message = "拆装出库的操作流程是什么?";
// 构建推理模板 // 构建推理模板
String SYSTEM_PROMPT = """ String SYSTEM_PROMPT = """
@@ -72,7 +73,7 @@ public class RAGApiTest {
{documents} {documents}
"""; """;
// 读取向量库信息 // 读取向量库信息
SearchRequest request = SearchRequest.query(message).withTopK(5).withFilterExpression("knowledge == '德德'"); SearchRequest request = SearchRequest.query(message).withTopK(5).withFilterExpression("knowledge == '富士迈泰国项目软件方案'");
// 相似性搜索 // 相似性搜索
List<Document> documents = pgVectorStore.similaritySearch(request); List<Document> documents = pgVectorStore.similaritySearch(request);
String documentsCollectors = documents.stream().map(Document::getContent).collect(Collectors.joining()); String documentsCollectors = documents.stream().map(Document::getContent).collect(Collectors.joining());
@@ -84,7 +85,8 @@ public class RAGApiTest {
messages.add(ragMessage); messages.add(ragMessage);
// 提问 // 提问
ChatResponse chatResponse = ollamaChatClient.call(new Prompt(messages, OllamaOptions.create().withModel("deepseek-r1:7b"))); // ChatResponse chatResponse = ollamaChatClient.call(new Prompt(messages, OllamaOptions.create().withModel("deepseek-r1:7b")));
log.info("测试结果:{}", JSON.toJSONString(chatResponse)); Flux<ChatResponse> stream = ollamaChatClient.stream(new Prompt(messages, OllamaOptions.create().withModel("deepseek-r1:7b")));
log.info("测试结果:{}", JSON.toJSONString(stream));
} }
} }

View File

@@ -23,18 +23,18 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<!-- <dependency>--> <dependency>
<!-- <groupId>org.springframework.ai</groupId>--> <groupId>org.springframework.ai</groupId>
<!-- <artifactId>spring-ai-openai-spring-boot-starter</artifactId>--> <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<!-- </dependency>--> </dependency>
<!-- <dependency>--> <dependency>
<!-- <groupId>org.springframework.ai</groupId>--> <groupId>org.springframework.ai</groupId>
<!-- <artifactId>spring-ai-tika-document-reader</artifactId>--> <artifactId>spring-ai-tika-document-reader</artifactId>
<!-- </dependency>--> </dependency>
<!-- <dependency>--> <dependency>
<!-- <groupId>org.springframework.ai</groupId>--> <groupId>org.springframework.ai</groupId>
<!-- <artifactId>spring-ai-pgvector-store</artifactId>--> <artifactId>spring-ai-pgvector-store</artifactId>
<!-- </dependency>--> </dependency>
<dependency> <dependency>
<groupId>org.springframework.ai</groupId> <groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama</artifactId> <artifactId>spring-ai-ollama</artifactId>

View File

@@ -2,17 +2,30 @@ package com.storm.dev.trigger.http;
import com.storm.dev.api.IAiService; import com.storm.dev.api.IAiService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.document.Document;
import org.springframework.ai.ollama.OllamaChatClient; import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.ai.ollama.api.OllamaOptions; import org.springframework.ai.ollama.api.OllamaOptions;
import org.springframework.ai.vectorstore.PgVectorStore;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* @author: lyd * @author: lyd
* @date: 2025/6/7 22:18 * @date: 2025/6/7 22:18
*/ */
@Slf4j
@RestController() @RestController()
@CrossOrigin("*") @CrossOrigin("*")
@RequestMapping("/api/v1/ollama/") @RequestMapping("/api/v1/ollama/")
@@ -20,6 +33,8 @@ public class OllamaController implements IAiService {
@Resource @Resource
private OllamaChatClient chatClient; private OllamaChatClient chatClient;
@Resource
private PgVectorStore pgVectorStore;
/** /**
* http://localhost:8090/api/v1/ollama/generate?model=deepseek-r1:7b&message=1+1 * http://localhost:8090/api/v1/ollama/generate?model=deepseek-r1:7b&message=1+1
@@ -38,4 +53,33 @@ public class OllamaController implements IAiService {
public Flux<ChatResponse> generateStream(@RequestParam String model, @RequestParam String message) { public Flux<ChatResponse> generateStream(@RequestParam String model, @RequestParam String message) {
return chatClient.stream(new Prompt(message, OllamaOptions.create().withModel(model))); return chatClient.stream(new Prompt(message, OllamaOptions.create().withModel(model)));
} }
@Override
@RequestMapping(value = "generate_stream_rag", method = RequestMethod.GET)
public Flux<ChatResponse> generateStreamRag(@RequestParam String model, @RequestParam String ragTag, @RequestParam String message) {
log.info("用户选择模型:{},知识库:{},提问问题:{}", model, ragTag, message);
// 构建推理模板
String SYSTEM_PROMPT = """
Use the information from the DOCUMENTS section to provide accurate answers but act as if you knew this information innately.
If unsure, simply state that you don't know.
Another thing you need to note is that your reply must be in Chinese!
DOCUMENTS:
{documents}
""";
// 读取向量库信息
SearchRequest request = SearchRequest.query(message).withTopK(5).withFilterExpression("knowledge == '" + ragTag + "'");
// 相似性搜索
List<Document> documents = pgVectorStore.similaritySearch(request);
String documentsCollectors = documents.stream().map(Document::getContent).collect(Collectors.joining());
// 推理RAG
Message ragMessage = new SystemPromptTemplate(SYSTEM_PROMPT).createMessage(Map.of("documents", documentsCollectors));
ArrayList<Message> messages = new ArrayList<>();
messages.add(new UserMessage(message));
messages.add(ragMessage);
// 提问
Flux<ChatResponse> chatResponse = chatClient.stream(new Prompt(messages, OllamaOptions.create().withModel(model)));
return chatResponse;
}
} }

View File

@@ -0,0 +1,86 @@
package com.storm.dev.trigger.http;
import com.storm.dev.api.IAiService;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.document.Document;
import org.springframework.ai.openai.OpenAiChatClient;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.vectorstore.PgVectorStore;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author: lyd
* @date: 2026/1/18 17:08
*/
@RestController()
@CrossOrigin("*")
@RequestMapping("/api/v1/openai/")
public class OpenAiController implements IAiService {
@Resource
private OpenAiChatClient chatClient;
@Resource
private PgVectorStore pgVectorStore;
@Override
public ChatResponse generate(String model, String message) {
return chatClient.call(new Prompt(message, OpenAiChatOptions.builder().withModel(model).build()));
}
@Override
public Flux<ChatResponse> generateStream(String model, String message) {
return chatClient.stream(new Prompt(
message,
OpenAiChatOptions.builder()
.withModel(model)
.build()
));
}
@Override
public Flux<ChatResponse> generateStreamRag(String model, String ragTag, String message) {
String SYSTEM_PROMPT = """
Use the information from the DOCUMENTS section to provide accurate answers but act as if you knew this information innately.
If unsure, simply state that you don't know.
Another thing you need to note is that your reply must be in Chinese!
DOCUMENTS:
{documents}
""";
// 指定文档搜索
SearchRequest request = SearchRequest.query(message)
.withTopK(5)
.withFilterExpression("knowledge == '" + ragTag + "'");
List<Document> documents = pgVectorStore.similaritySearch(request);
String documentCollectors = documents.stream().map(Document::getContent).collect(Collectors.joining());
Message ragMessage = new SystemPromptTemplate(SYSTEM_PROMPT).createMessage(Map.of("documents", documentCollectors));
List<Message> messages = new ArrayList<>();
messages.add(new UserMessage(message));
messages.add(ragMessage);
return chatClient.stream(new Prompt(
messages,
OpenAiChatOptions.builder()
.withModel(model)
.build()
));
}
}

View File

@@ -0,0 +1,187 @@
package com.storm.dev.trigger.http;
import com.alibaba.fastjson.JSON;
import com.storm.dev.api.IRAGService;
import com.storm.dev.api.response.Response;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.document.Document;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.ai.ollama.api.OllamaOptions;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.PgVectorStore;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.core.io.PathResource;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author: lyd
* @date: 2026/1/14 23:43
*/
@Slf4j
@RestController()
@CrossOrigin("*")
@RequestMapping("/api/v1/rag/")
public class RAGController implements IRAGService {
@Resource
private RedissonClient redissonClient;
@Resource
private OllamaChatClient ollamaChatClient;
@Resource
private TokenTextSplitter tokenTextSplitter;
@Resource
private SimpleVectorStore simpleVectorStore;
@Resource
private PgVectorStore pgVectorStore;
@Override
@RequestMapping(value = "query_rag_tag_list", method = RequestMethod.GET)
public Response<List<String>> queryRagTagList() {
RList<String> ragTag = redissonClient.getList("ragTag");
return Response.<List<String>>builder()
.code("0000")
.info("调用成功")
.data(ragTag)
.build();
}
@Override
@RequestMapping(value = "file/upload", method = RequestMethod.POST, headers = "content-type=multipart/form-data")
public Response<String> uploadFile(@RequestParam String ragTag, @RequestParam("file") List<MultipartFile> files) {
log.info("上传知识库开始 {}", ragTag);
for (MultipartFile file : files) {
// 上传
TikaDocumentReader reader = new TikaDocumentReader(file.getResource());
List<Document> documents = reader.get();
List<Document> documentSplitterList = tokenTextSplitter.apply(documents);
// 打标
documents.forEach(document -> document.getMetadata().put("knowledge", ragTag));
documentSplitterList.forEach(document -> document.getMetadata().put("knowledge", ragTag));
pgVectorStore.accept(documentSplitterList);
// 可以用MySQL存储
RList<String> elements = redissonClient.getList("ragTag");
if (!elements.contains(ragTag)){
elements.add(ragTag);
}
log.info("上传完成!");
}
return Response.<String>builder().code("0000").info("调用成功").build();
}
@Override
@RequestMapping(value = "generate_stream_rag", method = RequestMethod.GET)
public ChatResponse generateStreamRag(@RequestParam String model, @RequestParam String ragTag, @RequestParam String message) {
log.info("用户选择模型:{},知识库:{},提问问题:{}", model, ragTag, message);
// 构建推理模板
String SYSTEM_PROMPT = """
Use the information from the DOCUMENTS section to provide accurate answers but act as if you knew this information innately.
If unsure, simply state that you don't know.
Another thing you need to note is that your reply must be in Chinese!
DOCUMENTS:
{documents}
""";
// 读取向量库信息
SearchRequest request = SearchRequest.query(message).withTopK(5).withFilterExpression("knowledge == '" + ragTag + "'");
// 相似性搜索
List<Document> documents = pgVectorStore.similaritySearch(request);
String documentsCollectors = documents.stream().map(Document::getContent).collect(Collectors.joining());
// 推理RAG
Message ragMessage = new SystemPromptTemplate(SYSTEM_PROMPT).createMessage(Map.of("documents", documentsCollectors));
ArrayList<Message> messages = new ArrayList<>();
messages.add(new UserMessage(message));
messages.add(ragMessage);
// 提问
// Flux<ChatResponse> chatResponse = ollamaChatClient.stream(new Prompt(messages, OllamaOptions.create().withModel(model)));
ChatResponse call = ollamaChatClient.call(new Prompt(messages, OllamaOptions.create().withModel(model)));
log.info("测试结果:{}", call);
return call;
}
@RequestMapping(value = "analyze_git_repository", method = RequestMethod.POST)
@Override
public Response<String> analyzeGitRepository(@RequestParam String repoUrl, @RequestParam String userName, @RequestParam String token) throws Exception {
String localPath = "./git-cloned-repo";
String repoProjectName = extractProjectName(repoUrl);
log.info("克隆路径:{}", new File(localPath).getAbsolutePath());
FileUtils.deleteDirectory(new File(localPath));
Git git = Git.cloneRepository()
.setURI(repoUrl)
.setDirectory(new File(localPath))
.setCredentialsProvider(new UsernamePasswordCredentialsProvider(userName, token))
.call();
Files.walkFileTree(Paths.get(localPath), new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
log.info("{} 遍历解析路径,上传知识库:{}", repoProjectName, file.getFileName());
try {
TikaDocumentReader reader = new TikaDocumentReader(new PathResource(file));
List<Document> documents = reader.get();
List<Document> documentSplitterList = tokenTextSplitter.apply(documents);
documents.forEach(doc -> doc.getMetadata().put("knowledge", repoProjectName));
documentSplitterList.forEach(doc -> doc.getMetadata().put("knowledge", repoProjectName));
pgVectorStore.accept(documentSplitterList);
} catch (Exception e) {
log.error("遍历解析路径,上传知识库失败:{}", file.getFileName());
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
log.info("Failed to access file: {} - {}", file.toString(), exc.getMessage());
return FileVisitResult.CONTINUE;
}
});
FileUtils.deleteDirectory(new File(localPath));
RList<String> elements = redissonClient.getList("ragTag");
if (!elements.contains(repoProjectName)) {
elements.add(repoProjectName);
}
git.close();
log.info("遍历解析路径,上传完成:{}", repoUrl);
return Response.<String>builder().code("0000").info("调用成功").build();
}
private String extractProjectName(String repoUrl) {
String[] parts = repoUrl.split("/");
String projectNameWithGit = parts[parts.length - 1];
return projectNameWithGit.replace(".git", "");
}
}

1285
docs/nginx/html/rag-ai.html Normal file

File diff suppressed because it is too large Load Diff