feat: 集成 AI-Core gRPC 文档解析服务
- 新增 AICoreClient 客户端 - 添加 document_parser_client.go - 知识库服务集成 AI-Core 解析 - 配置中添加 ai_core_service_addr Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,7 +87,7 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Warning: Failed to initialize upload service: %v (files will not be available)", err)
|
log.Printf("Warning: Failed to initialize upload service: %v (files will not be available)", err)
|
||||||
}
|
}
|
||||||
knowledgeService := service.NewKnowledgeService(knowledgeRepo, modelRepo, uploadService, cfg.PythonServiceURL)
|
knowledgeService := service.NewKnowledgeService(knowledgeRepo, modelRepo, uploadService, cfg.PythonServiceURL, cfg.AICoreServiceAddr)
|
||||||
|
|
||||||
// 6. 初始化 Handler
|
// 6. 初始化 Handler
|
||||||
dbHandler := handler.NewDatabaseHandler(dbService)
|
dbHandler := handler.NewDatabaseHandler(dbService)
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
# 本地开发配置
|
# 本地开发配置
|
||||||
port: "8082"
|
port: "8082"
|
||||||
jwt_secret: "dev-secret-key"
|
jwt_secret: "dev-secret-key"
|
||||||
# Docker 内访问用 db:3306,本地访问用 localhost:6036
|
|
||||||
database_url: "root:root@tcp(localhost:6036)/x_agents?charset=utf8mb4&parseTime=True&loc=Local"
|
# 数据库配置
|
||||||
|
database_host: "localhost"
|
||||||
|
database_port: "6036"
|
||||||
|
database_user: "root"
|
||||||
|
database_password: "root"
|
||||||
|
database_name: "x_agents"
|
||||||
|
|
||||||
|
# AI 服务配置
|
||||||
python_service_url: "http://localhost:8081"
|
python_service_url: "http://localhost:8081"
|
||||||
|
ai_core_service_addr: "localhost:50051"
|
||||||
|
|
||||||
# 文件上传配置 (local 或 minio)
|
# 文件上传配置 (local 或 minio)
|
||||||
upload_mode: "local"
|
upload_mode: "local"
|
||||||
|
|||||||
@@ -70,7 +70,9 @@ require (
|
|||||||
golang.org/x/net v0.48.0 // indirect
|
golang.org/x/net v0.48.0 // indirect
|
||||||
golang.org/x/sys v0.39.0 // indirect
|
golang.org/x/sys v0.39.0 // indirect
|
||||||
golang.org/x/text v0.32.0 // indirect
|
golang.org/x/text v0.32.0 // indirect
|
||||||
google.golang.org/protobuf v1.31.0 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||||
|
google.golang.org/grpc v1.79.2 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.10 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
@@ -185,9 +186,16 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|||||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||||
|
google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
|
||||||
|
google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||||
|
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
@@ -14,8 +14,14 @@ import (
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
Port string
|
Port string
|
||||||
JWTSecret string
|
JWTSecret string
|
||||||
DatabaseURL string
|
DatabaseHost string
|
||||||
|
DatabasePort string
|
||||||
|
DatabaseUser string
|
||||||
|
DatabasePassword string
|
||||||
|
DatabaseName string
|
||||||
|
DatabaseURL string // 拼接后的完整连接字符串
|
||||||
PythonServiceURL string
|
PythonServiceURL string
|
||||||
|
AICoreServiceAddr string // AI-Core gRPC 服务地址,如 "localhost:50051"
|
||||||
// 文件上传配置
|
// 文件上传配置
|
||||||
UploadMode string // "local" 或 "minio"
|
UploadMode string // "local" 或 "minio"
|
||||||
UploadLocalPath string // 本地存储路径,如 "resource/files"
|
UploadLocalPath string // 本地存储路径,如 "resource/files"
|
||||||
@@ -39,7 +45,13 @@ func Load() *Config {
|
|||||||
viper.SetDefault("port", "8080")
|
viper.SetDefault("port", "8080")
|
||||||
viper.SetDefault("jwt_secret", "your-secret-key-change-in-production")
|
viper.SetDefault("jwt_secret", "your-secret-key-change-in-production")
|
||||||
viper.SetDefault("python_service_url", "http://localhost:8081")
|
viper.SetDefault("python_service_url", "http://localhost:8081")
|
||||||
viper.SetDefault("database_url", "root:root@tcp(localhost:3306)/x_agents?charset=utf8mb4&parseTime=True&loc=Local")
|
viper.SetDefault("ai_core_service_addr", "localhost:50051")
|
||||||
|
// 数据库默认配置
|
||||||
|
viper.SetDefault("database_host", "localhost")
|
||||||
|
viper.SetDefault("database_port", "3306")
|
||||||
|
viper.SetDefault("database_user", "root")
|
||||||
|
viper.SetDefault("database_password", "root")
|
||||||
|
viper.SetDefault("database_name", "x_agents")
|
||||||
// 文件上传默认配置
|
// 文件上传默认配置
|
||||||
viper.SetDefault("upload_mode", "local")
|
viper.SetDefault("upload_mode", "local")
|
||||||
viper.SetDefault("upload_local_path", "resource/files")
|
viper.SetDefault("upload_local_path", "resource/files")
|
||||||
@@ -54,11 +66,26 @@ func Load() *Config {
|
|||||||
log.Printf("Using default config: %v", err)
|
log.Printf("Using default config: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 拼接数据库连接字符串
|
||||||
|
dbHost := viper.GetString("database_host")
|
||||||
|
dbPort := viper.GetString("database_port")
|
||||||
|
dbUser := viper.GetString("database_user")
|
||||||
|
dbPassword := viper.GetString("database_password")
|
||||||
|
dbName := viper.GetString("database_name")
|
||||||
|
databaseURL := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
||||||
|
dbUser, dbPassword, dbHost, dbPort, dbName)
|
||||||
|
|
||||||
return &Config{
|
return &Config{
|
||||||
Port: viper.GetString("port"),
|
Port: viper.GetString("port"),
|
||||||
JWTSecret: viper.GetString("jwt_secret"),
|
JWTSecret: viper.GetString("jwt_secret"),
|
||||||
DatabaseURL: viper.GetString("database_url"),
|
DatabaseURL: databaseURL,
|
||||||
|
DatabaseHost: dbHost,
|
||||||
|
DatabasePort: dbPort,
|
||||||
|
DatabaseUser: dbUser,
|
||||||
|
DatabasePassword: dbPassword,
|
||||||
|
DatabaseName: dbName,
|
||||||
PythonServiceURL: viper.GetString("python_service_url"),
|
PythonServiceURL: viper.GetString("python_service_url"),
|
||||||
|
AICoreServiceAddr: viper.GetString("ai_core_service_addr"),
|
||||||
// 文件上传配置
|
// 文件上传配置
|
||||||
UploadMode: viper.GetString("upload_mode"),
|
UploadMode: viper.GetString("upload_mode"),
|
||||||
UploadLocalPath: viper.GetString("upload_local_path"),
|
UploadLocalPath: viper.GetString("upload_local_path"),
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ type KnowledgeDocument struct {
|
|||||||
FileKey string `json:"file_key" gorm:"type:varchar(500)"`
|
FileKey string `json:"file_key" gorm:"type:varchar(500)"`
|
||||||
FileURL string `json:"file_url" gorm:"type:varchar(500)"` // 文件访问 URL
|
FileURL string `json:"file_url" gorm:"type:varchar(500)"` // 文件访问 URL
|
||||||
FileSize int64 `json:"file_size" gorm:"type:bigint;default:0"`
|
FileSize int64 `json:"file_size" gorm:"type:bigint;default:0"`
|
||||||
|
Content string `json:"content" gorm:"type:longtext"` // Markdown 内容(AI-Core 解析结果)
|
||||||
Status string `json:"status" gorm:"type:varchar(20);default:parsing"` // parsing / parsed / failed
|
Status string `json:"status" gorm:"type:varchar(20);default:parsing"` // parsing / parsed / failed
|
||||||
ChunkCount int `json:"chunk_count" gorm:"default:0"`
|
ChunkCount int `json:"chunk_count" gorm:"default:0"`
|
||||||
UploadedAt time.Time `json:"uploaded_at"`
|
UploadedAt time.Time `json:"uploaded_at"`
|
||||||
|
|||||||
132
server/internal/service/document_parser_client.go
Normal file
132
server/internal/service/document_parser_client.go
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AICoreClient AI-Core 文档解析服务客户端
|
||||||
|
type AICoreClient struct {
|
||||||
|
conn *grpc.ClientConn
|
||||||
|
address string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseResult 解析结果
|
||||||
|
type ParseResult struct {
|
||||||
|
Success bool
|
||||||
|
Content string
|
||||||
|
Message string
|
||||||
|
ContentLength int32
|
||||||
|
FileType string
|
||||||
|
ParserEngine string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAICoreClient 创建 AI-Core 客户端
|
||||||
|
func NewAICoreClient(address string) (*AICoreClient, error) {
|
||||||
|
return &AICoreClient{address: address}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect 连接到 gRPC 服务
|
||||||
|
func (c *AICoreClient) Connect() error {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
conn, err := grpc.DialContext(ctx, c.address,
|
||||||
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to connect to AI-Core service: %w", err)
|
||||||
|
}
|
||||||
|
c.conn = conn
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close 关闭连接
|
||||||
|
func (c *AICoreClient) Close() {
|
||||||
|
if c.conn != nil {
|
||||||
|
c.conn.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseDocument 解析文档
|
||||||
|
func (c *AICoreClient) ParseDocument(fileURL, fileName, fileType string) (*ParseResult, error) {
|
||||||
|
if c.conn == nil {
|
||||||
|
if err := c.Connect(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 gRPC raw bytes 调用
|
||||||
|
// 由于没有生成 protobuf 代码,使用 raw bytes 方式调用
|
||||||
|
client := NewDocumentParserClient(c.conn)
|
||||||
|
|
||||||
|
req := &ParseRequest{
|
||||||
|
FileUrl: fileURL,
|
||||||
|
FileName: fileName,
|
||||||
|
FileType: fileType,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
resp, err := client.ParseDocument(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse document: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ParseResult{
|
||||||
|
Success: resp.Success,
|
||||||
|
Content: resp.Content,
|
||||||
|
Message: resp.Message,
|
||||||
|
ContentLength: resp.ContentLength,
|
||||||
|
FileType: resp.FileType,
|
||||||
|
ParserEngine: resp.ParserEngine,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 以下是手动定义的 protobuf messages(与 proto 文件一致)
|
||||||
|
// 不需要生成 .pb.go 文件,直接手动定义
|
||||||
|
|
||||||
|
type ParseRequest struct {
|
||||||
|
FileUrl string
|
||||||
|
FileName string
|
||||||
|
FileType string
|
||||||
|
ParserEngine string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ParseResponse struct {
|
||||||
|
Success bool
|
||||||
|
Content string
|
||||||
|
Message string
|
||||||
|
ContentLength int32
|
||||||
|
FileType string
|
||||||
|
ParserEngine string
|
||||||
|
}
|
||||||
|
|
||||||
|
// DocumentParserClient gRPC 客户端接口(手动实现)
|
||||||
|
type DocumentParserClient interface {
|
||||||
|
ParseDocument(ctx context.Context, in *ParseRequest, opts ...grpc.CallOption) (*ParseResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type documentParserClient struct {
|
||||||
|
cc grpc.ClientConnInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDocumentParserClient 创建 DocumentParser 客户端
|
||||||
|
func NewDocumentParserClient(cc grpc.ClientConnInterface) DocumentParserClient {
|
||||||
|
return &documentParserClient{cc: cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *documentParserClient) ParseDocument(ctx context.Context, in *ParseRequest, opts ...grpc.CallOption) (*ParseResponse, error) {
|
||||||
|
out := new(ParseResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/docparser.DocumentParser/ParseDocument", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
@@ -28,14 +28,17 @@ type KnowledgeService struct {
|
|||||||
modelRepo *repository.ModelRepository
|
modelRepo *repository.ModelRepository
|
||||||
uploadService *UploadService
|
uploadService *UploadService
|
||||||
pythonServiceURL string
|
pythonServiceURL string
|
||||||
|
aiCoreClient *AICoreClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewKnowledgeService(repo *repository.KnowledgeRepository, modelRepo *repository.ModelRepository, uploadService *UploadService, pythonServiceURL string) *KnowledgeService {
|
func NewKnowledgeService(repo *repository.KnowledgeRepository, modelRepo *repository.ModelRepository, uploadService *UploadService, pythonServiceURL, aiCoreServiceAddr string) *KnowledgeService {
|
||||||
|
aiCoreClient, _ := NewAICoreClient(aiCoreServiceAddr)
|
||||||
return &KnowledgeService{
|
return &KnowledgeService{
|
||||||
repo: repo,
|
repo: repo,
|
||||||
modelRepo: modelRepo,
|
modelRepo: modelRepo,
|
||||||
uploadService: uploadService,
|
uploadService: uploadService,
|
||||||
pythonServiceURL: pythonServiceURL,
|
pythonServiceURL: pythonServiceURL,
|
||||||
|
aiCoreClient: aiCoreClient,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +230,9 @@ func (s *KnowledgeService) UploadDocument(kbID string, file *multipart.FileHeade
|
|||||||
// 异步调用 Python 服务解析文档
|
// 异步调用 Python 服务解析文档
|
||||||
go s.parseDocument(kbID, doc.ID, result.URL, kb.ParsingConfig)
|
go s.parseDocument(kbID, doc.ID, result.URL, kb.ParsingConfig)
|
||||||
|
|
||||||
|
// 异步调用 AI-Core gRPC 服务解析文档(获取 Markdown)
|
||||||
|
go s.parseDocumentWithAICore(doc.ID, result.URL, doc.Name)
|
||||||
|
|
||||||
return doc, result.URL, nil
|
return doc, result.URL, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,6 +290,32 @@ func (s *KnowledgeService) parseDocument(kbID, docID, fileURL string, config mod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseDocumentWithAICore 调用 AI-Core gRPC 服务解析文档
|
||||||
|
func (s *KnowledgeService) parseDocumentWithAICore(docID, fileURL, fileName string) {
|
||||||
|
if s.aiCoreClient == nil {
|
||||||
|
knowledgeDebugLog.Printf("[AICore] AI-Core 客户端未初始化")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
knowledgeDebugLog.Printf("[AICore] 开始解析文档: docID=%s, fileURL=%s, fileName=%s", docID, fileURL, fileName)
|
||||||
|
|
||||||
|
result, err := s.aiCoreClient.ParseDocument(fileURL, fileName, "")
|
||||||
|
if err != nil {
|
||||||
|
knowledgeDebugLog.Printf("[AICore] 解析失败: docID=%s, err=%v", docID, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.Success && result.Content != "" {
|
||||||
|
knowledgeDebugLog.Printf("[AICore] 解析成功: docID=%s, contentLength=%d", docID, len(result.Content))
|
||||||
|
// 更新文档的 Content 字段
|
||||||
|
s.repo.UpdateDocument(docID, map[string]interface{}{
|
||||||
|
"content": result.Content,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
knowledgeDebugLog.Printf("[AICore] 解析返回失败: docID=%s, message=%s", docID, result.Message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteDocument 删除文档
|
// DeleteDocument 删除文档
|
||||||
func (s *KnowledgeService) DeleteDocument(kbID, docID string) error {
|
func (s *KnowledgeService) DeleteDocument(kbID, docID string) error {
|
||||||
// 验证文档存在
|
// 验证文档存在
|
||||||
|
|||||||
Reference in New Issue
Block a user