mirror of
https://gitee.com/milvus-io/milvus.git
synced 2026-02-02 01:06:41 +08:00
feat: Add highlight scores (#47017)
https://github.com/milvus-io/milvus/issues/46994 Signed-off-by: junjie.jiang <junjie.jiang@zilliz.com>
This commit is contained in:
parent
2b556dcac7
commit
b9752362d1
2
go.mod
2
go.mod
@ -20,7 +20,7 @@ require (
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
github.com/klauspost/compress v1.18.0
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20251224033913-b2fbe2627f1c
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20260113024922-c7feeb806088
|
||||
github.com/minio/minio-go/v7 v7.0.73
|
||||
github.com/panjf2000/ants/v2 v2.11.3 // indirect
|
||||
github.com/pingcap/log v1.1.1-0.20221015072633-39906604fb81 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@ -799,8 +799,8 @@ github.com/milvus-io/cgosymbolizer v0.0.0-20250318084424-114f4050c3a6 h1:YHMFI6L
|
||||
github.com/milvus-io/cgosymbolizer v0.0.0-20250318084424-114f4050c3a6/go.mod h1:DvXTE/K/RtHehxU8/GtDs4vFtfw64jJ3PaCnFri8CRg=
|
||||
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b h1:TfeY0NxYxZzUfIfYe5qYDBzt4ZYRqzUjTR6CvUzjat8=
|
||||
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b/go.mod h1:iwW+9cWfIzzDseEBCCeDSN5SD16Tidvy8cwQ7ZY8Qj4=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20251224033913-b2fbe2627f1c h1:W66Mf/hlR7SWHrSr7xpyt4ACE8v9/C7Y9dMJiZCvp3s=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20251224033913-b2fbe2627f1c/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20260113024922-c7feeb806088 h1:qzlpV+1xygF/XK0bRVoLFg03uAQSCZ2AywZR3wt5ov0=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20260113024922-c7feeb806088/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs=
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
|
||||
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI=
|
||||
|
||||
@ -353,8 +353,7 @@ func (_c *MockMsgHandler_HandleTruncateCollection_Call) RunAndReturn(run func(me
|
||||
func NewMockMsgHandler(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
},
|
||||
) *MockMsgHandler {
|
||||
}) *MockMsgHandler {
|
||||
mock := &MockMsgHandler{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
|
||||
@ -859,6 +859,65 @@ func (_c *MockProxy_BatchDescribeCollection_Call) RunAndReturn(run func(context.
|
||||
return _c
|
||||
}
|
||||
|
||||
// BatchUpdateManifest provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) BatchUpdateManifest(_a0 context.Context, _a1 *milvuspb.BatchUpdateManifestRequest) (*commonpb.Status, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for BatchUpdateManifest")
|
||||
}
|
||||
|
||||
var r0 *commonpb.Status
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.BatchUpdateManifestRequest) (*commonpb.Status, error)); ok {
|
||||
return rf(_a0, _a1)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.BatchUpdateManifestRequest) *commonpb.Status); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*commonpb.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.BatchUpdateManifestRequest) error); ok {
|
||||
r1 = rf(_a0, _a1)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockProxy_BatchUpdateManifest_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BatchUpdateManifest'
|
||||
type MockProxy_BatchUpdateManifest_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// BatchUpdateManifest is a helper method to define mock.On call
|
||||
// - _a0 context.Context
|
||||
// - _a1 *milvuspb.BatchUpdateManifestRequest
|
||||
func (_e *MockProxy_Expecter) BatchUpdateManifest(_a0 interface{}, _a1 interface{}) *MockProxy_BatchUpdateManifest_Call {
|
||||
return &MockProxy_BatchUpdateManifest_Call{Call: _e.mock.On("BatchUpdateManifest", _a0, _a1)}
|
||||
}
|
||||
|
||||
func (_c *MockProxy_BatchUpdateManifest_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.BatchUpdateManifestRequest)) *MockProxy_BatchUpdateManifest_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*milvuspb.BatchUpdateManifestRequest))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_BatchUpdateManifest_Call) Return(_a0 *commonpb.Status, _a1 error) *MockProxy_BatchUpdateManifest_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockProxy_BatchUpdateManifest_Call) RunAndReturn(run func(context.Context, *milvuspb.BatchUpdateManifestRequest) (*commonpb.Status, error)) *MockProxy_BatchUpdateManifest_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CalcDistance provides a mock function with given fields: _a0, _a1
|
||||
func (_m *MockProxy) CalcDistance(_a0 context.Context, _a1 *milvuspb.CalcDistanceRequest) (*milvuspb.CalcDistanceResults, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
@ -455,18 +455,23 @@ func (op *semanticHighlightOperator) run(ctx context.Context, span trace.Span, i
|
||||
return nil, errors.Errorf("get highlight failed, text field not in output field %d", fieldID)
|
||||
}
|
||||
texts := fieldDatas.GetScalars().GetStringData().GetData()
|
||||
highlights, err := op.highlight.Process(ctx, result.Results.GetTopks(), texts)
|
||||
highlights, scores, err := op.highlight.Process(ctx, result.Results.GetTopks(), texts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
singeFieldHighlights := &commonpb.HighlightResult{
|
||||
|
||||
if len(highlights) != len(scores) {
|
||||
return nil, errors.Errorf("Highlights size must equal to scores size, but got highlights size [%d], scores size [%d]", len(highlights), len(scores))
|
||||
}
|
||||
|
||||
singleFieldHighlights := &commonpb.HighlightResult{
|
||||
FieldName: op.highlight.GetFieldName(fieldID),
|
||||
Datas: make([]*commonpb.HighlightData, 0, len(highlights)),
|
||||
Datas: make([]*commonpb.HighlightData, len(highlights)),
|
||||
}
|
||||
for _, highlight := range highlights {
|
||||
singeFieldHighlights.Datas = append(singeFieldHighlights.Datas, &commonpb.HighlightData{Fragments: highlight})
|
||||
for i := range highlights {
|
||||
singleFieldHighlights.Datas[i] = &commonpb.HighlightData{Fragments: highlights[i], Scores: scores[i]}
|
||||
}
|
||||
highlightResults = append(highlightResults, singeFieldHighlights)
|
||||
highlightResults = append(highlightResults, singleFieldHighlights)
|
||||
}
|
||||
result.Results.HighlightResults = highlightResults
|
||||
return []any{result}, nil
|
||||
|
||||
@ -368,12 +368,16 @@ func (s *SearchPipelineSuite) TestSemanticHighlightOp() {
|
||||
|
||||
// Mock SemanticHighlight methods
|
||||
mockProcess := mockey.Mock((*highlight.SemanticHighlight).Process).To(
|
||||
func(h *highlight.SemanticHighlight, ctx context.Context, topks []int64, texts []string) ([][]string, error) {
|
||||
func(h *highlight.SemanticHighlight, ctx context.Context, topks []int64, texts []string) ([][]string, [][]float32, error) {
|
||||
return [][]string{
|
||||
{"<em>highlighted</em> text 1"},
|
||||
{"<em>highlighted</em> text 2"},
|
||||
{"<em>highlighted</em> text 3"},
|
||||
}, nil
|
||||
{"<em>highlighted</em> text 1"},
|
||||
{"<em>highlighted</em> text 2"},
|
||||
{"<em>highlighted</em> text 3"},
|
||||
}, [][]float32{
|
||||
{0.9},
|
||||
{0.8},
|
||||
{0.7},
|
||||
}, nil
|
||||
}).Build()
|
||||
defer mockProcess.UnPatch()
|
||||
|
||||
@ -484,12 +488,15 @@ func (s *SearchPipelineSuite) TestSemanticHighlightOpMultipleFields() {
|
||||
// Use a counter to return different results for different calls
|
||||
callCount := 0
|
||||
mockProcess := mockey.Mock((*highlight.SemanticHighlight).Process).To(
|
||||
func(h *highlight.SemanticHighlight, ctx context.Context, topks []int64, texts []string) ([][]string, error) {
|
||||
func(h *highlight.SemanticHighlight, ctx context.Context, topks []int64, texts []string) ([][]string, [][]float32, error) {
|
||||
callCount++
|
||||
return [][]string{
|
||||
{fmt.Sprintf("<em>highlighted</em> text field%d-1", callCount)},
|
||||
{fmt.Sprintf("<em>highlighted</em> text field%d-2", callCount)},
|
||||
}, nil
|
||||
{fmt.Sprintf("<em>highlighted</em> text field%d-1", callCount)},
|
||||
{fmt.Sprintf("<em>highlighted</em> text field%d-2", callCount)},
|
||||
}, [][]float32{
|
||||
{0.9},
|
||||
{0.8},
|
||||
}, nil
|
||||
}).Build()
|
||||
defer mockProcess.UnPatch()
|
||||
|
||||
@ -571,8 +578,8 @@ func (s *SearchPipelineSuite) TestSemanticHighlightOpEmptyResults() {
|
||||
|
||||
// Mock Process to return empty results
|
||||
mockProcess := mockey.Mock((*highlight.SemanticHighlight).Process).To(
|
||||
func(h *highlight.SemanticHighlight, ctx context.Context, topks []int64, texts []string) ([][]string, error) {
|
||||
return [][]string{}, nil
|
||||
func(h *highlight.SemanticHighlight, ctx context.Context, topks []int64, texts []string) ([][]string, [][]float32, error) {
|
||||
return [][]string{}, [][]float32{}, nil
|
||||
}).Build()
|
||||
defer mockProcess.UnPatch()
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@ import (
|
||||
)
|
||||
|
||||
type semanticHighlightProvider interface {
|
||||
highlight(ctx context.Context, query string, texts []string) ([][]string, error)
|
||||
highlight(ctx context.Context, query string, texts []string) ([][]string, [][]float32, error)
|
||||
maxBatch() int
|
||||
}
|
||||
|
||||
@ -114,40 +114,43 @@ func (highlight *SemanticHighlight) GetFieldName(id int64) string {
|
||||
return highlight.fieldNames[id]
|
||||
}
|
||||
|
||||
func (highlight *SemanticHighlight) processOneQuery(ctx context.Context, query string, data []string) ([][]string, error) {
|
||||
if len(data) == 0 {
|
||||
return [][]string{}, nil
|
||||
func (highlight *SemanticHighlight) processOneQuery(ctx context.Context, query string, documents []string) ([][]string, [][]float32, error) {
|
||||
if len(documents) == 0 {
|
||||
return [][]string{}, [][]float32{}, nil
|
||||
}
|
||||
highlights, err := highlight.provider.highlight(ctx, query, data)
|
||||
highlights, scores, err := highlight.provider.highlight(ctx, query, documents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(highlights) != len(data) {
|
||||
return nil, fmt.Errorf("Highlights size must equal to data size, but got highlights size [%d], data size [%d]", len(highlights), len(data))
|
||||
if len(highlights) != len(documents) || len(scores) != len(documents) {
|
||||
return nil, nil, fmt.Errorf("Highlights size must equal to documents size, but got highlights size [%d], scores size [%d], documents size [%d]", len(highlights), len(scores), len(documents))
|
||||
}
|
||||
return highlights, nil
|
||||
|
||||
return highlights, scores, nil
|
||||
}
|
||||
|
||||
func (highlight *SemanticHighlight) Process(ctx context.Context, topks []int64, data []string) ([][]string, error) {
|
||||
func (highlight *SemanticHighlight) Process(ctx context.Context, topks []int64, documents []string) ([][]string, [][]float32, error) {
|
||||
nq := len(topks)
|
||||
if len(highlight.queries) != nq {
|
||||
return nil, fmt.Errorf("nq must equal to queries size, but got nq [%d], queries size [%d], queries: [%v]", nq, len(highlight.queries), highlight.queries)
|
||||
return nil, nil, fmt.Errorf("nq must equal to queries size, but got nq [%d], queries size [%d], queries: [%v]", nq, len(highlight.queries), highlight.queries)
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return [][]string{}, nil
|
||||
if len(documents) == 0 {
|
||||
return [][]string{}, [][]float32{}, nil
|
||||
}
|
||||
|
||||
highlights := make([][]string, 0, len(data))
|
||||
highlights := make([][]string, 0, len(documents))
|
||||
scores := make([][]float32, 0, len(documents))
|
||||
start := int64(0)
|
||||
|
||||
for i, query := range highlight.queries {
|
||||
size := topks[i]
|
||||
singleHighlights, err := highlight.processOneQuery(ctx, query, data[start:start+size])
|
||||
singleQueryHighlights, singleQueryScores, err := highlight.processOneQuery(ctx, query, documents[start:start+size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
highlights = append(highlights, singleHighlights...)
|
||||
highlights = append(highlights, singleQueryHighlights...)
|
||||
scores = append(scores, singleQueryScores...)
|
||||
start += size
|
||||
}
|
||||
return highlights, nil
|
||||
return highlights, scores, nil
|
||||
}
|
||||
|
||||
@ -261,14 +261,18 @@ func (s *SemanticHighlightSuite) TestProcessOneQuery_Success() {
|
||||
{"machine learning"},
|
||||
{"machine"},
|
||||
}
|
||||
expectedScores := [][]float32{
|
||||
{0.95},
|
||||
{0.80},
|
||||
}
|
||||
|
||||
mock1 := mockey.Mock(zilliz.NewZilliClient).To(func(_ string, _ string, _ string, _ map[string]string) (*zilliz.ZillizClient, error) {
|
||||
return &zilliz.ZillizClient{}, nil
|
||||
}).Build()
|
||||
defer mock1.UnPatch()
|
||||
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, _ []string, _ map[string]string) ([][]string, error) {
|
||||
return expectedHighlights, nil
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, _ []string, _ map[string]string) ([][]string, [][]float32, error) {
|
||||
return expectedHighlights, expectedScores, nil
|
||||
}).Build()
|
||||
defer mock2.UnPatch()
|
||||
|
||||
@ -292,10 +296,11 @@ func (s *SemanticHighlightSuite) TestProcessOneQuery_Success() {
|
||||
|
||||
ctx := context.Background()
|
||||
data := []string{"Machine learning is a subset of AI", "Machine learning is powerful"}
|
||||
highlights, err := highlight.processOneQuery(ctx, "machine learning", data)
|
||||
highlights, scores, err := highlight.processOneQuery(ctx, "machine learning", data)
|
||||
|
||||
s.NoError(err)
|
||||
s.Equal(expectedHighlights, highlights)
|
||||
s.Equal(expectedScores, scores)
|
||||
}
|
||||
|
||||
func (s *SemanticHighlightSuite) TestProcessOneQuery_Error() {
|
||||
@ -312,8 +317,8 @@ func (s *SemanticHighlightSuite) TestProcessOneQuery_Error() {
|
||||
}).Build()
|
||||
defer mock1.UnPatch()
|
||||
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, _ []string, _ map[string]string) ([][]string, error) {
|
||||
return nil, expectedError
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, _ []string, _ map[string]string) ([][]string, [][]float32, error) {
|
||||
return nil, nil, expectedError
|
||||
}).Build()
|
||||
defer mock2.UnPatch()
|
||||
|
||||
@ -337,10 +342,11 @@ func (s *SemanticHighlightSuite) TestProcessOneQuery_Error() {
|
||||
|
||||
ctx := context.Background()
|
||||
data := []string{"test document"}
|
||||
highlights, err := highlight.processOneQuery(ctx, "test query", data)
|
||||
highlights, scores, err := highlight.processOneQuery(ctx, "test query", data)
|
||||
|
||||
s.Error(err)
|
||||
s.Nil(highlights)
|
||||
s.Nil(scores)
|
||||
s.Equal(expectedError, err)
|
||||
}
|
||||
|
||||
@ -354,9 +360,15 @@ func (s *SemanticHighlightSuite) TestProcess_Success() {
|
||||
expectedHighlights1 := [][]string{
|
||||
{"machine learning", "deep learning"},
|
||||
}
|
||||
expectedScores1 := [][]float32{
|
||||
{0.90},
|
||||
}
|
||||
expectedHighlights2 := [][]string{
|
||||
{"deep learning", "machine learning"},
|
||||
}
|
||||
expectedScores2 := [][]float32{
|
||||
{0.85},
|
||||
}
|
||||
|
||||
callCount := 0
|
||||
mock1 := mockey.Mock(zilliz.NewZilliClient).To(func(_ string, _ string, _ string, _ map[string]string) (*zilliz.ZillizClient, error) {
|
||||
@ -364,12 +376,12 @@ func (s *SemanticHighlightSuite) TestProcess_Success() {
|
||||
}).Build()
|
||||
defer mock1.UnPatch()
|
||||
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, query string, _ []string, _ map[string]string) ([][]string, error) {
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, query string, _ []string, _ map[string]string) ([][]string, [][]float32, error) {
|
||||
callCount++
|
||||
if query == "machine learning" {
|
||||
return expectedHighlights1, nil
|
||||
return expectedHighlights1, expectedScores1, nil
|
||||
}
|
||||
return expectedHighlights2, nil
|
||||
return expectedHighlights2, expectedScores2, nil
|
||||
}).Build()
|
||||
defer mock2.UnPatch()
|
||||
|
||||
@ -393,11 +405,15 @@ func (s *SemanticHighlightSuite) TestProcess_Success() {
|
||||
|
||||
ctx := context.Background()
|
||||
data := []string{"Machine learning document", "Deep learning document"}
|
||||
highlights, err := highlight.Process(ctx, []int64{1, 1}, data)
|
||||
highlights, scores, err := highlight.Process(ctx, []int64{1, 1}, data)
|
||||
|
||||
s.NoError(err)
|
||||
s.NotNil(highlights)
|
||||
s.Equal(2, callCount, "Should call highlight twice for two queries")
|
||||
s.NotNil(scores)
|
||||
s.Equal(2, len(scores))
|
||||
s.Equal(1, len(scores[0]))
|
||||
s.Equal(1, len(scores[1]))
|
||||
}
|
||||
|
||||
func (s *SemanticHighlightSuite) TestProcess_NqMismatch() {
|
||||
@ -432,11 +448,12 @@ func (s *SemanticHighlightSuite) TestProcess_NqMismatch() {
|
||||
|
||||
ctx := context.Background()
|
||||
data := []string{"test document"}
|
||||
highlights, err := highlight.Process(ctx, []int64{1, 1, 1}, data) // nq=3 but queries has only 1
|
||||
highlights, scores, err := highlight.Process(ctx, []int64{1, 1, 1}, data) // nq=3 but queries has only 1
|
||||
|
||||
s.Error(err)
|
||||
s.Nil(highlights)
|
||||
s.Contains(err.Error(), "nq must equal to queries size")
|
||||
s.Nil(scores)
|
||||
}
|
||||
|
||||
func (s *SemanticHighlightSuite) TestProcess_ProviderError() {
|
||||
@ -453,8 +470,8 @@ func (s *SemanticHighlightSuite) TestProcess_ProviderError() {
|
||||
}).Build()
|
||||
defer mock1.UnPatch()
|
||||
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, _ []string, _ map[string]string) ([][]string, error) {
|
||||
return nil, expectedError
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, _ []string, _ map[string]string) ([][]string, [][]float32, error) {
|
||||
return nil, nil, expectedError
|
||||
}).Build()
|
||||
defer mock2.UnPatch()
|
||||
|
||||
@ -478,11 +495,12 @@ func (s *SemanticHighlightSuite) TestProcess_ProviderError() {
|
||||
|
||||
ctx := context.Background()
|
||||
data := []string{"test document"}
|
||||
highlights, err := highlight.Process(ctx, []int64{1}, data)
|
||||
highlights, scores, err := highlight.Process(ctx, []int64{1}, data)
|
||||
|
||||
s.Error(err)
|
||||
s.Nil(highlights)
|
||||
s.Equal(expectedError, err)
|
||||
s.Nil(scores)
|
||||
}
|
||||
|
||||
func (s *SemanticHighlightSuite) TestProcess_EmptyData() {
|
||||
@ -497,8 +515,12 @@ func (s *SemanticHighlightSuite) TestProcess_EmptyData() {
|
||||
}).Build()
|
||||
defer mock1.UnPatch()
|
||||
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, texts []string, _ map[string]string) ([][]string, error) {
|
||||
return [][]string{texts}, nil
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, texts []string, _ map[string]string) ([][]string, [][]float32, error) {
|
||||
scores := make([][]float32, len(texts))
|
||||
for i := range texts {
|
||||
scores[i] = []float32{0.75}
|
||||
}
|
||||
return [][]string{texts}, scores, nil
|
||||
}).Build()
|
||||
defer mock2.UnPatch()
|
||||
|
||||
@ -522,18 +544,25 @@ func (s *SemanticHighlightSuite) TestProcess_EmptyData() {
|
||||
|
||||
ctx := context.Background()
|
||||
data := []string{}
|
||||
highlights, err := highlight.Process(ctx, []int64{0, 0, 0}, data)
|
||||
highlights, scores, err := highlight.Process(ctx, []int64{0, 0, 0}, data)
|
||||
|
||||
s.NoError(err)
|
||||
s.NotNil(highlights)
|
||||
s.Equal(0, len(highlights))
|
||||
s.NotNil(scores)
|
||||
s.Equal(0, len(scores))
|
||||
|
||||
data2 := []string{"test document"}
|
||||
|
||||
highlights2, err := highlight.Process(ctx, []int64{0, 1, 0}, data2)
|
||||
highlights2, scores2, err := highlight.Process(ctx, []int64{0, 1, 0}, data2)
|
||||
|
||||
s.NoError(err)
|
||||
s.Equal(1, len(highlights2))
|
||||
s.Equal([][]string{{"test document"}}, highlights2)
|
||||
s.NotNil(scores2)
|
||||
s.Equal(1, len(scores2))
|
||||
s.Equal(1, len(scores2[0]))
|
||||
s.Equal(float32(0.75), scores2[0][0])
|
||||
}
|
||||
|
||||
func (s *SemanticHighlightSuite) TestBaseSemanticHighlightProvider_MaxBatch() {
|
||||
|
||||
@ -69,10 +69,10 @@ func newZillizHighlightProvider(params []*commonpb.KeyValuePair, conf map[string
|
||||
return &provider, nil
|
||||
}
|
||||
|
||||
func (h *zillizHighlightProvider) highlight(ctx context.Context, query string, texts []string) ([][]string, error) {
|
||||
highlights, err := h.client.Highlight(ctx, query, texts, h.modelParams)
|
||||
func (h *zillizHighlightProvider) highlight(ctx context.Context, query string, texts []string) ([][]string, [][]float32, error) {
|
||||
highlights, scores, err := h.client.Highlight(ctx, query, texts, h.modelParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return highlights, nil
|
||||
return highlights, scores, nil
|
||||
}
|
||||
|
||||
@ -177,14 +177,19 @@ func (s *ZillizHighlightProviderSuite) TestZillizHighlightProvider_Highlight_Suc
|
||||
{"Deep learning", "machine learning"},
|
||||
{"Natural language processing", "machine learning"},
|
||||
}
|
||||
expectedScores := [][]float32{
|
||||
{0.9, 0.8},
|
||||
{0.8, 0.7},
|
||||
{0.7, 0.6},
|
||||
}
|
||||
|
||||
mock1 := mockey.Mock(zilliz.NewZilliClient).To(func(_ string, _ string, _ string, _ map[string]string) (*zilliz.ZillizClient, error) {
|
||||
return &zilliz.ZillizClient{}, nil
|
||||
}).Build()
|
||||
defer mock1.UnPatch()
|
||||
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, _ []string, _ map[string]string) ([][]string, error) {
|
||||
return expectedHighlights, nil
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, _ []string, _ map[string]string) ([][]string, [][]float32, error) {
|
||||
return expectedHighlights, expectedScores, nil
|
||||
}).Build()
|
||||
defer mock2.UnPatch()
|
||||
|
||||
@ -197,10 +202,11 @@ func (s *ZillizHighlightProviderSuite) TestZillizHighlightProvider_Highlight_Suc
|
||||
s.NoError(err)
|
||||
s.NotNil(provider)
|
||||
|
||||
highlights, err := provider.highlight(ctx, query, texts)
|
||||
highlights, scores, err := provider.highlight(ctx, query, texts)
|
||||
|
||||
s.NoError(err)
|
||||
s.Equal(expectedHighlights, highlights)
|
||||
s.Equal(expectedScores, scores)
|
||||
}
|
||||
|
||||
func (s *ZillizHighlightProviderSuite) TestZillizHighlightProvider_Highlight_Error() {
|
||||
@ -215,8 +221,8 @@ func (s *ZillizHighlightProviderSuite) TestZillizHighlightProvider_Highlight_Err
|
||||
}).Build()
|
||||
defer mock1.UnPatch()
|
||||
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, _ []string, _ map[string]string) ([][]string, error) {
|
||||
return nil, expectedError
|
||||
mock2 := mockey.Mock((*zilliz.ZillizClient).Highlight).To(func(_ *zilliz.ZillizClient, _ context.Context, _ string, _ []string, _ map[string]string) ([][]string, [][]float32, error) {
|
||||
return nil, nil, expectedError
|
||||
}).Build()
|
||||
defer mock2.UnPatch()
|
||||
|
||||
@ -230,9 +236,10 @@ func (s *ZillizHighlightProviderSuite) TestZillizHighlightProvider_Highlight_Err
|
||||
s.NotNil(provider)
|
||||
|
||||
// Test the highlight method
|
||||
highlights, err := provider.highlight(ctx, query, texts)
|
||||
highlights, scores, err := provider.highlight(ctx, query, texts)
|
||||
|
||||
s.Error(err)
|
||||
s.Nil(highlights)
|
||||
s.Nil(scores)
|
||||
s.Equal(expectedError, err)
|
||||
}
|
||||
|
||||
@ -253,7 +253,7 @@ func (c *ZillizClient) Rerank(ctx context.Context, query string, texts []string,
|
||||
return res.Scores, nil
|
||||
}
|
||||
|
||||
func (c *ZillizClient) Highlight(ctx context.Context, query string, texts []string, params map[string]string) ([][]string, error) {
|
||||
func (c *ZillizClient) Highlight(ctx context.Context, query string, texts []string, params map[string]string) ([][]string, [][]float32, error) {
|
||||
stub := modelservicepb.NewHighlightServiceClient(c.conn)
|
||||
req := &modelservicepb.HighlightRequest{
|
||||
Query: query,
|
||||
@ -263,11 +263,27 @@ func (c *ZillizClient) Highlight(ctx context.Context, query string, texts []stri
|
||||
ctx = c.setMeta(ctx)
|
||||
res, err := stub.Highlight(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
highlights := make([][]string, 0, len(res.GetResults()))
|
||||
scores := make([][]float32, 0, len(res.GetResults()))
|
||||
for _, ret := range res.GetResults() {
|
||||
highlights = append(highlights, ret.GetSentences())
|
||||
sentences := ret.GetSentences()
|
||||
retScores := ret.GetScores()
|
||||
|
||||
// Handle nil cases
|
||||
if sentences == nil {
|
||||
sentences = []string{}
|
||||
}
|
||||
if retScores == nil {
|
||||
retScores = []float32{}
|
||||
}
|
||||
|
||||
if len(sentences) != len(retScores) {
|
||||
return nil, nil, fmt.Errorf("sentences length %d does not match scores length %d", len(sentences), len(retScores))
|
||||
}
|
||||
highlights = append(highlights, sentences)
|
||||
scores = append(scores, retScores)
|
||||
}
|
||||
return highlights, nil
|
||||
return highlights, scores, nil
|
||||
}
|
||||
|
||||
@ -585,9 +585,11 @@ func TestZillizClient_Highlight(t *testing.T) {
|
||||
Results: []*modelservicepb.HighlightResult{
|
||||
{
|
||||
Sentences: []string{"highlight1", "highlight2"},
|
||||
Scores: []float32{0.9, 0.8},
|
||||
},
|
||||
{
|
||||
Sentences: []string{"highlight3", "highlight4"},
|
||||
Scores: []float32{0.8, 0.7},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -623,9 +625,10 @@ func TestZillizClient_Highlight(t *testing.T) {
|
||||
query := "test query"
|
||||
texts := []string{"doc1", "doc2", "doc3"}
|
||||
params := map[string]string{"param1": "value1"}
|
||||
highlights, err := client.Highlight(ctx, query, texts, params)
|
||||
highlights, scores, err := client.Highlight(ctx, query, texts, params)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, [][]string{{"highlight1", "highlight2"}, {"highlight3", "highlight4"}}, highlights)
|
||||
assert.Equal(t, [][]float32{{0.9, 0.8}, {0.8, 0.7}}, scores)
|
||||
}
|
||||
|
||||
func TestZillizClient_Highlight_Error(t *testing.T) {
|
||||
@ -668,7 +671,130 @@ func TestZillizClient_Highlight_Error(t *testing.T) {
|
||||
query := "test query"
|
||||
texts := []string{"doc1", "doc2", "doc3"}
|
||||
params := map[string]string{"param1": "value1"}
|
||||
highlights, err := client.Highlight(ctx, query, texts, params)
|
||||
highlights, scores, err := client.Highlight(ctx, query, texts, params)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, highlights)
|
||||
assert.Nil(t, scores)
|
||||
}
|
||||
|
||||
func TestZillizClient_Highlight_MismatchLength(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
response *modelservicepb.HighlightResponse
|
||||
expectedErrMsg string
|
||||
}{
|
||||
{
|
||||
name: "more sentences than scores",
|
||||
response: &modelservicepb.HighlightResponse{
|
||||
Status: &modelservicepb.Status{Code: 0, Msg: "success"},
|
||||
Results: []*modelservicepb.HighlightResult{
|
||||
{
|
||||
Sentences: []string{"highlight1", "highlight2", "highlight3"},
|
||||
Scores: []float32{0.9, 0.8},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrMsg: "sentences length 3 does not match scores length 2",
|
||||
},
|
||||
{
|
||||
name: "more scores than sentences",
|
||||
response: &modelservicepb.HighlightResponse{
|
||||
Status: &modelservicepb.Status{Code: 0, Msg: "success"},
|
||||
Results: []*modelservicepb.HighlightResult{
|
||||
{
|
||||
Sentences: []string{"highlight1"},
|
||||
Scores: []float32{0.9, 0.8, 0.7},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrMsg: "sentences length 1 does not match scores length 3",
|
||||
},
|
||||
{
|
||||
name: "mismatch in second result",
|
||||
response: &modelservicepb.HighlightResponse{
|
||||
Status: &modelservicepb.Status{Code: 0, Msg: "success"},
|
||||
Results: []*modelservicepb.HighlightResult{
|
||||
{
|
||||
Sentences: []string{"highlight1", "highlight2"},
|
||||
Scores: []float32{0.9, 0.8},
|
||||
},
|
||||
{
|
||||
Sentences: []string{"highlight3"},
|
||||
Scores: []float32{0.7, 0.6},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrMsg: "sentences length 1 does not match scores length 2",
|
||||
},
|
||||
{
|
||||
name: "nil sentences",
|
||||
response: &modelservicepb.HighlightResponse{
|
||||
Status: &modelservicepb.Status{Code: 0, Msg: "success"},
|
||||
Results: []*modelservicepb.HighlightResult{
|
||||
{},
|
||||
{
|
||||
Sentences: []string{"highlight3"},
|
||||
Scores: []float32{0.7, 0.6},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrMsg: "sentences length 1 does not match scores length 2",
|
||||
},
|
||||
{
|
||||
name: "nil scores",
|
||||
response: &modelservicepb.HighlightResponse{
|
||||
Status: &modelservicepb.Status{Code: 0, Msg: "success"},
|
||||
Results: []*modelservicepb.HighlightResult{
|
||||
{
|
||||
Sentences: []string{"highlight1", "highlight2"},
|
||||
Scores: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrMsg: "sentences length 2 does not match scores length 0",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s, lis, dialer := setupMockServer(t)
|
||||
defer lis.Close()
|
||||
defer s.Stop()
|
||||
|
||||
mockServer := &mockHighlightServer{
|
||||
response: tt.response,
|
||||
}
|
||||
|
||||
modelservicepb.RegisterHighlightServiceServer(s, mockServer)
|
||||
|
||||
go func() {
|
||||
if err := s.Serve(lis); err != nil {
|
||||
fmt.Printf("Server exited with error: %v\n", err)
|
||||
}
|
||||
}()
|
||||
|
||||
conn, err := grpc.DialContext(
|
||||
context.Background(),
|
||||
"bufnet",
|
||||
grpc.WithContextDialer(dialer),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithBlock(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
defer conn.Close()
|
||||
|
||||
client := &ZillizClient{
|
||||
modelDeploymentID: "test-deployment",
|
||||
clusterID: "test-cluster",
|
||||
conn: conn,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
highlights, scores, err := client.Highlight(ctx, "test query", []string{"doc1"}, map[string]string{})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tt.expectedErrMsg)
|
||||
assert.Nil(t, highlights)
|
||||
assert.Nil(t, scores)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ require (
|
||||
github.com/jolestar/go-commons-pool/v2 v2.1.2
|
||||
github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12
|
||||
github.com/klauspost/compress v1.18.0
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20251224033913-b2fbe2627f1c
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20260113024922-c7feeb806088
|
||||
github.com/minio/minio-go/v7 v7.0.73
|
||||
github.com/panjf2000/ants/v2 v2.11.3
|
||||
github.com/prometheus/client_golang v1.20.5
|
||||
|
||||
@ -482,8 +482,8 @@ github.com/milvus-io/cgosymbolizer v0.0.0-20250318084424-114f4050c3a6 h1:YHMFI6L
|
||||
github.com/milvus-io/cgosymbolizer v0.0.0-20250318084424-114f4050c3a6/go.mod h1:DvXTE/K/RtHehxU8/GtDs4vFtfw64jJ3PaCnFri8CRg=
|
||||
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b h1:TfeY0NxYxZzUfIfYe5qYDBzt4ZYRqzUjTR6CvUzjat8=
|
||||
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b/go.mod h1:iwW+9cWfIzzDseEBCCeDSN5SD16Tidvy8cwQ7ZY8Qj4=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20251224033913-b2fbe2627f1c h1:W66Mf/hlR7SWHrSr7xpyt4ACE8v9/C7Y9dMJiZCvp3s=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20251224033913-b2fbe2627f1c/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20260113024922-c7feeb806088 h1:qzlpV+1xygF/XK0bRVoLFg03uAQSCZ2AywZR3wt5ov0=
|
||||
github.com/milvus-io/milvus-proto/go-api/v2 v2.6.6-0.20260113024922-c7feeb806088/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.73 h1:qr2vi96Qm7kZ4v7LLebjte+MQh621fFWnv93p12htEo=
|
||||
|
||||
@ -82,6 +82,7 @@ message HighlightRequest {
|
||||
|
||||
message HighlightResult {
|
||||
repeated string sentences = 1;
|
||||
repeated float scores = 2;
|
||||
}
|
||||
|
||||
message HighlightResponse {
|
||||
|
||||
@ -696,7 +696,8 @@ type HighlightResult struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Sentences []string `protobuf:"bytes,1,rep,name=sentences,proto3" json:"sentences,omitempty"`
|
||||
Sentences []string `protobuf:"bytes,1,rep,name=sentences,proto3" json:"sentences,omitempty"`
|
||||
Scores []float32 `protobuf:"fixed32,2,rep,packed,name=scores,proto3" json:"scores,omitempty"`
|
||||
}
|
||||
|
||||
func (x *HighlightResult) Reset() {
|
||||
@ -738,6 +739,13 @@ func (x *HighlightResult) GetSentences() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *HighlightResult) GetScores() []float32 {
|
||||
if x != nil {
|
||||
return x.Scores
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type HighlightResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -925,57 +933,58 @@ var file_model_service_proto_rawDesc = []byte{
|
||||
0x61, 0x6d, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x3a, 0x02, 0x38, 0x01, 0x22, 0x2f, 0x0a, 0x0f, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68,
|
||||
0x3a, 0x02, 0x38, 0x01, 0x22, 0x47, 0x0a, 0x0f, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68,
|
||||
0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x74, 0x65,
|
||||
0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x74,
|
||||
0x65, 0x6e, 0x63, 0x65, 0x73, 0x22, 0xae, 0x02, 0x0a, 0x11, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69,
|
||||
0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x73,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x69,
|
||||
0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06,
|
||||
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x5a, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f,
|
||||
0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x6d, 0x69, 0x6c,
|
||||
0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x49, 0x6e,
|
||||
0x66, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x65, 0x78, 0x74, 0x72, 0x61, 0x49, 0x6e,
|
||||
0x66, 0x6f, 0x12, 0x44, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18,
|
||||
0x02, 0x20, 0x03, 0x28, 0x02, 0x52, 0x06, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x22, 0xae, 0x02,
|
||||
0x0a, 0x11, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
|
||||
0x48, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52,
|
||||
0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x3c, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x72,
|
||||
0x61, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
|
||||
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0x86, 0x01, 0x0a, 0x14, 0x54, 0x65, 0x78, 0x74, 0x45,
|
||||
0x6d, 0x62, 0x65, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
|
||||
0x6e, 0x0a, 0x09, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x2e, 0x6d,
|
||||
0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65,
|
||||
0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x45, 0x6d, 0x62,
|
||||
0x65, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e,
|
||||
0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64,
|
||||
0x65, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x45, 0x6d,
|
||||
0x62, 0x65, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32,
|
||||
0x76, 0x0a, 0x0d, 0x52, 0x65, 0x72, 0x61, 0x6e, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x12, 0x65, 0x0a, 0x06, 0x52, 0x65, 0x72, 0x61, 0x6e, 0x6b, 0x12, 0x2c, 0x2e, 0x6d, 0x69, 0x6c,
|
||||
0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x52, 0x65, 0x72, 0x61, 0x6e,
|
||||
0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75,
|
||||
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x52, 0x65, 0x72, 0x61, 0x6e, 0x6b, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x7a, 0x0a, 0x10, 0x48, 0x69, 0x67, 0x68, 0x6c,
|
||||
0x69, 0x67, 0x68, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x66, 0x0a, 0x09, 0x48,
|
||||
0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2b, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75,
|
||||
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70,
|
||||
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x5a,
|
||||
0x0a, 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48,
|
||||
0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x2e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
|
||||
0x09, 0x65, 0x78, 0x74, 0x72, 0x61, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x07, 0x72, 0x65,
|
||||
0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6d, 0x69,
|
||||
0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68,
|
||||
0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73,
|
||||
0x1a, 0x3c, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0x86,
|
||||
0x01, 0x0a, 0x14, 0x54, 0x65, 0x78, 0x74, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x69, 0x6e, 0x67,
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6e, 0x0a, 0x09, 0x45, 0x6d, 0x62, 0x65, 0x64,
|
||||
0x64, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x2e, 0x54, 0x65, 0x78, 0x74, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x2e, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x2f, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2d, 0x69, 0x6f, 0x2f, 0x6d, 0x69, 0x6c, 0x76,
|
||||
0x75, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
|
||||
0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x70, 0x62, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x65, 0x2e, 0x54, 0x65, 0x78, 0x74, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x76, 0x0a, 0x0d, 0x52, 0x65, 0x72, 0x61, 0x6e,
|
||||
0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x65, 0x0a, 0x06, 0x52, 0x65, 0x72, 0x61,
|
||||
0x6e, 0x6b, 0x12, 0x2c, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54,
|
||||
0x65, 0x78, 0x74, 0x52, 0x65, 0x72, 0x61, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x2d, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
|
||||
0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x65, 0x78,
|
||||
0x74, 0x52, 0x65, 0x72, 0x61, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32,
|
||||
0x7a, 0x0a, 0x10, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x53, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x12, 0x66, 0x0a, 0x09, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74,
|
||||
0x12, 0x2b, 0x2e, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
|
||||
0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x69, 0x67,
|
||||
0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e,
|
||||
0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x6f, 0x64,
|
||||
0x65, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69,
|
||||
0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x39, 0x5a, 0x37, 0x67,
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73,
|
||||
0x2d, 0x69, 0x6f, 0x2f, 0x6d, 0x69, 0x6c, 0x76, 0x75, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x76,
|
||||
0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user