@@ -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+
664754func (r * weaviateWrapper ) createClassWithAutoTenantEnabled (client * goweaviate.Client ) error {
665755 timeout , cancelFunc := context .WithTimeout (context .Background (), time .Second * 60 )
666756 defer cancelFunc ()
0 commit comments