feat: 完善后端知识库服务和配置
- 优化 AI-Core 客户端调用 - 添加更多知识库配置选项 - 完善文档解析逻辑 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -29,9 +29,10 @@ type KnowledgeService struct {
|
||||
uploadService *UploadService
|
||||
pythonServiceURL string
|
||||
aiCoreClient *AICoreClient
|
||||
markdownLocalPath string // Markdown 本地存储路径
|
||||
}
|
||||
|
||||
func NewKnowledgeService(repo *repository.KnowledgeRepository, modelRepo *repository.ModelRepository, uploadService *UploadService, pythonServiceURL, aiCoreServiceAddr string) *KnowledgeService {
|
||||
func NewKnowledgeService(repo *repository.KnowledgeRepository, modelRepo *repository.ModelRepository, uploadService *UploadService, pythonServiceURL, aiCoreServiceAddr, markdownLocalPath string) *KnowledgeService {
|
||||
aiCoreClient, _ := NewAICoreClient(aiCoreServiceAddr)
|
||||
return &KnowledgeService{
|
||||
repo: repo,
|
||||
@@ -39,6 +40,7 @@ func NewKnowledgeService(repo *repository.KnowledgeRepository, modelRepo *reposi
|
||||
uploadService: uploadService,
|
||||
pythonServiceURL: pythonServiceURL,
|
||||
aiCoreClient: aiCoreClient,
|
||||
markdownLocalPath: markdownLocalPath,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,6 +309,13 @@ func (s *KnowledgeService) parseDocumentWithAICore(docID, fileURL, fileName stri
|
||||
|
||||
if result.Success && result.Content != "" {
|
||||
knowledgeDebugLog.Printf("[AICore] 解析成功: docID=%s, contentLength=%d", docID, len(result.Content))
|
||||
|
||||
// 保存到本地文件
|
||||
markdownPath := s.saveMarkdownToFile(docID, fileName, result.Content)
|
||||
if markdownPath != "" {
|
||||
knowledgeDebugLog.Printf("[AICore] Markdown 保存到本地: docID=%s, path=%s", docID, markdownPath)
|
||||
}
|
||||
|
||||
// 更新文档的 Content 字段
|
||||
s.repo.UpdateDocument(docID, map[string]interface{}{
|
||||
"content": result.Content,
|
||||
@@ -316,6 +325,31 @@ func (s *KnowledgeService) parseDocumentWithAICore(docID, fileURL, fileName stri
|
||||
}
|
||||
}
|
||||
|
||||
// saveMarkdownToFile 保存 Markdown 内容到本地文件
|
||||
func (s *KnowledgeService) saveMarkdownToFile(docID, fileName, content string) string {
|
||||
if s.markdownLocalPath == "" {
|
||||
s.markdownLocalPath = "resource/markdown"
|
||||
}
|
||||
|
||||
// 创建目录
|
||||
if err := os.MkdirAll(s.markdownLocalPath, 0755); err != nil {
|
||||
knowledgeDebugLog.Printf("[AICore] 创建目录失败: path=%s, err=%v", s.markdownLocalPath, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
// 生成文件名(用 docID + .md)
|
||||
markdownFileName := docID + ".md"
|
||||
markdownPath := s.markdownLocalPath + "/" + markdownFileName
|
||||
|
||||
// 写入文件
|
||||
if err := os.WriteFile(markdownPath, []byte(content), 0644); err != nil {
|
||||
knowledgeDebugLog.Printf("[AICore] 保存 Markdown 失败: path=%s, err=%v", markdownPath, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
return markdownPath
|
||||
}
|
||||
|
||||
// DeleteDocument 删除文档
|
||||
func (s *KnowledgeService) DeleteDocument(kbID, docID string) error {
|
||||
// 验证文档存在
|
||||
@@ -400,24 +434,66 @@ func (s *KnowledgeService) GetDocumentPreview(kbID, docID string, page int) (*mo
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 如果已解析,返回解析内容;否则返回文件 URL
|
||||
if doc.Status == "parsed" {
|
||||
// TODO: 从存储中读取解析内容(可以存到数据库或文件)
|
||||
// 暂时返回文件 URL
|
||||
fileURL, _ := s.uploadService.GetFileURL(doc.FileKey)
|
||||
// 获取文件URL
|
||||
fileURL, _ := s.uploadService.GetFileURL(doc.FileKey)
|
||||
|
||||
// 根据文件类型决定预览方式
|
||||
fileName := doc.Name
|
||||
isPDF := strings.HasSuffix(strings.ToLower(fileName), ".pdf")
|
||||
isOffice := false
|
||||
officeExts := []string{".csv", ".xlsx", ".xls", ".docx", ".doc", ".pptx", ".ppt", ".txt", ".md"}
|
||||
for _, ext := range officeExts {
|
||||
if strings.HasSuffix(strings.ToLower(fileName), ext) {
|
||||
isOffice = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// PDF文件返回文件URL
|
||||
if isPDF {
|
||||
return &model.DocumentPreviewResponse{
|
||||
TotalPages: 1,
|
||||
CurrentPage: page,
|
||||
Content: fileURL,
|
||||
ContentType: "url",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 未解析,返回文件 URL
|
||||
fileURL, _ := s.uploadService.GetFileURL(doc.FileKey)
|
||||
// Office文件调用解析服务转换为HTML
|
||||
if isOffice && s.aiCoreClient != nil {
|
||||
knowledgeDebugLog.Printf("[Preview] Parsing office file: %s, URL: %s", fileName, fileURL)
|
||||
result, err := s.aiCoreClient.ParseDocument(fileURL, fileName, "")
|
||||
if err != nil {
|
||||
// 解析失败,返回文件URL
|
||||
knowledgeDebugLog.Printf("[Preview] Parse document failed: %v", err)
|
||||
return &model.DocumentPreviewResponse{
|
||||
TotalPages: 1,
|
||||
CurrentPage: page,
|
||||
Content: fileURL,
|
||||
ContentType: "url",
|
||||
}, nil
|
||||
}
|
||||
|
||||
knowledgeDebugLog.Printf("[Preview] Parse result: success=%v, content_length=%d", result.Success, len(result.Content))
|
||||
|
||||
// 返回HTML内容
|
||||
if result.Success && result.Content != "" {
|
||||
knowledgeDebugLog.Printf("[Preview] Returning HTML content, length: %d", len(result.Content))
|
||||
return &model.DocumentPreviewResponse{
|
||||
TotalPages: 1,
|
||||
CurrentPage: page,
|
||||
Content: result.Content,
|
||||
ContentType: "html",
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 其他情况返回文件URL
|
||||
return &model.DocumentPreviewResponse{
|
||||
TotalPages: 1,
|
||||
CurrentPage: page,
|
||||
Content: fileURL,
|
||||
ContentType: "url",
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user