Skip to content

Commit bd662ef

Browse files
committed
git code from remote
1 parent 6015ffa commit bd662ef

File tree

4 files changed

+100
-6
lines changed

4 files changed

+100
-6
lines changed

internal/config/vector.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ type VectorStoreConf struct {
1111
Embedder EmbedderConf
1212
Reranker RerankerConf
1313
// 具体实现配置
14-
Weaviate WeaviateConf // Weaviate配置
14+
Weaviate WeaviateConf // Weaviate配置
15+
FetchSourceCode bool `json:",default=false"` // 是否获取源码
16+
BaseURL string `json:",optional"` // 获取代码内容的基础URL
1517
}
1618

1719
// WeaviateConf Weaviate向量数据库配置

internal/logic/semantic.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
78
"github.com/zgsm-ai/codebase-indexer/internal/errs"
89
"github.com/zgsm-ai/codebase-indexer/internal/store/vector"
910
"github.com/zgsm-ai/codebase-indexer/internal/tracer"
@@ -60,7 +61,7 @@ func (l *SemanticLogic) SemanticSearch(req *types.SemanticSearchRequest) (resp *
6061
ctx := context.WithValue(l.ctx, tracer.Key, tracer.RequestTraceId(int(codebase.ID)))
6162

6263
documents, err := l.svcCtx.VectorStore.Query(ctx, req.Query, topK,
63-
vector.Options{CodebaseId: codebase.ID,
64+
vector.Options{CodebaseId: codebase.ID, ClientId: clientId,
6465
CodebasePath: codebase.Path, CodebaseName: codebase.Name})
6566
if err != nil {
6667
return nil, err

internal/store/vector/vector_store.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type Options struct {
3131
CodebasePath string
3232
CodebaseName string
3333
TotalFiles int
34+
ClientId string
3435
}
3536

3637
func NewVectorStore(cfg config.VectorStoreConf, embedder Embedder, reranker Reranker) (Store, error) {

internal/store/vector/weaviate_wrapper.go

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ import (
55
"crypto/md5"
66
"encoding/hex"
77
"fmt"
8+
"io"
89
"math"
10+
"net/http"
11+
"net/url"
12+
"path/filepath"
913
"reflect"
14+
"runtime"
1015
"strings"
1116
"time"
1217

@@ -243,15 +248,15 @@ func (r *weaviateWrapper) SimilaritySearch(ctx context.Context, query string, nu
243248
return nil, fmt.Errorf("query weaviate failed: %w", err)
244249
}
245250

246-
items, err := r.unmarshalSimilarSearchResponse(res)
251+
items, err := r.unmarshalSimilarSearchResponse(res, options.CodebasePath, options.ClientId)
247252
if err != nil {
248253
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
249254
}
250255

251256
return items, nil
252257
}
253258

254-
func (r *weaviateWrapper) unmarshalSimilarSearchResponse(res *models.GraphQLResponse) ([]*types.SemanticFileItem, error) {
259+
func (r *weaviateWrapper) unmarshalSimilarSearchResponse(res *models.GraphQLResponse, codebasePath, clientId string) ([]*types.SemanticFileItem, error) {
255260
// Get the data for our class
256261
data, ok := res.Data["Get"].(map[string]interface{})
257262
if !ok {
@@ -276,10 +281,37 @@ func (r *weaviateWrapper) unmarshalSimilarSearchResponse(res *models.GraphQLResp
276281
continue
277282
}
278283

284+
content := getStringValue(obj, Content)
285+
filePath := getStringValue(obj, MetadataFilePath)
286+
287+
// 如果开启获取源码,则从MetadataRange中提取行号信息
288+
if r.cfg.FetchSourceCode && content != "" && filePath != "" {
289+
// 从MetadataRange中提取startLine和endLine
290+
var startLine, endLine int
291+
if rangeValue, ok := obj[MetadataRange].([]interface{}); ok && len(rangeValue) >= 2 {
292+
if first, ok := rangeValue[0].(float64); ok {
293+
startLine = int(first)
294+
}
295+
if second, ok := rangeValue[2].(float64); ok {
296+
endLine = int(second)
297+
}
298+
}
299+
300+
// 通过fetchCodeContent接口获取代码片段
301+
if codebasePath != "" {
302+
fetchedContent, err := fetchCodeContent(context.Background(), r.cfg, clientId, codebasePath, filePath, startLine, endLine)
303+
if err == nil && fetchedContent != "" {
304+
content = fetchedContent
305+
}
306+
}
307+
}
308+
309+
fmt.Printf("[DEBUG] %s content: %s\n", filePath, content)
310+
279311
// Create SemanticFileItem with proper fields
280312
item := &types.SemanticFileItem{
281-
Content: getStringValue(obj, Content),
282-
FilePath: getStringValue(obj, MetadataFilePath),
313+
Content: content,
314+
FilePath: filePath,
283315
Score: float32(getFloatValue(additional, "certainty")), // Convert float64 to float32
284316
}
285317

@@ -661,6 +693,64 @@ func (r *weaviateWrapper) Query(ctx context.Context, query string, topK int, opt
661693
return rerankedDocs, nil
662694
}
663695

696+
// fetchCodeContent 通过API获取代码片段的Content
697+
func fetchCodeContent(ctx context.Context, cfg config.VectorStoreConf, clientId, codebasePath, filePath string, startLine, endLine int) (string, error) {
698+
// 构建API请求URL
699+
baseURL := cfg.BaseURL
700+
701+
// 对参数进行URL编码
702+
encodedCodebasePath := url.QueryEscape(codebasePath)
703+
704+
// 如果filePath是全路径,则与codebasePath拼接处理
705+
var processedFilePath string
706+
if strings.HasPrefix(filePath, "/") {
707+
// filePath是全路径,直接使用
708+
processedFilePath = filePath
709+
} else {
710+
// filePath是相对路径,与codebasePath拼接
711+
processedFilePath = fmt.Sprintf("%s/%s", strings.TrimSuffix(codebasePath, "/"), filePath)
712+
}
713+
714+
// 检查操作系统类型,如果是Windows则将路径转换为Windows格式
715+
if runtime.GOOS == "windows" {
716+
// 将Unix风格的路径转换为Windows风格
717+
processedFilePath = filepath.FromSlash(processedFilePath)
718+
// 确保路径是绝对路径格式
719+
if !strings.HasPrefix(processedFilePath, "\\") && !strings.Contains(processedFilePath, ":") {
720+
// 如果不是网络路径也不是驱动器路径,添加当前驱动器
721+
processedFilePath = filepath.Join(filepath.VolumeName("."), processedFilePath)
722+
}
723+
}
724+
725+
encodedFilePath := url.QueryEscape(processedFilePath)
726+
727+
// 构建完整的请求URL
728+
requestURL := fmt.Sprintf("%s?clientId=%s&codebasePath=%s&filePath=%s&startLine=%d&endLine=%d",
729+
baseURL, clientId, encodedCodebasePath, encodedFilePath, startLine, endLine)
730+
731+
tracer.WithTrace(ctx).Infof("fetchCodeContent %s: ", requestURL)
732+
733+
// 发送HTTP GET请求
734+
resp, err := http.Get(requestURL)
735+
if err != nil {
736+
return "", fmt.Errorf("failed to fetch code content: %w", err)
737+
}
738+
defer resp.Body.Close()
739+
740+
// 检查响应状态码
741+
if resp.StatusCode != http.StatusOK {
742+
return "", fmt.Errorf("unexpected status code: %d", resp.StatusCode)
743+
}
744+
745+
// 读取响应体
746+
body, err := io.ReadAll(resp.Body)
747+
if err != nil {
748+
return "", fmt.Errorf("failed to read response body: %w", err)
749+
}
750+
751+
return string(body), nil
752+
}
753+
664754
func (r *weaviateWrapper) createClassWithAutoTenantEnabled(client *goweaviate.Client) error {
665755
timeout, cancelFunc := context.WithTimeout(context.Background(), time.Second*60)
666756
defer cancelFunc()

0 commit comments

Comments
 (0)