fix(knowledge): 修复 readDocument 文件路径拼接问题
## 问题
L1 语义检索返回文档后,尝试读取文档内容时报错:
```
读取文档失败: api/payment-errors.md
java.nio.file.NoSuchFileException: api\payment-errors.md
```
**原因**:
- `KnowledgeEntry.filePath` 存储的是相对路径(如 `api/payment-errors.md`)
- `readDocument()` 方法直接使用相对路径读取,未拼接 `knowledge_base` 前缀
- 导致找不到文件
## 修复内容
### 1. 添加 knowledge.base-path 配置
```java
@Value("${knowledge.base-path:knowledge_base}")
private String knowledgeBasePath;
```
**默认值**:`knowledge_base`(当前工作目录下)
### 2. 修复 readDocument 方法
```java
public String readDocument(String filePath, int maxChars) {
// 拼接完整路径:knowledge_base + 相对路径
Path fullPath = Paths.get(knowledgeBasePath, filePath);
String content = Files.readString(fullPath);
// ...
}
```
**修复前**:
```
读取: api/payment-errors.md
实际路径: <当前目录>/api/payment-errors.md ❌
```
**修复后**:
```
读取: api/payment-errors.md
实际路径: knowledge_base/api/payment-errors.md ✅
```
## 数据流
```
L1 语义检索
↓
返回 KnowledgeEntry
filePath = "api/payment-errors.md"
↓
readDocument("api/payment-errors.md", 2000)
↓
拼接路径: Paths.get("knowledge_base", "api/payment-errors.md")
↓
完整路径: "knowledge_base/api/payment-errors.md"
↓
Files.readString(fullPath)
↓
返回文档内容 ✅
```
## 配置
在 `application.yml` 中可以自定义路径:
```yaml
knowledge:
base-path: ./knowledge_base # 默认值
```
或者绝对路径:
```yaml
knowledge:
base-path: /data/knowledge_base
```
## 验证
```bash
# 1. 启动应用
mvn spring-boot:run
# 2. 提问触发 L1
你:支付为什么会失败?
# 3. Agent 应该:
# - lookup_knowledge("支付为什么会失败")
# - L0 失败 → L1 语义检索
# - 找到 api/payment-errors.md
# - 读取文件内容成功 ✅
# - 返回文档内容给用户
```
## 相关代码路径
- `KnowledgeIndexService.readDocument()` - 文件读取
- `KnowledgeEntry.filePath` - 存储相对路径
- `LookupKnowledgeTool` - 调用 readDocument
This commit is contained in:
@@ -29,6 +29,9 @@ import java.util.stream.Stream;
|
|||||||
@Service
|
@Service
|
||||||
public class KnowledgeIndexService {
|
public class KnowledgeIndexService {
|
||||||
|
|
||||||
|
@Value("${knowledge.base-path:knowledge_base}")
|
||||||
|
private String knowledgeBasePath;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ApiDocumentRepository apiDocumentRepository;
|
private ApiDocumentRepository apiDocumentRepository;
|
||||||
|
|
||||||
@@ -195,13 +198,15 @@ public class KnowledgeIndexService {
|
|||||||
/**
|
/**
|
||||||
* 读取文档内容
|
* 读取文档内容
|
||||||
*
|
*
|
||||||
* @param filePath 文件路径
|
* @param filePath 文件相对路径(如 api/payment-errors.md)
|
||||||
* @param maxChars 最大字符数
|
* @param maxChars 最大字符数
|
||||||
* @return 文档内容(前 maxChars 字符),失败返回 null
|
* @return 文档内容(前 maxChars 字符),失败返回 null
|
||||||
*/
|
*/
|
||||||
public String readDocument(String filePath, int maxChars) {
|
public String readDocument(String filePath, int maxChars) {
|
||||||
try {
|
try {
|
||||||
String content = Files.readString(Paths.get(filePath));
|
// 拼接完整路径:knowledge_base + 相对路径
|
||||||
|
Path fullPath = Paths.get(knowledgeBasePath, filePath);
|
||||||
|
String content = Files.readString(fullPath);
|
||||||
|
|
||||||
if (content.length() > maxChars) {
|
if (content.length() > maxChars) {
|
||||||
return content.substring(0, maxChars) + "...";
|
return content.substring(0, maxChars) + "...";
|
||||||
@@ -210,7 +215,7 @@ public class KnowledgeIndexService {
|
|||||||
return content;
|
return content;
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("读取文档失败: {}", filePath, e);
|
log.error("读取文档失败: {}/{}", knowledgeBasePath, filePath, e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class ApiDocumentRepositoryTest {
|
|||||||
.filePath("/uploads/api-spec.md")
|
.filePath("/uploads/api-spec.md")
|
||||||
.fileHash("abc123hash")
|
.fileHash("abc123hash")
|
||||||
.fileSize(1024L)
|
.fileSize(1024L)
|
||||||
.faultCategory(FaultCategory.EXTERNAL_API)
|
.faultCategory(FaultCategory.API)
|
||||||
.faultSource("广东")
|
.faultSource("广东")
|
||||||
.apiName("查询接口")
|
.apiName("查询接口")
|
||||||
.status("PENDING")
|
.status("PENDING")
|
||||||
@@ -167,7 +167,7 @@ class ApiDocumentRepositoryTest {
|
|||||||
.docId(UUID.randomUUID().toString())
|
.docId(UUID.randomUUID().toString())
|
||||||
.fileName("guangdong-api.md")
|
.fileName("guangdong-api.md")
|
||||||
.faultSource("广东")
|
.faultSource("广东")
|
||||||
.faultCategory(FaultCategory.EXTERNAL_API)
|
.faultCategory(FaultCategory.API)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
repository.save(doc);
|
repository.save(doc);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class DiagnosisRecordRepositoryTest {
|
|||||||
.sessionId("session-001")
|
.sessionId("session-001")
|
||||||
.businessId("order-12345")
|
.businessId("order-12345")
|
||||||
.traceId("trace-abc123")
|
.traceId("trace-abc123")
|
||||||
.faultCategory(FaultCategory.EXTERNAL_API)
|
.faultCategory(FaultCategory.API)
|
||||||
.faultSource("广东")
|
.faultSource("广东")
|
||||||
.faultTarget("http://api.example.com/query")
|
.faultTarget("http://api.example.com/query")
|
||||||
.errorCode("40003")
|
.errorCode("40003")
|
||||||
|
|||||||
Reference in New Issue
Block a user