自定义GitHub仓库文档读取器
一向不喜欢废话,摸索两小时,干货奉上,希望大家点点赞
一、引入依赖
▼xml复制代码<!-- GitHub API --> <dependency> <groupId>org.kohsuke</groupId> <artifactId>github-api</artifactId> <version>1.318</version> </dependency>
二、具体实现
▼java复制代码/** * @version v1.0.0 * @belongsProject: feng-ai-agent * @belongsPackage: com.qcdfz.fengaiagent.rag * @author: fgh * @description: GitHub文档加载器 用于加载GitHub仓库中的文档内容 * @createTime: 2025-05-12 16:53 */ @Slf4j public class GitHubDocumentLoader { private final GitHub gitHub; private final String owner; private final String repo; private final String branch; /** * 构造函数 * * @param gitHub GitHub客户端实例 * @param owner 仓库所有者 * @param repo 仓库名称 * @param branch 分支名称 */ public GitHubDocumentLoader(GitHub gitHub, String owner, String repo, String branch) { Assert.notNull(gitHub, "GitHub实例不能为空"); Assert.notNull(owner, "仓库所有者不能为空"); Assert.notNull(repo, "仓库名称不能为空"); this.gitHub = gitHub; this.owner = owner; this.repo = repo; this.branch = branch != null ? branch : "main"; } /** * 加载单个文件内容 * * @param path 文件路径 * @return Document对象 */ public Document loadDocument(String path) { try { GHContent content = getRepository().getFileContent(path, branch); Assert.isTrue(content.isFile(), "路径必须指向文件"); return createDocument(content); } catch (IOException e) { log.error("从GitHub加载文档失败: {}", path, e); throw new RuntimeException("从GitHub加载文档失败: " + path, e); } } /** * 加载目录下的所有文件 * * @param path 目录路径 * @return Document列表 */ public List<Document> loadDocuments(String path) { List<Document> documents = new ArrayList<>(); try { List<GHContent> contents = getRepository().getDirectoryContent(path, branch); for (GHContent content : contents) { if (content.isFile()) { documents.add(createDocument(content)); } else if (content.isDirectory()) { documents.addAll(loadDocuments(content.getPath())); } } } catch (IOException e) { log.error("从GitHub加载文档失败: {}", path, e); throw new RuntimeException("从GitHub加载文档失败: " + path, e); } return documents; } /** * 获取仓库信息 * * @return 仓库信息Map */ public Map<String, Object> getRepositoryInfo() { try { GHRepository repository = getRepository(); return Map.of( "name", Objects.toString(repository.getName(), ""), "description", Objects.toString(repository.getDescription(), ""), "stars", repository.getStargazersCount(), "forks", repository.getForksCount(), "language", Objects.toString(repository.getLanguage(), ""), "defaultBranch", Objects.toString(repository.getDefaultBranch(), ""), "htmlUrl", repository.getHtmlUrl() != null ? repository.getHtmlUrl().toString() : "", "cloneUrl", Objects.toString(repository.getHttpTransportUrl(), "") ); } catch (IOException e) { log.error("获取仓库信息失败: {}/{}", owner, repo, e); throw new RuntimeException("获取仓库信息失败: " + owner + "/" + repo, e); } } /** * 获取仓库对象 * * @return GHRepository对象 * @throws IOException 如果获取失败 */ private GHRepository getRepository() throws IOException { return gitHub.getRepository(owner + "/" + repo); } /** * 创建Document对象 * * @param content GitHub内容对象 * @return Document对象 * @throws IOException 如果读取失败 */ private Document createDocument(GHContent content) throws IOException { String text = content.getContent(); Map<String, Object> metadata = Map.of( "github_git_url", content.getGitUrl(), "github_download_url", content.getDownloadUrl(), "github_html_url", content.getHtmlUrl(), "github_url", content.getUrl(), "github_file_name", content.getName(), "github_file_path", content.getPath(), "github_file_sha", content.getSha(), "github_file_size", Long.toString(content.getSize()), "github_file_encoding", content.getEncoding() ); return new Document(text, metadata); } /** * 创建Builder实例 * * @return Builder实例 */ public static Builder builder() { return new Builder(); } /** * 构建器类 */ public static class Builder { private GitHub gitHub; private String owner; private String repo; private String branch; /** * 设置GitHub客户端实例 * * @param gitHub GitHub客户端实例 * @return Builder实例 */ public Builder gitHub(GitHub gitHub) { this.gitHub = gitHub; return this; } /** * 设置仓库所有者 * * @param owner 仓库所有者 * @return Builder实例 */ public Builder owner(String owner) { this.owner = owner; return this; } /** * 设置仓库名称 * * @param repo 仓库名称 * @return Builder实例 */ public Builder repo(String repo) { this.repo = repo; return this; } /** * 设置分支名称 * * @param branch 分支名称 * @return Builder实例 */ public Builder branch(String branch) { this.branch = branch; return this; } /** * 构建GitHubDocumentLoader实例 * * @return GitHubDocumentLoader实例 */ public GitHubDocumentLoader build() { return new GitHubDocumentLoader(gitHub, owner, repo, branch); } } }
这个是仿照SpringAi官方的DocumentReader的Builder构造器实现的,但是我并没有去实现他的DocumentReader接口,这里只是一个例子,需要其他增强,自己实现即可
三、使用方法
▼java复制代码@SpringBootTest class GitHubDocumentLoaderTest { @Test public void test() throws IOException { String token = GlobalApiKey.GITHUB_TOKEN; // 推荐用GitHubBuilder GitHub github = new GitHubBuilder().withOAuthToken(token).build(); GitHubDocumentLoader loader = GitHubDocumentLoader.builder() .gitHub(github) .owner("fenghuanghuai") .repo("hell-world") .branch("main") .build(); // 读取文件 下面有实现效果 Document doc = loader.loadDocument("/test/test.md"); // 读取目录 下面有实现效果 List<Document> docs = loader.loadDocuments("/"); // 获取仓库信息 下面有实现效果 Map<String, Object> repoInfo = loader.getRepositoryInfo(); Assertions.assertNotNull(repoInfo); } }
这个是我的仓库内容
下面是读取结果


评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
作者分享
llm-wiki:把 AI 会话沉淀成可长期复用的本地知识库
7
我做了一个 AI Token Dashboard:把 Claude Code、Codex、Gemini 等 AI 工具的 Token 消耗统一看清楚
13
最近公司一直在推进AI的产品落地,我负责了一块有关于数据查询AI化的部分,大致能力就是,
实现用自然语言转换成sql进行查询,得到数据,返回给用户。我找了网上很多的资料,都是介绍
用对应的mcp和插件来实现,不能满足当前需求,因为这个能力是需要单独部署成mcp工具,给很
多部门做数据分析用。所以想请教大家有没有帖子或资源,是使用代码实现的。语言java和python都可。
3
error installing 14.21.3: open C:\Users\qcdfz\AppData\Local\Temp\nvm-npm-1073152608\npm-v6.14.18.zip
2
超级AI智能体完结篇
9
