From 4b19e6fb9faee7fdac4eec461b9f81293dbe6b1d Mon Sep 17 00:00:00 2001 From: Hayden Date: Tue, 9 Jul 2024 15:30:24 +0700 Subject: [PATCH 01/19] feat: conversation models --- typesense/api/client_gen.go | 249 ++++++++++++++++++++++++++ typesense/api/generator/generator.yml | 80 +++++++++ typesense/api/types_gen.go | 46 +++++ typesense/conversation_models.go | 40 +++++ typesense/mocks/mock_client.go | 120 +++++++++++++ 5 files changed, 535 insertions(+) create mode 100644 typesense/conversation_models.go diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index 04bc669..bf2b32d 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -202,6 +202,14 @@ type ClientInterface interface { UpsertSearchSynonym(ctx context.Context, collectionName string, synonymId string, body UpsertSearchSynonymJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // RetrieveAllConversationModels request + RetrieveAllConversationModels(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + + // CreateConversationModelWithBody request with any body + CreateConversationModelWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + CreateConversationModel(ctx context.Context, body CreateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // Debug request Debug(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -760,6 +768,42 @@ func (c *Client) UpsertSearchSynonym(ctx context.Context, collectionName string, return c.Client.Do(req) } +func (c *Client) RetrieveAllConversationModels(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRetrieveAllConversationModelsRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreateConversationModelWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateConversationModelRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreateConversationModel(ctx context.Context, body CreateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateConversationModelRequest(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) Debug(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewDebugRequest(c.Server) if err != nil { @@ -3342,6 +3386,73 @@ func NewUpsertSearchSynonymRequestWithBody(server string, collectionName string, return req, nil } +// NewRetrieveAllConversationModelsRequest generates requests for RetrieveAllConversationModels +func NewRetrieveAllConversationModelsRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/conversations/models") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewCreateConversationModelRequest calls the generic CreateConversationModel builder with application/json body +func NewCreateConversationModelRequest(server string, body CreateConversationModelJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewCreateConversationModelRequestWithBody(server, "application/json", bodyReader) +} + +// NewCreateConversationModelRequestWithBody generates requests for CreateConversationModel with any type of body +func NewCreateConversationModelRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/conversations/models") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewDebugRequest generates requests for Debug func NewDebugRequest(server string) (*http.Request, error) { var err error @@ -5023,6 +5134,14 @@ type ClientWithResponsesInterface interface { UpsertSearchSynonymWithResponse(ctx context.Context, collectionName string, synonymId string, body UpsertSearchSynonymJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertSearchSynonymResponse, error) + // RetrieveAllConversationModelsWithResponse request + RetrieveAllConversationModelsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAllConversationModelsResponse, error) + + // CreateConversationModelWithBodyWithResponse request with any body + CreateConversationModelWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateConversationModelResponse, error) + + CreateConversationModelWithResponse(ctx context.Context, body CreateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateConversationModelResponse, error) + // DebugWithResponse request DebugWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*DebugResponse, error) @@ -5806,6 +5925,51 @@ func (r UpsertSearchSynonymResponse) StatusCode() int { return 0 } +type RetrieveAllConversationModelsResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *[]*ConversationModelResponse +} + +// Status returns HTTPResponse.Status +func (r RetrieveAllConversationModelsResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r RetrieveAllConversationModelsResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type CreateConversationModelResponse struct { + Body []byte + HTTPResponse *http.Response + JSON201 *ConversationModelResponse + JSON400 *ApiResponse +} + +// Status returns HTTPResponse.Status +func (r CreateConversationModelResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CreateConversationModelResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type DebugResponse struct { Body []byte HTTPResponse *http.Response @@ -6599,6 +6763,32 @@ func (c *ClientWithResponses) UpsertSearchSynonymWithResponse(ctx context.Contex return ParseUpsertSearchSynonymResponse(rsp) } +// RetrieveAllConversationModelsWithResponse request returning *RetrieveAllConversationModelsResponse +func (c *ClientWithResponses) RetrieveAllConversationModelsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAllConversationModelsResponse, error) { + rsp, err := c.RetrieveAllConversationModels(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseRetrieveAllConversationModelsResponse(rsp) +} + +// CreateConversationModelWithBodyWithResponse request with arbitrary body returning *CreateConversationModelResponse +func (c *ClientWithResponses) CreateConversationModelWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateConversationModelResponse, error) { + rsp, err := c.CreateConversationModelWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateConversationModelResponse(rsp) +} + +func (c *ClientWithResponses) CreateConversationModelWithResponse(ctx context.Context, body CreateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateConversationModelResponse, error) { + rsp, err := c.CreateConversationModel(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateConversationModelResponse(rsp) +} + // DebugWithResponse request returning *DebugResponse func (c *ClientWithResponses) DebugWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*DebugResponse, error) { rsp, err := c.Debug(ctx, reqEditors...) @@ -7823,6 +8013,65 @@ func ParseUpsertSearchSynonymResponse(rsp *http.Response) (*UpsertSearchSynonymR return response, nil } +// ParseRetrieveAllConversationModelsResponse parses an HTTP response from a RetrieveAllConversationModelsWithResponse call +func ParseRetrieveAllConversationModelsResponse(rsp *http.Response) (*RetrieveAllConversationModelsResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RetrieveAllConversationModelsResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest []*ConversationModelResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseCreateConversationModelResponse parses an HTTP response from a CreateConversationModelWithResponse call +func ParseCreateConversationModelResponse(rsp *http.Response) (*CreateConversationModelResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CreateConversationModelResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: + var dest ConversationModelResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON201 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest ApiResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + + return response, nil +} + // ParseDebugResponse parses an HTTP response from a DebugWithResponse call func ParseDebugResponse(rsp *http.Response) (*DebugResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index 8b38c18..8227da4 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -256,6 +256,41 @@ components: required: - fields type: object + ConversationModelResponse: + allOf: + - $ref: '#/components/schemas/ConversationModelSchema' + - properties: + id: + readOnly: true + type: string + type: object + ConversationModelSchema: + properties: + account_id: + description: LLM service's account ID (only applicable for Cloudflare) + type: string + api_key: + description: The LLM service's API Key + type: string + max_bytes: + description: | + The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. + type: integer + model_name: + description: Name of the LLM model offered by OpenAI, Cloudflare or vLLM + type: string + system_prompt: + description: The system prompt that contains special instructions to the LLM + type: string + vllm_url: + description: URL of vLLM service + type: string + required: + - model_name + - api_key + - system_prompt + - max_bytes + type: object ErrorResponse: properties: message: @@ -2420,6 +2455,46 @@ paths: summary: Create or update a synonym tags: - documents + /conversations/models: + get: + description: Retrieve all conversation models + operationId: retrieveAllConversationModels + responses: + 200: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/ConversationModelResponse' + type: array + x-go-type: '[]*ConversationModelResponse' + description: List of all conversation models + summary: List all conversation models + tags: + - conversations + post: + description: Create a Conversation Model + operationId: createConversationModel + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + responses: + 201: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelResponse' + description: Created Conversation Model + 400: + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + description: Bad request, see error message for details + tags: + - conversations /debug: get: description: Print debugging information @@ -3122,3 +3197,8 @@ tags: description: Find out more url: https://typesense.org/docs/26.0/api/search.html#presets name: presets + - description: Conversational Search (RAG) + externalDocs: + description: Find out more + url: https://typesense.org/docs/26.0/api/conversational-search-rag.html + name: conversations diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index 309d760..5ebd57f 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -176,6 +176,49 @@ type CollectionUpdateSchema struct { Fields []Field `json:"fields"` } +// ConversationModelResponse defines model for ConversationModelResponse. +type ConversationModelResponse struct { + // AccountId LLM service's account ID (only applicable for Cloudflare) + AccountId *string `json:"account_id,omitempty"` + + // ApiKey The LLM service's API Key + ApiKey string `json:"api_key"` + Id *string `json:"id,omitempty"` + + // MaxBytes The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. + MaxBytes int `json:"max_bytes"` + + // ModelName Name of the LLM model offered by OpenAI, Cloudflare or vLLM + ModelName string `json:"model_name"` + + // SystemPrompt The system prompt that contains special instructions to the LLM + SystemPrompt string `json:"system_prompt"` + + // VllmUrl URL of vLLM service + VllmUrl *string `json:"vllm_url,omitempty"` +} + +// ConversationModelSchema defines model for ConversationModelSchema. +type ConversationModelSchema struct { + // AccountId LLM service's account ID (only applicable for Cloudflare) + AccountId *string `json:"account_id,omitempty"` + + // ApiKey The LLM service's API Key + ApiKey string `json:"api_key"` + + // MaxBytes The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. + MaxBytes int `json:"max_bytes"` + + // ModelName Name of the LLM model offered by OpenAI, Cloudflare or vLLM + ModelName string `json:"model_name"` + + // SystemPrompt The system prompt that contains special instructions to the LLM + SystemPrompt string `json:"system_prompt"` + + // VllmUrl URL of vLLM service + VllmUrl *string `json:"vllm_url,omitempty"` +} + // FacetCounts defines model for FacetCounts. type FacetCounts struct { Counts *[]struct { @@ -1164,6 +1207,9 @@ type UpsertSearchOverrideJSONRequestBody = SearchOverrideSchema // UpsertSearchSynonymJSONRequestBody defines body for UpsertSearchSynonym for application/json ContentType. type UpsertSearchSynonymJSONRequestBody = SearchSynonymSchema +// CreateConversationModelJSONRequestBody defines body for CreateConversationModel for application/json ContentType. +type CreateConversationModelJSONRequestBody = ConversationModelSchema + // CreateKeyJSONRequestBody defines body for CreateKey for application/json ContentType. type CreateKeyJSONRequestBody = ApiKeySchema diff --git a/typesense/conversation_models.go b/typesense/conversation_models.go new file mode 100644 index 0000000..0cf87bb --- /dev/null +++ b/typesense/conversation_models.go @@ -0,0 +1,40 @@ +package typesense + +import ( + "context" + + "github.com/typesense/typesense-go/typesense/api" +) + +// ConversationModelsInterface is a type for ConversationModels API operations +type ConversationModelsInterface interface { + Create(ctx context.Context, conversationModelSchema *api.ConversationModelSchema) (*api.ConversationModelResponse, error) + Retrieve(ctx context.Context) ([]*api.ConversationModelResponse, error) +} + +// conversationModels is internal implementation of ConversationModelsInterface +type conversationModels struct { + apiClient APIClientInterface +} + +func (a *conversationModels) Create(ctx context.Context, conversationModelSchema *api.ConversationModelSchema) (*api.ConversationModelResponse, error) { + response, err := a.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*conversationModelSchema)) + if err != nil { + return nil, err + } + if response.JSON201 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON201, nil +} + +func (a *conversationModels) Retrieve(ctx context.Context) ([]*api.ConversationModelResponse, error) { + response, err := a.apiClient.RetrieveAllConversationModelsWithResponse(ctx) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return *response.JSON200, nil +} diff --git a/typesense/mocks/mock_client.go b/typesense/mocks/mock_client.go index 5d66b65..f2edd3b 100644 --- a/typesense/mocks/mock_client.go +++ b/typesense/mocks/mock_client.go @@ -202,6 +202,86 @@ func (mr *MockAPIClientInterfaceMockRecorder) CreateCollectionWithResponse(ctx, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCollectionWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).CreateCollectionWithResponse), varargs...) } +// CreateConversationModel mocks base method. +func (m *MockAPIClientInterface) CreateConversationModel(ctx context.Context, body api.CreateConversationModelJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CreateConversationModel", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateConversationModel indicates an expected call of CreateConversationModel. +func (mr *MockAPIClientInterfaceMockRecorder) CreateConversationModel(ctx, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateConversationModel", reflect.TypeOf((*MockAPIClientInterface)(nil).CreateConversationModel), varargs...) +} + +// CreateConversationModelWithBody mocks base method. +func (m *MockAPIClientInterface) CreateConversationModelWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, contentType, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CreateConversationModelWithBody", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateConversationModelWithBody indicates an expected call of CreateConversationModelWithBody. +func (mr *MockAPIClientInterfaceMockRecorder) CreateConversationModelWithBody(ctx, contentType, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, contentType, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateConversationModelWithBody", reflect.TypeOf((*MockAPIClientInterface)(nil).CreateConversationModelWithBody), varargs...) +} + +// CreateConversationModelWithBodyWithResponse mocks base method. +func (m *MockAPIClientInterface) CreateConversationModelWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*api.CreateConversationModelResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, contentType, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CreateConversationModelWithBodyWithResponse", varargs...) + ret0, _ := ret[0].(*api.CreateConversationModelResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateConversationModelWithBodyWithResponse indicates an expected call of CreateConversationModelWithBodyWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) CreateConversationModelWithBodyWithResponse(ctx, contentType, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, contentType, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateConversationModelWithBodyWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).CreateConversationModelWithBodyWithResponse), varargs...) +} + +// CreateConversationModelWithResponse mocks base method. +func (m *MockAPIClientInterface) CreateConversationModelWithResponse(ctx context.Context, body api.CreateConversationModelJSONRequestBody, reqEditors ...api.RequestEditorFn) (*api.CreateConversationModelResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CreateConversationModelWithResponse", varargs...) + ret0, _ := ret[0].(*api.CreateConversationModelResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateConversationModelWithResponse indicates an expected call of CreateConversationModelWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) CreateConversationModelWithResponse(ctx, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateConversationModelWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).CreateConversationModelWithResponse), varargs...) +} + // CreateKey mocks base method. func (m *MockAPIClientInterface) CreateKey(ctx context.Context, body api.CreateKeyJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -1522,6 +1602,46 @@ func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllPresetsWithResponse(ctx return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllPresetsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllPresetsWithResponse), varargs...) } +// RetrieveAllConversationModels mocks base method. +func (m *MockAPIClientInterface) RetrieveAllConversationModels(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RetrieveAllConversationModels", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RetrieveAllConversationModels indicates an expected call of RetrieveAllConversationModels. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationModels(ctx any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationModels", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationModels), varargs...) +} + +// RetrieveAllConversationModelsWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrieveAllConversationModelsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveAllConversationModelsResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RetrieveAllConversationModelsWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrieveAllConversationModelsResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RetrieveAllConversationModelsWithResponse indicates an expected call of RetrieveAllConversationModelsWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationModelsWithResponse(ctx any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationModelsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationModelsWithResponse), varargs...) +} + // RetrieveAnalyticsRule mocks base method. func (m *MockAPIClientInterface) RetrieveAnalyticsRule(ctx context.Context, ruleName string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() From c4e0d588ab6f45c9e6f6d1853b78e1e4b2c076c9 Mon Sep 17 00:00:00 2001 From: Hayden Date: Tue, 9 Jul 2024 16:51:34 +0700 Subject: [PATCH 02/19] feat: conversations --- typesense/api/client_gen.go | 102 ++++++++++++++++++++++++++ typesense/api/generator/generator.yml | 38 ++++++++++ typesense/api/generator/openapi.yml | 80 +++++++++++++++++++- typesense/api/types_gen.go | 15 ++++ typesense/client.go | 4 + typesense/conversation_models.go | 8 +- typesense/conversations.go | 33 +++++++++ typesense/mocks/mock_client.go | 40 ++++++++++ 8 files changed, 315 insertions(+), 5 deletions(-) create mode 100644 typesense/conversations.go diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index bf2b32d..8f72bc7 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -202,6 +202,9 @@ type ClientInterface interface { UpsertSearchSynonym(ctx context.Context, collectionName string, synonymId string, body UpsertSearchSynonymJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // RetrieveAllConversations request + RetrieveAllConversations(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + // RetrieveAllConversationModels request RetrieveAllConversationModels(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -768,6 +771,18 @@ func (c *Client) UpsertSearchSynonym(ctx context.Context, collectionName string, return c.Client.Do(req) } +func (c *Client) RetrieveAllConversations(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRetrieveAllConversationsRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) RetrieveAllConversationModels(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewRetrieveAllConversationModelsRequest(c.Server) if err != nil { @@ -3386,6 +3401,33 @@ func NewUpsertSearchSynonymRequestWithBody(server string, collectionName string, return req, nil } +// NewRetrieveAllConversationsRequest generates requests for RetrieveAllConversations +func NewRetrieveAllConversationsRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/conversations") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewRetrieveAllConversationModelsRequest generates requests for RetrieveAllConversationModels func NewRetrieveAllConversationModelsRequest(server string) (*http.Request, error) { var err error @@ -5134,6 +5176,9 @@ type ClientWithResponsesInterface interface { UpsertSearchSynonymWithResponse(ctx context.Context, collectionName string, synonymId string, body UpsertSearchSynonymJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertSearchSynonymResponse, error) + // RetrieveAllConversationsWithResponse request + RetrieveAllConversationsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAllConversationsResponse, error) + // RetrieveAllConversationModelsWithResponse request RetrieveAllConversationModelsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAllConversationModelsResponse, error) @@ -5925,6 +5970,28 @@ func (r UpsertSearchSynonymResponse) StatusCode() int { return 0 } +type RetrieveAllConversationsResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ConversationsRetrieveSchema +} + +// Status returns HTTPResponse.Status +func (r RetrieveAllConversationsResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r RetrieveAllConversationsResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type RetrieveAllConversationModelsResponse struct { Body []byte HTTPResponse *http.Response @@ -6763,6 +6830,15 @@ func (c *ClientWithResponses) UpsertSearchSynonymWithResponse(ctx context.Contex return ParseUpsertSearchSynonymResponse(rsp) } +// RetrieveAllConversationsWithResponse request returning *RetrieveAllConversationsResponse +func (c *ClientWithResponses) RetrieveAllConversationsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAllConversationsResponse, error) { + rsp, err := c.RetrieveAllConversations(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseRetrieveAllConversationsResponse(rsp) +} + // RetrieveAllConversationModelsWithResponse request returning *RetrieveAllConversationModelsResponse func (c *ClientWithResponses) RetrieveAllConversationModelsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAllConversationModelsResponse, error) { rsp, err := c.RetrieveAllConversationModels(ctx, reqEditors...) @@ -8013,6 +8089,32 @@ func ParseUpsertSearchSynonymResponse(rsp *http.Response) (*UpsertSearchSynonymR return response, nil } +// ParseRetrieveAllConversationsResponse parses an HTTP response from a RetrieveAllConversationsWithResponse call +func ParseRetrieveAllConversationsResponse(rsp *http.Response) (*RetrieveAllConversationsResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RetrieveAllConversationsResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ConversationsRetrieveSchema + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + // ParseRetrieveAllConversationModelsResponse parses an HTTP response from a RetrieveAllConversationModelsWithResponse call func ParseRetrieveAllConversationModelsResponse(rsp *http.Response) (*RetrieveAllConversationModelsResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index 8227da4..66468d0 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -291,6 +291,30 @@ components: - system_prompt - max_bytes type: object + ConversationSchema: + properties: + conversation: + items: + type: object + type: array + id: + type: integer + last_updated: + type: integer + ttl: + description: Time to live. Conversations are stored by default for 24 hours, and then purged. + type: integer + type: object + ConversationsRetrieveSchema: + properties: + conversations: + items: + $ref: '#/components/schemas/ConversationSchema' + type: array + x-go-type: '[]*ConversationSchema' + required: + - conversations + type: object ErrorResponse: properties: message: @@ -2455,6 +2479,20 @@ paths: summary: Create or update a synonym tags: - documents + /conversations: + get: + description: Retrieve all past conversations + operationId: retrieveAllConversations + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationsRetrieveSchema' + description: List of all past conversations + summary: List all past conversations + tags: + - conversations /conversations/models: get: description: Retrieve all conversation models diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index 249a696..16545ea 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -879,7 +879,61 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/ApiResponse" + $ref: '#/components/schemas/ApiResponse' + /conversations: + get: + description: Retrieve all past conversations + operationId: retrieveAllConversations + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationsRetrieveSchema' + description: List of all past conversations + summary: List all past conversations + tags: + - conversations + /conversations/models: + get: + description: Retrieve all conversation models + operationId: retrieveAllConversationModels + responses: + 200: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/ConversationModelResponse' + type: array + x-go-type: '[]*ConversationModelResponse' + description: List of all conversation models + summary: List all conversation models + tags: + - conversations + post: + description: Create a Conversation Model + operationId: createConversationModel + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + responses: + 201: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelResponse' + description: Created Conversation Model + 400: + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + description: Bad request, see error message for details + tags: + - conversations /keys: get: tags: @@ -2996,6 +3050,30 @@ components: - stopwords example: | {"stopwords": [{"id": "countries", "stopwords": ["Germany", "France", "Italy"], "locale": "en"}]} + ConversationSchema: + properties: + id: + type: integer + conversation: + items: + type: object + type: array + last_updated: + type: integer + ttl: + description: Time to live. Conversations are stored by default for 24 hours, and then purged. + type: integer + type: object + ConversationsRetrieveSchema: + type: object + required: + - conversations + properties: + conversations: + type: array + items: + $ref: '#/components/schemas/ConversationSchema' + x-go-type: '[]*ConversationSchema' PresetUpsertSchema: properties: value: diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index 5ebd57f..01c613e 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -219,6 +219,21 @@ type ConversationModelSchema struct { VllmUrl *string `json:"vllm_url,omitempty"` } +// ConversationSchema defines model for ConversationSchema. +type ConversationSchema struct { + Conversation *[]map[string]interface{} `json:"conversation,omitempty"` + Id *int `json:"id,omitempty"` + LastUpdated *int `json:"last_updated,omitempty"` + + // Ttl Time to live. Conversations are stored by default for 24 hours, and then purged. + Ttl *int `json:"ttl,omitempty"` +} + +// ConversationsRetrieveSchema defines model for ConversationsRetrieveSchema. +type ConversationsRetrieveSchema struct { + Conversations []*ConversationSchema `json:"conversations"` +} + // FacetCounts defines model for FacetCounts. type FacetCounts struct { Counts *[]struct { diff --git a/typesense/client.go b/typesense/client.go index fe714c1..2cf897a 100644 --- a/typesense/client.go +++ b/typesense/client.go @@ -44,6 +44,10 @@ func (c *Client) Alias(aliasName string) AliasInterface { return &alias{apiClient: c.apiClient, name: aliasName} } +func (c *Client) Conversations() ConversationsInterface { + return &conversations{apiClient: c.apiClient} +} + func (c *Client) Keys() KeysInterface { return &keys{apiClient: c.apiClient} } diff --git a/typesense/conversation_models.go b/typesense/conversation_models.go index 0cf87bb..f802208 100644 --- a/typesense/conversation_models.go +++ b/typesense/conversation_models.go @@ -17,8 +17,8 @@ type conversationModels struct { apiClient APIClientInterface } -func (a *conversationModels) Create(ctx context.Context, conversationModelSchema *api.ConversationModelSchema) (*api.ConversationModelResponse, error) { - response, err := a.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*conversationModelSchema)) +func (c *conversationModels) Create(ctx context.Context, conversationModelSchema *api.ConversationModelSchema) (*api.ConversationModelResponse, error) { + response, err := c.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*conversationModelSchema)) if err != nil { return nil, err } @@ -28,8 +28,8 @@ func (a *conversationModels) Create(ctx context.Context, conversationModelSchema return response.JSON201, nil } -func (a *conversationModels) Retrieve(ctx context.Context) ([]*api.ConversationModelResponse, error) { - response, err := a.apiClient.RetrieveAllConversationModelsWithResponse(ctx) +func (c *conversationModels) Retrieve(ctx context.Context) ([]*api.ConversationModelResponse, error) { + response, err := c.apiClient.RetrieveAllConversationModelsWithResponse(ctx) if err != nil { return nil, err } diff --git a/typesense/conversations.go b/typesense/conversations.go new file mode 100644 index 0000000..059d625 --- /dev/null +++ b/typesense/conversations.go @@ -0,0 +1,33 @@ +package typesense + +import ( + "context" + + "github.com/typesense/typesense-go/typesense/api" +) + +// ConversationsInterface is a type for Conversations API operations +type ConversationsInterface interface { + Retrieve(ctx context.Context) ([]*api.ConversationSchema, error) + Models() ConversationModelsInterface +} + +// conversations is internal implementation of ConversationsInterface +type conversations struct { + apiClient APIClientInterface +} + +func (c *conversations) Retrieve(ctx context.Context) ([]*api.ConversationSchema, error) { + response, err := c.apiClient.RetrieveAllConversationsWithResponse(ctx) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON200.Conversations, nil +} + +func (c *conversations) Models() ConversationModelsInterface { + return &conversationModels{apiClient: c.apiClient} +} diff --git a/typesense/mocks/mock_client.go b/typesense/mocks/mock_client.go index f2edd3b..53113d5 100644 --- a/typesense/mocks/mock_client.go +++ b/typesense/mocks/mock_client.go @@ -1642,6 +1642,46 @@ func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationModelsWithR return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationModelsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationModelsWithResponse), varargs...) } +// RetrieveAllConversations mocks base method. +func (m *MockAPIClientInterface) RetrieveAllConversations(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RetrieveAllConversations", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RetrieveAllConversations indicates an expected call of RetrieveAllConversations. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversations(ctx any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversations", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversations), varargs...) +} + +// RetrieveAllConversationsWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrieveAllConversationsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveAllConversationsResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RetrieveAllConversationsWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrieveAllConversationsResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RetrieveAllConversationsWithResponse indicates an expected call of RetrieveAllConversationsWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationsWithResponse(ctx any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationsWithResponse), varargs...) +} + // RetrieveAnalyticsRule mocks base method. func (m *MockAPIClientInterface) RetrieveAnalyticsRule(ctx context.Context, ruleName string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() From 4ed8b9d94d4cdf429fca4f61137ef15c58836bcb Mon Sep 17 00:00:00 2001 From: Hayden Date: Tue, 9 Jul 2024 18:04:47 +0700 Subject: [PATCH 03/19] feat: retrieve, update, delete a conversation --- typesense/api/client_gen.go | 364 ++++++++++++++++++++++++++ typesense/api/generator/generator.yml | 84 ++++++ typesense/api/generator/openapi.yml | 84 ++++++ typesense/api/types_gen.go | 16 +- typesense/client.go | 4 + typesense/conversation.go | 51 ++++ typesense/mocks/mock_client.go | 160 +++++++++++ 7 files changed, 762 insertions(+), 1 deletion(-) create mode 100644 typesense/conversation.go diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index 8f72bc7..6f73d2e 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -213,6 +213,17 @@ type ClientInterface interface { CreateConversationModel(ctx context.Context, body CreateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // DeleteConversation request + DeleteConversation(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*http.Response, error) + + // RetrieveConversation request + RetrieveConversation(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*http.Response, error) + + // UpdateConversationWithBody request with any body + UpdateConversationWithBody(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + UpdateConversation(ctx context.Context, conversationId int64, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // Debug request Debug(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -819,6 +830,54 @@ func (c *Client) CreateConversationModel(ctx context.Context, body CreateConvers return c.Client.Do(req) } +func (c *Client) DeleteConversation(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteConversationRequest(c.Server, conversationId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) RetrieveConversation(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRetrieveConversationRequest(c.Server, conversationId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpdateConversationWithBody(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateConversationRequestWithBody(c.Server, conversationId, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpdateConversation(ctx context.Context, conversationId int64, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateConversationRequest(c.Server, conversationId, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) Debug(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewDebugRequest(c.Server) if err != nil { @@ -3495,6 +3554,121 @@ func NewCreateConversationModelRequestWithBody(server string, contentType string return req, nil } +// NewDeleteConversationRequest generates requests for DeleteConversation +func NewDeleteConversationRequest(server string, conversationId int64) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "conversationId", runtime.ParamLocationPath, conversationId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/conversations/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("DELETE", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewRetrieveConversationRequest generates requests for RetrieveConversation +func NewRetrieveConversationRequest(server string, conversationId int64) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "conversationId", runtime.ParamLocationPath, conversationId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/conversations/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewUpdateConversationRequest calls the generic UpdateConversation builder with application/json body +func NewUpdateConversationRequest(server string, conversationId int64, body UpdateConversationJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewUpdateConversationRequestWithBody(server, conversationId, "application/json", bodyReader) +} + +// NewUpdateConversationRequestWithBody generates requests for UpdateConversation with any type of body +func NewUpdateConversationRequestWithBody(server string, conversationId int64, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "conversationId", runtime.ParamLocationPath, conversationId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/conversations/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("PUT", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewDebugRequest generates requests for Debug func NewDebugRequest(server string) (*http.Request, error) { var err error @@ -5187,6 +5361,17 @@ type ClientWithResponsesInterface interface { CreateConversationModelWithResponse(ctx context.Context, body CreateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateConversationModelResponse, error) + // DeleteConversationWithResponse request + DeleteConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*DeleteConversationResponse, error) + + // RetrieveConversationWithResponse request + RetrieveConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*RetrieveConversationResponse, error) + + // UpdateConversationWithBodyWithResponse request with any body + UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) + + UpdateConversationWithResponse(ctx context.Context, conversationId int64, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) + // DebugWithResponse request DebugWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*DebugResponse, error) @@ -6037,6 +6222,72 @@ func (r CreateConversationModelResponse) StatusCode() int { return 0 } +type DeleteConversationResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ConversationDeleteSchema +} + +// Status returns HTTPResponse.Status +func (r DeleteConversationResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r DeleteConversationResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type RetrieveConversationResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *[]*ConversationSchema +} + +// Status returns HTTPResponse.Status +func (r RetrieveConversationResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r RetrieveConversationResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type UpdateConversationResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ConversationUpdateSchema +} + +// Status returns HTTPResponse.Status +func (r UpdateConversationResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r UpdateConversationResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type DebugResponse struct { Body []byte HTTPResponse *http.Response @@ -6865,6 +7116,41 @@ func (c *ClientWithResponses) CreateConversationModelWithResponse(ctx context.Co return ParseCreateConversationModelResponse(rsp) } +// DeleteConversationWithResponse request returning *DeleteConversationResponse +func (c *ClientWithResponses) DeleteConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*DeleteConversationResponse, error) { + rsp, err := c.DeleteConversation(ctx, conversationId, reqEditors...) + if err != nil { + return nil, err + } + return ParseDeleteConversationResponse(rsp) +} + +// RetrieveConversationWithResponse request returning *RetrieveConversationResponse +func (c *ClientWithResponses) RetrieveConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*RetrieveConversationResponse, error) { + rsp, err := c.RetrieveConversation(ctx, conversationId, reqEditors...) + if err != nil { + return nil, err + } + return ParseRetrieveConversationResponse(rsp) +} + +// UpdateConversationWithBodyWithResponse request with arbitrary body returning *UpdateConversationResponse +func (c *ClientWithResponses) UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) { + rsp, err := c.UpdateConversationWithBody(ctx, conversationId, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpdateConversationResponse(rsp) +} + +func (c *ClientWithResponses) UpdateConversationWithResponse(ctx context.Context, conversationId int64, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) { + rsp, err := c.UpdateConversation(ctx, conversationId, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpdateConversationResponse(rsp) +} + // DebugWithResponse request returning *DebugResponse func (c *ClientWithResponses) DebugWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*DebugResponse, error) { rsp, err := c.Debug(ctx, reqEditors...) @@ -8174,6 +8460,84 @@ func ParseCreateConversationModelResponse(rsp *http.Response) (*CreateConversati return response, nil } +// ParseDeleteConversationResponse parses an HTTP response from a DeleteConversationWithResponse call +func ParseDeleteConversationResponse(rsp *http.Response) (*DeleteConversationResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &DeleteConversationResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ConversationDeleteSchema + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseRetrieveConversationResponse parses an HTTP response from a RetrieveConversationWithResponse call +func ParseRetrieveConversationResponse(rsp *http.Response) (*RetrieveConversationResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RetrieveConversationResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest []*ConversationSchema + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseUpdateConversationResponse parses an HTTP response from a UpdateConversationWithResponse call +func ParseUpdateConversationResponse(rsp *http.Response) (*UpdateConversationResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &UpdateConversationResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ConversationUpdateSchema + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + // ParseDebugResponse parses an HTTP response from a DebugWithResponse call func ParseDebugResponse(rsp *http.Response) (*DebugResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index 66468d0..906665c 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -256,6 +256,10 @@ components: required: - fields type: object + ConversationDeleteSchema: + properties: + id: + type: integer ConversationModelResponse: allOf: - $ref: '#/components/schemas/ConversationModelSchema' @@ -304,7 +308,15 @@ components: ttl: description: Time to live. Conversations are stored by default for 24 hours, and then purged. type: integer + required: + - id + - ttl type: object + ConversationUpdateSchema: + properties: + ttl: + description: Time to live. Conversations are stored by default for 24 hours, and then purged. + type: integer ConversationsRetrieveSchema: properties: conversations: @@ -2493,6 +2505,78 @@ paths: summary: List all past conversations tags: - conversations + /conversations/{conversationId}: + delete: + description: Delete a past conversation + operationId: deleteConversation + parameters: + - description: The id of the conversation to delete + in: path + name: conversationId + required: true + schema: + format: int64 + type: integer + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationDeleteSchema' + description: The conversation was successfully deleted + summary: Delete a past conversation + tags: + - conversations + get: + description: Retrieve a conversation + operationId: retrieveConversation + parameters: + - description: The id of the conversation to retrieve + in: path + name: conversationId + required: true + schema: + format: int64 + type: integer + responses: + 200: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/ConversationSchema' + type: array + x-go-type: '[]*ConversationSchema' + description: A past conversation + summary: Retrieve a past conversation + tags: + - conversations + put: + description: Update the TTL for a conversation + operationId: updateConversation + parameters: + - description: The id of the conversation to update + in: path + name: conversationId + required: true + schema: + format: int64 + type: integer + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationUpdateSchema' + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationUpdateSchema' + description: The conversation was successfully updated + summary: Update the TTL for a past conversation + tags: + - conversations /conversations/models: get: description: Retrieve all conversation models diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index 16545ea..512dc0e 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -894,6 +894,78 @@ paths: summary: List all past conversations tags: - conversations + /conversations/{conversationId}: + get: + description: Retrieve a conversation + operationId: retrieveConversation + parameters: + - name: conversationId + in: path + description: The id of the conversation to retrieve + required: true + schema: + type: integer + format: int64 + responses: + 200: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/ConversationSchema' + type: array + x-go-type: '[]*ConversationSchema' + description: A past conversation + summary: Retrieve a past conversation + tags: + - conversations + put: + description: Update the TTL for a conversation + operationId: updateConversation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationUpdateSchema' + parameters: + - name: conversationId + in: path + description: The id of the conversation to update + required: true + schema: + type: integer + format: int64 + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationUpdateSchema' + description: The conversation was successfully updated + summary: Update the TTL for a past conversation + tags: + - conversations + delete: + description: Delete a past conversation + operationId: deleteConversation + parameters: + - name: conversationId + in: path + description: The id of the conversation to delete + required: true + schema: + type: integer + format: int64 + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationDeleteSchema' + description: The conversation was successfully deleted + summary: Delete a past conversation + tags: + - conversations /conversations/models: get: description: Retrieve all conversation models @@ -3064,6 +3136,18 @@ components: description: Time to live. Conversations are stored by default for 24 hours, and then purged. type: integer type: object + required: + - id + - ttl + ConversationUpdateSchema: + properties: + ttl: + description: Time to live. Conversations are stored by default for 24 hours, and then purged. + type: integer + ConversationDeleteSchema: + properties: + id: + type: integer ConversationsRetrieveSchema: type: object required: diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index 01c613e..af5dafe 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -176,6 +176,11 @@ type CollectionUpdateSchema struct { Fields []Field `json:"fields"` } +// ConversationDeleteSchema defines model for ConversationDeleteSchema. +type ConversationDeleteSchema struct { + Id *int `json:"id,omitempty"` +} + // ConversationModelResponse defines model for ConversationModelResponse. type ConversationModelResponse struct { // AccountId LLM service's account ID (only applicable for Cloudflare) @@ -222,9 +227,15 @@ type ConversationModelSchema struct { // ConversationSchema defines model for ConversationSchema. type ConversationSchema struct { Conversation *[]map[string]interface{} `json:"conversation,omitempty"` - Id *int `json:"id,omitempty"` + Id int `json:"id"` LastUpdated *int `json:"last_updated,omitempty"` + // Ttl Time to live. Conversations are stored by default for 24 hours, and then purged. + Ttl int `json:"ttl"` +} + +// ConversationUpdateSchema defines model for ConversationUpdateSchema. +type ConversationUpdateSchema struct { // Ttl Time to live. Conversations are stored by default for 24 hours, and then purged. Ttl *int `json:"ttl,omitempty"` } @@ -1225,6 +1236,9 @@ type UpsertSearchSynonymJSONRequestBody = SearchSynonymSchema // CreateConversationModelJSONRequestBody defines body for CreateConversationModel for application/json ContentType. type CreateConversationModelJSONRequestBody = ConversationModelSchema +// UpdateConversationJSONRequestBody defines body for UpdateConversation for application/json ContentType. +type UpdateConversationJSONRequestBody = ConversationUpdateSchema + // CreateKeyJSONRequestBody defines body for CreateKey for application/json ContentType. type CreateKeyJSONRequestBody = ApiKeySchema diff --git a/typesense/client.go b/typesense/client.go index 2cf897a..ac31ab1 100644 --- a/typesense/client.go +++ b/typesense/client.go @@ -48,6 +48,10 @@ func (c *Client) Conversations() ConversationsInterface { return &conversations{apiClient: c.apiClient} } +func (c *Client) Conversation(conversationId int64) ConversationInterface { + return &conversation{apiClient: c.apiClient, conversationId: conversationId} +} + func (c *Client) Keys() KeysInterface { return &keys{apiClient: c.apiClient} } diff --git a/typesense/conversation.go b/typesense/conversation.go new file mode 100644 index 0000000..81e84bc --- /dev/null +++ b/typesense/conversation.go @@ -0,0 +1,51 @@ +package typesense + +import ( + "context" + + "github.com/typesense/typesense-go/typesense/api" +) + +type ConversationInterface interface { + Retrieve(ctx context.Context) ([]*api.ConversationSchema, error) + Update(ctx context.Context, conversation *api.ConversationUpdateSchema) (*api.ConversationUpdateSchema, error) + Delete(ctx context.Context) (*api.ConversationDeleteSchema, error) +} + +type conversation struct { + apiClient APIClientInterface + conversationId int64 +} + +func (c *conversation) Retrieve(ctx context.Context) ([]*api.ConversationSchema, error) { + response, err := c.apiClient.RetrieveConversationWithResponse(ctx, c.conversationId) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return *response.JSON200, nil +} + +func (c *conversation) Update(ctx context.Context, conversation *api.ConversationUpdateSchema) (*api.ConversationUpdateSchema, error) { + response, err := c.apiClient.UpdateConversationWithResponse(ctx, c.conversationId, api.UpdateConversationJSONRequestBody(*conversation)) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON200, nil +} + +func (c *conversation) Delete(ctx context.Context) (*api.ConversationDeleteSchema, error) { + response, err := c.apiClient.DeleteConversationWithResponse(ctx, c.conversationId) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON200, nil +} diff --git a/typesense/mocks/mock_client.go b/typesense/mocks/mock_client.go index 53113d5..1eccfc8 100644 --- a/typesense/mocks/mock_client.go +++ b/typesense/mocks/mock_client.go @@ -522,6 +522,46 @@ func (mr *MockAPIClientInterfaceMockRecorder) DeleteCollectionWithResponse(ctx, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCollectionWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).DeleteCollectionWithResponse), varargs...) } +// DeleteConversation mocks base method. +func (m *MockAPIClientInterface) DeleteConversation(ctx context.Context, conversationId int64, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, conversationId} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "DeleteConversation", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteConversation indicates an expected call of DeleteConversation. +func (mr *MockAPIClientInterfaceMockRecorder) DeleteConversation(ctx, conversationId any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, conversationId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).DeleteConversation), varargs...) +} + +// DeleteConversationWithResponse mocks base method. +func (m *MockAPIClientInterface) DeleteConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...api.RequestEditorFn) (*api.DeleteConversationResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, conversationId} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "DeleteConversationWithResponse", varargs...) + ret0, _ := ret[0].(*api.DeleteConversationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteConversationWithResponse indicates an expected call of DeleteConversationWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) DeleteConversationWithResponse(ctx, conversationId any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, conversationId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConversationWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).DeleteConversationWithResponse), varargs...) +} + // DeleteDocument mocks base method. func (m *MockAPIClientInterface) DeleteDocument(ctx context.Context, collectionName, documentId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -1842,6 +1882,46 @@ func (mr *MockAPIClientInterfaceMockRecorder) RetrievePresetWithResponse(ctx, pr return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrievePresetWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrievePresetWithResponse), varargs...) } +// RetrieveConversation mocks base method. +func (m *MockAPIClientInterface) RetrieveConversation(ctx context.Context, conversationId int64, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, conversationId} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RetrieveConversation", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RetrieveConversation indicates an expected call of RetrieveConversation. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversation(ctx, conversationId any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, conversationId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversation), varargs...) +} + +// RetrieveConversationWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrieveConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...api.RequestEditorFn) (*api.RetrieveConversationResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, conversationId} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RetrieveConversationWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrieveConversationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RetrieveConversationWithResponse indicates an expected call of RetrieveConversationWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationWithResponse(ctx, conversationId any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, conversationId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationWithResponse), varargs...) +} + // RetrieveStopwordsSet mocks base method. func (m *MockAPIClientInterface) RetrieveStopwordsSet(ctx context.Context, setId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -2082,6 +2162,86 @@ func (mr *MockAPIClientInterfaceMockRecorder) UpdateCollectionWithResponse(ctx, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateCollectionWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateCollectionWithResponse), varargs...) } +// UpdateConversation mocks base method. +func (m *MockAPIClientInterface) UpdateConversation(ctx context.Context, conversationId int64, body api.UpdateConversationJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, conversationId, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "UpdateConversation", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateConversation indicates an expected call of UpdateConversation. +func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversation(ctx, conversationId, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, conversationId, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversation), varargs...) +} + +// UpdateConversationWithBody mocks base method. +func (m *MockAPIClientInterface) UpdateConversationWithBody(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, conversationId, contentType, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "UpdateConversationWithBody", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateConversationWithBody indicates an expected call of UpdateConversationWithBody. +func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationWithBody(ctx, conversationId, contentType, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, conversationId, contentType, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationWithBody", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationWithBody), varargs...) +} + +// UpdateConversationWithBodyWithResponse mocks base method. +func (m *MockAPIClientInterface) UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*api.UpdateConversationResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, conversationId, contentType, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "UpdateConversationWithBodyWithResponse", varargs...) + ret0, _ := ret[0].(*api.UpdateConversationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateConversationWithBodyWithResponse indicates an expected call of UpdateConversationWithBodyWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationWithBodyWithResponse(ctx, conversationId, contentType, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, conversationId, contentType, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationWithBodyWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationWithBodyWithResponse), varargs...) +} + +// UpdateConversationWithResponse mocks base method. +func (m *MockAPIClientInterface) UpdateConversationWithResponse(ctx context.Context, conversationId int64, body api.UpdateConversationJSONRequestBody, reqEditors ...api.RequestEditorFn) (*api.UpdateConversationResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, conversationId, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "UpdateConversationWithResponse", varargs...) + ret0, _ := ret[0].(*api.UpdateConversationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateConversationWithResponse indicates an expected call of UpdateConversationWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationWithResponse(ctx, conversationId, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, conversationId, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationWithResponse), varargs...) +} + // UpdateDocument mocks base method. func (m *MockAPIClientInterface) UpdateDocument(ctx context.Context, collectionName, documentId string, body api.UpdateDocumentJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() From 6568c8672bab69174ff57ec13e76e261b5078076 Mon Sep 17 00:00:00 2001 From: Hayden Date: Tue, 9 Jul 2024 18:47:04 +0700 Subject: [PATCH 04/19] feat: retrieve, update, delete conversation model --- typesense/api/client_gen.go | 372 +++++++++++++++++++++++++- typesense/api/generator/generator.yml | 98 ++++++- typesense/api/generator/openapi.yml | 94 ++++++- typesense/api/types_gen.go | 24 +- typesense/conversation_model.go | 51 ++++ typesense/conversation_models.go | 10 +- typesense/conversations.go | 4 + typesense/mocks/mock_client.go | 160 +++++++++++ 8 files changed, 769 insertions(+), 44 deletions(-) create mode 100644 typesense/conversation_model.go diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index 6f73d2e..b695e00 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -213,6 +213,17 @@ type ClientInterface interface { CreateConversationModel(ctx context.Context, body CreateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // DeleteConversationModel request + DeleteConversationModel(ctx context.Context, modelId string, reqEditors ...RequestEditorFn) (*http.Response, error) + + // RetrieveConversationModel request + RetrieveConversationModel(ctx context.Context, modelId string, reqEditors ...RequestEditorFn) (*http.Response, error) + + // UpdateConversationModelWithBody request with any body + UpdateConversationModelWithBody(ctx context.Context, modelId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + UpdateConversationModel(ctx context.Context, modelId string, body UpdateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // DeleteConversation request DeleteConversation(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -830,6 +841,54 @@ func (c *Client) CreateConversationModel(ctx context.Context, body CreateConvers return c.Client.Do(req) } +func (c *Client) DeleteConversationModel(ctx context.Context, modelId string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteConversationModelRequest(c.Server, modelId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) RetrieveConversationModel(ctx context.Context, modelId string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRetrieveConversationModelRequest(c.Server, modelId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpdateConversationModelWithBody(ctx context.Context, modelId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateConversationModelRequestWithBody(c.Server, modelId, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpdateConversationModel(ctx context.Context, modelId string, body UpdateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateConversationModelRequest(c.Server, modelId, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) DeleteConversation(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewDeleteConversationRequest(c.Server, conversationId) if err != nil { @@ -3554,6 +3613,121 @@ func NewCreateConversationModelRequestWithBody(server string, contentType string return req, nil } +// NewDeleteConversationModelRequest generates requests for DeleteConversationModel +func NewDeleteConversationModelRequest(server string, modelId string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "modelId", runtime.ParamLocationPath, modelId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/conversations/models/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("DELETE", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewRetrieveConversationModelRequest generates requests for RetrieveConversationModel +func NewRetrieveConversationModelRequest(server string, modelId string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "modelId", runtime.ParamLocationPath, modelId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/conversations/models/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewUpdateConversationModelRequest calls the generic UpdateConversationModel builder with application/json body +func NewUpdateConversationModelRequest(server string, modelId string, body UpdateConversationModelJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewUpdateConversationModelRequestWithBody(server, modelId, "application/json", bodyReader) +} + +// NewUpdateConversationModelRequestWithBody generates requests for UpdateConversationModel with any type of body +func NewUpdateConversationModelRequestWithBody(server string, modelId string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "modelId", runtime.ParamLocationPath, modelId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/conversations/models/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("PUT", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewDeleteConversationRequest generates requests for DeleteConversation func NewDeleteConversationRequest(server string, conversationId int64) (*http.Request, error) { var err error @@ -5361,6 +5535,17 @@ type ClientWithResponsesInterface interface { CreateConversationModelWithResponse(ctx context.Context, body CreateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateConversationModelResponse, error) + // DeleteConversationModelWithResponse request + DeleteConversationModelWithResponse(ctx context.Context, modelId string, reqEditors ...RequestEditorFn) (*DeleteConversationModelResponse, error) + + // RetrieveConversationModelWithResponse request + RetrieveConversationModelWithResponse(ctx context.Context, modelId string, reqEditors ...RequestEditorFn) (*RetrieveConversationModelResponse, error) + + // UpdateConversationModelWithBodyWithResponse request with any body + UpdateConversationModelWithBodyWithResponse(ctx context.Context, modelId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateConversationModelResponse, error) + + UpdateConversationModelWithResponse(ctx context.Context, modelId string, body UpdateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationModelResponse, error) + // DeleteConversationWithResponse request DeleteConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*DeleteConversationResponse, error) @@ -6180,7 +6365,7 @@ func (r RetrieveAllConversationsResponse) StatusCode() int { type RetrieveAllConversationModelsResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *[]*ConversationModelResponse + JSON200 *[]*ConversationModelSchema } // Status returns HTTPResponse.Status @@ -6202,7 +6387,7 @@ func (r RetrieveAllConversationModelsResponse) StatusCode() int { type CreateConversationModelResponse struct { Body []byte HTTPResponse *http.Response - JSON201 *ConversationModelResponse + JSON201 *ConversationModelSchema JSON400 *ApiResponse } @@ -6222,6 +6407,72 @@ func (r CreateConversationModelResponse) StatusCode() int { return 0 } +type DeleteConversationModelResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ConversationModelDeleteSchema +} + +// Status returns HTTPResponse.Status +func (r DeleteConversationModelResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r DeleteConversationModelResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type RetrieveConversationModelResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ConversationModelSchema +} + +// Status returns HTTPResponse.Status +func (r RetrieveConversationModelResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r RetrieveConversationModelResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type UpdateConversationModelResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ConversationModelCreateSchema +} + +// Status returns HTTPResponse.Status +func (r UpdateConversationModelResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r UpdateConversationModelResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type DeleteConversationResponse struct { Body []byte HTTPResponse *http.Response @@ -7116,6 +7367,41 @@ func (c *ClientWithResponses) CreateConversationModelWithResponse(ctx context.Co return ParseCreateConversationModelResponse(rsp) } +// DeleteConversationModelWithResponse request returning *DeleteConversationModelResponse +func (c *ClientWithResponses) DeleteConversationModelWithResponse(ctx context.Context, modelId string, reqEditors ...RequestEditorFn) (*DeleteConversationModelResponse, error) { + rsp, err := c.DeleteConversationModel(ctx, modelId, reqEditors...) + if err != nil { + return nil, err + } + return ParseDeleteConversationModelResponse(rsp) +} + +// RetrieveConversationModelWithResponse request returning *RetrieveConversationModelResponse +func (c *ClientWithResponses) RetrieveConversationModelWithResponse(ctx context.Context, modelId string, reqEditors ...RequestEditorFn) (*RetrieveConversationModelResponse, error) { + rsp, err := c.RetrieveConversationModel(ctx, modelId, reqEditors...) + if err != nil { + return nil, err + } + return ParseRetrieveConversationModelResponse(rsp) +} + +// UpdateConversationModelWithBodyWithResponse request with arbitrary body returning *UpdateConversationModelResponse +func (c *ClientWithResponses) UpdateConversationModelWithBodyWithResponse(ctx context.Context, modelId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateConversationModelResponse, error) { + rsp, err := c.UpdateConversationModelWithBody(ctx, modelId, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpdateConversationModelResponse(rsp) +} + +func (c *ClientWithResponses) UpdateConversationModelWithResponse(ctx context.Context, modelId string, body UpdateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationModelResponse, error) { + rsp, err := c.UpdateConversationModel(ctx, modelId, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpdateConversationModelResponse(rsp) +} + // DeleteConversationWithResponse request returning *DeleteConversationResponse func (c *ClientWithResponses) DeleteConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*DeleteConversationResponse, error) { rsp, err := c.DeleteConversation(ctx, conversationId, reqEditors...) @@ -8416,7 +8702,7 @@ func ParseRetrieveAllConversationModelsResponse(rsp *http.Response) (*RetrieveAl switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest []*ConversationModelResponse + var dest []*ConversationModelSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -8442,7 +8728,7 @@ func ParseCreateConversationModelResponse(rsp *http.Response) (*CreateConversati switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: - var dest ConversationModelResponse + var dest ConversationModelSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -8460,6 +8746,84 @@ func ParseCreateConversationModelResponse(rsp *http.Response) (*CreateConversati return response, nil } +// ParseDeleteConversationModelResponse parses an HTTP response from a DeleteConversationModelWithResponse call +func ParseDeleteConversationModelResponse(rsp *http.Response) (*DeleteConversationModelResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &DeleteConversationModelResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ConversationModelDeleteSchema + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseRetrieveConversationModelResponse parses an HTTP response from a RetrieveConversationModelWithResponse call +func ParseRetrieveConversationModelResponse(rsp *http.Response) (*RetrieveConversationModelResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RetrieveConversationModelResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ConversationModelSchema + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseUpdateConversationModelResponse parses an HTTP response from a UpdateConversationModelWithResponse call +func ParseUpdateConversationModelResponse(rsp *http.Response) (*UpdateConversationModelResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &UpdateConversationModelResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ConversationModelCreateSchema + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + // ParseDeleteConversationResponse parses an HTTP response from a DeleteConversationWithResponse call func ParseDeleteConversationResponse(rsp *http.Response) (*DeleteConversationResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index 906665c..bc7a9c0 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -260,15 +260,7 @@ components: properties: id: type: integer - ConversationModelResponse: - allOf: - - $ref: '#/components/schemas/ConversationModelSchema' - - properties: - id: - readOnly: true - type: string - type: object - ConversationModelSchema: + ConversationModelCreateSchema: properties: account_id: description: LLM service's account ID (only applicable for Cloudflare) @@ -292,9 +284,21 @@ components: required: - model_name - api_key - - system_prompt - max_bytes type: object + ConversationModelDeleteSchema: + properties: + id: + type: string + type: object + ConversationModelSchema: + allOf: + - $ref: '#/components/schemas/ConversationModelCreateSchema' + - properties: + id: + readOnly: true + type: string + type: object ConversationSchema: properties: conversation: @@ -2587,9 +2591,9 @@ paths: application/json: schema: items: - $ref: '#/components/schemas/ConversationModelResponse' + $ref: '#/components/schemas/ConversationModelSchema' type: array - x-go-type: '[]*ConversationModelResponse' + x-go-type: '[]*ConversationModelSchema' description: List of all conversation models summary: List all conversation models tags: @@ -2601,13 +2605,13 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelSchema' + $ref: '#/components/schemas/ConversationModelCreateSchema' responses: 201: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelResponse' + $ref: '#/components/schemas/ConversationModelSchema' description: Created Conversation Model 400: content: @@ -2617,6 +2621,72 @@ paths: description: Bad request, see error message for details tags: - conversations + /conversations/models/{modelId}: + delete: + description: Delete a conversation model + operationId: deleteConversationModel + parameters: + - description: The id of the conversation model to delete + in: path + name: modelId + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelDeleteSchema' + description: The conversation model was successfully deleted + summary: Delete a conversation model + tags: + - conversations + get: + description: Retrieve a conversation model + operationId: retrieveConversationModel + parameters: + - description: The id of the conversation model to retrieve + in: path + name: modelId + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + description: A conversation model + summary: Retrieve a conversation model + tags: + - conversations + put: + description: Update a conversation model + operationId: updateConversationModel + parameters: + - description: The id of the conversation model to update + in: path + name: modelId + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelCreateSchema' + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelCreateSchema' + description: The conversation model was successfully updated + summary: Update a conversation model + tags: + - conversations /debug: get: description: Print debugging information diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index 512dc0e..489060d 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -976,9 +976,9 @@ paths: application/json: schema: items: - $ref: '#/components/schemas/ConversationModelResponse' + $ref: '#/components/schemas/ConversationModelSchema' type: array - x-go-type: '[]*ConversationModelResponse' + x-go-type: '[]*ConversationModelSchema' description: List of all conversation models summary: List all conversation models tags: @@ -990,13 +990,13 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelSchema' + $ref: '#/components/schemas/ConversationModelCreateSchema' responses: 201: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelResponse' + $ref: '#/components/schemas/ConversationModelSchema' description: Created Conversation Model 400: content: @@ -1006,6 +1006,72 @@ paths: description: Bad request, see error message for details tags: - conversations + /conversations/models/{modelId}: + get: + description: Retrieve a conversation model + operationId: retrieveConversationModel + parameters: + - name: modelId + in: path + description: The id of the conversation model to retrieve + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + description: A conversation model + summary: Retrieve a conversation model + tags: + - conversations + put: + description: Update a conversation model + operationId: updateConversationModel + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelCreateSchema' + parameters: + - name: modelId + in: path + description: The id of the conversation model to update + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelCreateSchema' + description: The conversation model was successfully updated + summary: Update a conversation model + tags: + - conversations + delete: + description: Delete a conversation model + operationId: deleteConversationModel + parameters: + - name: modelId + in: path + description: The id of the conversation model to delete + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelDeleteSchema' + description: The conversation model was successfully deleted + summary: Delete a conversation model + tags: + - conversations /keys: get: tags: @@ -3158,22 +3224,24 @@ components: items: $ref: '#/components/schemas/ConversationSchema' x-go-type: '[]*ConversationSchema' - PresetUpsertSchema: + ConversationModelSchema: properties: value: oneOf: - $ref: '#/components/schemas/SearchParameters' - $ref: '#/components/schemas/MultiSearchSearchesParameter' required: - - value - PresetSchema: + - model_name + - api_key + - system_prompt + - max_bytes + type: object + ConversationModelResponse: allOf: - - $ref: '#/components/schemas/PresetUpsertSchema' - - type: object - required: - - name - properties: - name: + - $ref: '#/components/schemas/ConversationModelSchema' + - properties: + id: + readOnly: true type: string PresetsRetrieveSchema: type: object diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index af5dafe..cb544be 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -181,14 +181,13 @@ type ConversationDeleteSchema struct { Id *int `json:"id,omitempty"` } -// ConversationModelResponse defines model for ConversationModelResponse. -type ConversationModelResponse struct { +// ConversationModelCreateSchema defines model for ConversationModelCreateSchema. +type ConversationModelCreateSchema struct { // AccountId LLM service's account ID (only applicable for Cloudflare) AccountId *string `json:"account_id,omitempty"` // ApiKey The LLM service's API Key - ApiKey string `json:"api_key"` - Id *string `json:"id,omitempty"` + ApiKey string `json:"api_key"` // MaxBytes The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. MaxBytes int `json:"max_bytes"` @@ -197,19 +196,25 @@ type ConversationModelResponse struct { ModelName string `json:"model_name"` // SystemPrompt The system prompt that contains special instructions to the LLM - SystemPrompt string `json:"system_prompt"` + SystemPrompt *string `json:"system_prompt,omitempty"` // VllmUrl URL of vLLM service VllmUrl *string `json:"vllm_url,omitempty"` } +// ConversationModelDeleteSchema defines model for ConversationModelDeleteSchema. +type ConversationModelDeleteSchema struct { + Id *string `json:"id,omitempty"` +} + // ConversationModelSchema defines model for ConversationModelSchema. type ConversationModelSchema struct { // AccountId LLM service's account ID (only applicable for Cloudflare) AccountId *string `json:"account_id,omitempty"` // ApiKey The LLM service's API Key - ApiKey string `json:"api_key"` + ApiKey string `json:"api_key"` + Id *string `json:"id,omitempty"` // MaxBytes The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. MaxBytes int `json:"max_bytes"` @@ -218,7 +223,7 @@ type ConversationModelSchema struct { ModelName string `json:"model_name"` // SystemPrompt The system prompt that contains special instructions to the LLM - SystemPrompt string `json:"system_prompt"` + SystemPrompt *string `json:"system_prompt,omitempty"` // VllmUrl URL of vLLM service VllmUrl *string `json:"vllm_url,omitempty"` @@ -1234,7 +1239,10 @@ type UpsertSearchOverrideJSONRequestBody = SearchOverrideSchema type UpsertSearchSynonymJSONRequestBody = SearchSynonymSchema // CreateConversationModelJSONRequestBody defines body for CreateConversationModel for application/json ContentType. -type CreateConversationModelJSONRequestBody = ConversationModelSchema +type CreateConversationModelJSONRequestBody = ConversationModelCreateSchema + +// UpdateConversationModelJSONRequestBody defines body for UpdateConversationModel for application/json ContentType. +type UpdateConversationModelJSONRequestBody = ConversationModelCreateSchema // UpdateConversationJSONRequestBody defines body for UpdateConversation for application/json ContentType. type UpdateConversationJSONRequestBody = ConversationUpdateSchema diff --git a/typesense/conversation_model.go b/typesense/conversation_model.go new file mode 100644 index 0000000..855f20e --- /dev/null +++ b/typesense/conversation_model.go @@ -0,0 +1,51 @@ +package typesense + +import ( + "context" + + "github.com/typesense/typesense-go/typesense/api" +) + +type ConversationModelInterface interface { + Retrieve(ctx context.Context) (*api.ConversationModelSchema, error) + Update(ctx context.Context, model *api.ConversationModelCreateSchema) (*api.ConversationModelCreateSchema, error) + Delete(ctx context.Context) (*api.ConversationModelDeleteSchema, error) +} + +type conversationModel struct { + apiClient APIClientInterface + modelId string +} + +func (c *conversationModel) Retrieve(ctx context.Context) (*api.ConversationModelSchema, error) { + response, err := c.apiClient.RetrieveConversationModelWithResponse(ctx, c.modelId) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON200, nil +} + +func (c *conversationModel) Update(ctx context.Context, model *api.ConversationModelCreateSchema) (*api.ConversationModelCreateSchema, error) { + response, err := c.apiClient.UpdateConversationModelWithResponse(ctx, c.modelId, api.UpdateConversationModelJSONRequestBody(*model)) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON200, nil +} + +func (c *conversationModel) Delete(ctx context.Context) (*api.ConversationModelDeleteSchema, error) { + response, err := c.apiClient.DeleteConversationModelWithResponse(ctx, c.modelId) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON200, nil +} diff --git a/typesense/conversation_models.go b/typesense/conversation_models.go index f802208..13ce7a5 100644 --- a/typesense/conversation_models.go +++ b/typesense/conversation_models.go @@ -8,8 +8,8 @@ import ( // ConversationModelsInterface is a type for ConversationModels API operations type ConversationModelsInterface interface { - Create(ctx context.Context, conversationModelSchema *api.ConversationModelSchema) (*api.ConversationModelResponse, error) - Retrieve(ctx context.Context) ([]*api.ConversationModelResponse, error) + Create(ctx context.Context, conversationModelCreateSchema *api.ConversationModelCreateSchema) (*api.ConversationModelSchema, error) + Retrieve(ctx context.Context) ([]*api.ConversationModelSchema, error) } // conversationModels is internal implementation of ConversationModelsInterface @@ -17,8 +17,8 @@ type conversationModels struct { apiClient APIClientInterface } -func (c *conversationModels) Create(ctx context.Context, conversationModelSchema *api.ConversationModelSchema) (*api.ConversationModelResponse, error) { - response, err := c.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*conversationModelSchema)) +func (c *conversationModels) Create(ctx context.Context, conversationModelCreateSchema *api.ConversationModelCreateSchema) (*api.ConversationModelSchema, error) { + response, err := c.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*conversationModelCreateSchema)) if err != nil { return nil, err } @@ -28,7 +28,7 @@ func (c *conversationModels) Create(ctx context.Context, conversationModelSchema return response.JSON201, nil } -func (c *conversationModels) Retrieve(ctx context.Context) ([]*api.ConversationModelResponse, error) { +func (c *conversationModels) Retrieve(ctx context.Context) ([]*api.ConversationModelSchema, error) { response, err := c.apiClient.RetrieveAllConversationModelsWithResponse(ctx) if err != nil { return nil, err diff --git a/typesense/conversations.go b/typesense/conversations.go index 059d625..cf13eac 100644 --- a/typesense/conversations.go +++ b/typesense/conversations.go @@ -31,3 +31,7 @@ func (c *conversations) Retrieve(ctx context.Context) ([]*api.ConversationSchema func (c *conversations) Models() ConversationModelsInterface { return &conversationModels{apiClient: c.apiClient} } + +func (c *conversations) Model(modelId string) ConversationModelInterface { + return &conversationModel{apiClient: c.apiClient, modelId: modelId} +} diff --git a/typesense/mocks/mock_client.go b/typesense/mocks/mock_client.go index 1eccfc8..5baa8f4 100644 --- a/typesense/mocks/mock_client.go +++ b/typesense/mocks/mock_client.go @@ -542,6 +542,46 @@ func (mr *MockAPIClientInterfaceMockRecorder) DeleteConversation(ctx, conversati return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).DeleteConversation), varargs...) } +// DeleteConversationModel mocks base method. +func (m *MockAPIClientInterface) DeleteConversationModel(ctx context.Context, modelId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, modelId} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "DeleteConversationModel", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteConversationModel indicates an expected call of DeleteConversationModel. +func (mr *MockAPIClientInterfaceMockRecorder) DeleteConversationModel(ctx, modelId any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, modelId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConversationModel", reflect.TypeOf((*MockAPIClientInterface)(nil).DeleteConversationModel), varargs...) +} + +// DeleteConversationModelWithResponse mocks base method. +func (m *MockAPIClientInterface) DeleteConversationModelWithResponse(ctx context.Context, modelId string, reqEditors ...api.RequestEditorFn) (*api.DeleteConversationModelResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, modelId} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "DeleteConversationModelWithResponse", varargs...) + ret0, _ := ret[0].(*api.DeleteConversationModelResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteConversationModelWithResponse indicates an expected call of DeleteConversationModelWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) DeleteConversationModelWithResponse(ctx, modelId any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, modelId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConversationModelWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).DeleteConversationModelWithResponse), varargs...) +} + // DeleteConversationWithResponse mocks base method. func (m *MockAPIClientInterface) DeleteConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...api.RequestEditorFn) (*api.DeleteConversationResponse, error) { m.ctrl.T.Helper() @@ -1902,6 +1942,46 @@ func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversation(ctx, conversa return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversation), varargs...) } +// RetrieveConversationModel mocks base method. +func (m *MockAPIClientInterface) RetrieveConversationModel(ctx context.Context, modelId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, modelId} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RetrieveConversationModel", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RetrieveConversationModel indicates an expected call of RetrieveConversationModel. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationModel(ctx, modelId any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, modelId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationModel", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationModel), varargs...) +} + +// RetrieveConversationModelWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrieveConversationModelWithResponse(ctx context.Context, modelId string, reqEditors ...api.RequestEditorFn) (*api.RetrieveConversationModelResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, modelId} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RetrieveConversationModelWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrieveConversationModelResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RetrieveConversationModelWithResponse indicates an expected call of RetrieveConversationModelWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationModelWithResponse(ctx, modelId any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, modelId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationModelWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationModelWithResponse), varargs...) +} + // RetrieveConversationWithResponse mocks base method. func (m *MockAPIClientInterface) RetrieveConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...api.RequestEditorFn) (*api.RetrieveConversationResponse, error) { m.ctrl.T.Helper() @@ -2182,6 +2262,86 @@ func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversation(ctx, conversati return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversation), varargs...) } +// UpdateConversationModel mocks base method. +func (m *MockAPIClientInterface) UpdateConversationModel(ctx context.Context, modelId string, body api.UpdateConversationModelJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, modelId, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "UpdateConversationModel", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateConversationModel indicates an expected call of UpdateConversationModel. +func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationModel(ctx, modelId, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, modelId, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationModel", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationModel), varargs...) +} + +// UpdateConversationModelWithBody mocks base method. +func (m *MockAPIClientInterface) UpdateConversationModelWithBody(ctx context.Context, modelId, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, modelId, contentType, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "UpdateConversationModelWithBody", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateConversationModelWithBody indicates an expected call of UpdateConversationModelWithBody. +func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationModelWithBody(ctx, modelId, contentType, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, modelId, contentType, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationModelWithBody", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationModelWithBody), varargs...) +} + +// UpdateConversationModelWithBodyWithResponse mocks base method. +func (m *MockAPIClientInterface) UpdateConversationModelWithBodyWithResponse(ctx context.Context, modelId, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*api.UpdateConversationModelResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, modelId, contentType, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "UpdateConversationModelWithBodyWithResponse", varargs...) + ret0, _ := ret[0].(*api.UpdateConversationModelResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateConversationModelWithBodyWithResponse indicates an expected call of UpdateConversationModelWithBodyWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationModelWithBodyWithResponse(ctx, modelId, contentType, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, modelId, contentType, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationModelWithBodyWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationModelWithBodyWithResponse), varargs...) +} + +// UpdateConversationModelWithResponse mocks base method. +func (m *MockAPIClientInterface) UpdateConversationModelWithResponse(ctx context.Context, modelId string, body api.UpdateConversationModelJSONRequestBody, reqEditors ...api.RequestEditorFn) (*api.UpdateConversationModelResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, modelId, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "UpdateConversationModelWithResponse", varargs...) + ret0, _ := ret[0].(*api.UpdateConversationModelResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateConversationModelWithResponse indicates an expected call of UpdateConversationModelWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationModelWithResponse(ctx, modelId, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, modelId, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationModelWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationModelWithResponse), varargs...) +} + // UpdateConversationWithBody mocks base method. func (m *MockAPIClientInterface) UpdateConversationWithBody(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() From 3710717b0adcee3263f7270dcbd0948853d8d770 Mon Sep 17 00:00:00 2001 From: Hayden Date: Wed, 10 Jul 2024 10:03:26 +0700 Subject: [PATCH 05/19] test: retrieve all conversations --- typesense/api/generator/generator.yml | 5 +++ typesense/api/generator/openapi.yml | 5 +++ typesense/api/types_gen.go | 6 +-- typesense/conversations_test.go | 59 +++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 typesense/conversations_test.go diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index bc7a9c0..941c835 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -314,6 +314,8 @@ components: type: integer required: - id + - conversation + - last_updated - ttl type: object ConversationUpdateSchema: @@ -2571,6 +2573,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationUpdateSchema' + required: true responses: 200: content: @@ -2606,6 +2609,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationModelCreateSchema' + required: true responses: 201: content: @@ -2677,6 +2681,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationModelCreateSchema' + required: true responses: 200: content: diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index 489060d..b9372e2 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -927,6 +927,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationUpdateSchema' + required: true parameters: - name: conversationId in: path @@ -991,6 +992,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationModelCreateSchema' + required: true responses: 201: content: @@ -1035,6 +1037,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ConversationModelCreateSchema' + required: true parameters: - name: modelId in: path @@ -3204,6 +3207,8 @@ components: type: object required: - id + - conversation + - last_updated - ttl ConversationUpdateSchema: properties: diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index cb544be..19fbba0 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -231,9 +231,9 @@ type ConversationModelSchema struct { // ConversationSchema defines model for ConversationSchema. type ConversationSchema struct { - Conversation *[]map[string]interface{} `json:"conversation,omitempty"` - Id int `json:"id"` - LastUpdated *int `json:"last_updated,omitempty"` + Conversation []map[string]interface{} `json:"conversation"` + Id int `json:"id"` + LastUpdated int `json:"last_updated"` // Ttl Time to live. Conversations are stored by default for 24 hours, and then purged. Ttl int `json:"ttl"` diff --git a/typesense/conversations_test.go b/typesense/conversations_test.go new file mode 100644 index 0000000..0baca83 --- /dev/null +++ b/typesense/conversations_test.go @@ -0,0 +1,59 @@ +package typesense + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/typesense/typesense-go/typesense/api" +) + +func newTestServerAndClient(handler func(w http.ResponseWriter, r *http.Request)) (*httptest.Server, *Client) { + server := httptest.NewServer(http.HandlerFunc(handler)) + return server, NewClient(WithServer(server.URL)) +} +func TestConversationsRetrieveAllConversations(t *testing.T) { + expectedData := api.ConversationsRetrieveSchema{ + Conversations: []*api.ConversationSchema{ + { + Id: 1, + Conversation: []map[string]any{ + {"any": "any"}, + }, + LastUpdated: 12, + Ttl: 34, + }, + }, + } + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + if r.RequestURI != "/conversations" { + t.Fatal("Invalid request endpoint!") + } + data, err := json.Marshal(expectedData) + assert.NoError(t, err) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(data) + }) + defer server.Close() + + res, err := client.Conversations().Retrieve(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData.Conversations, res) +} + +func TestConversationsRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + if r.RequestURI != "/conversations" { + t.Fatal("Invalid request endpoint!") + } + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Conversations().Retrieve(context.Background()) + assert.NotNil(t, err) +} From d53375eb2f262b2390c406a62a5fa027061ce2e1 Mon Sep 17 00:00:00 2001 From: Hayden Date: Wed, 10 Jul 2024 10:45:51 +0700 Subject: [PATCH 06/19] test: retrieve, update and delete a conversation --- typesense/api/generator/generator.yml | 4 + typesense/api/generator/openapi.yml | 4 + typesense/api/types_gen.go | 4 +- typesense/conversation_test.go | 113 ++++++++++++++++++++++++++ typesense/conversations_test.go | 17 ++-- 5 files changed, 134 insertions(+), 8 deletions(-) create mode 100644 typesense/conversation_test.go diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index 941c835..d74081b 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -260,6 +260,8 @@ components: properties: id: type: integer + required: + - id ConversationModelCreateSchema: properties: account_id: @@ -323,6 +325,8 @@ components: ttl: description: Time to live. Conversations are stored by default for 24 hours, and then purged. type: integer + required: + - ttl ConversationsRetrieveSchema: properties: conversations: diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index b9372e2..8cbb3d8 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -3215,10 +3215,14 @@ components: ttl: description: Time to live. Conversations are stored by default for 24 hours, and then purged. type: integer + required: + - ttl ConversationDeleteSchema: properties: id: type: integer + required: + - id ConversationsRetrieveSchema: type: object required: diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index 19fbba0..4bc5d89 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -178,7 +178,7 @@ type CollectionUpdateSchema struct { // ConversationDeleteSchema defines model for ConversationDeleteSchema. type ConversationDeleteSchema struct { - Id *int `json:"id,omitempty"` + Id int `json:"id"` } // ConversationModelCreateSchema defines model for ConversationModelCreateSchema. @@ -242,7 +242,7 @@ type ConversationSchema struct { // ConversationUpdateSchema defines model for ConversationUpdateSchema. type ConversationUpdateSchema struct { // Ttl Time to live. Conversations are stored by default for 24 hours, and then purged. - Ttl *int `json:"ttl,omitempty"` + Ttl int `json:"ttl"` } // ConversationsRetrieveSchema defines model for ConversationsRetrieveSchema. diff --git a/typesense/conversation_test.go b/typesense/conversation_test.go new file mode 100644 index 0000000..7d869a1 --- /dev/null +++ b/typesense/conversation_test.go @@ -0,0 +1,113 @@ +package typesense + +import ( + "context" + "encoding/json" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/typesense/typesense-go/typesense/api" +) + +func TestConversationRetrieveConversation(t *testing.T) { + expectedData := []*api.ConversationSchema{{ + Id: 1, + Conversation: []map[string]any{ + {"any": "any"}, + }, + LastUpdated: 12, + Ttl: 34, + }} + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/123", http.MethodGet) + data, err := json.Marshal(expectedData) + assert.NoError(t, err) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(data) + }) + defer server.Close() + + res, err := client.Conversation(123).Retrieve(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestConversationRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/123", http.MethodGet) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Conversation(123).Retrieve(context.Background()) + assert.Error(t, err) +} +func TestConversationUpdateConversation(t *testing.T) { + expectedData := &api.ConversationUpdateSchema{ + Ttl: 3000, + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/123", http.MethodPut) + data, err := json.Marshal(expectedData) + assert.NoError(t, err) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(data) + }) + defer server.Close() + + res, err := client.Conversation(123).Update(context.Background(), expectedData) + + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestConversationUpdateOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/123", http.MethodPut) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Conversation(123).Update(context.Background(), &api.ConversationUpdateSchema{ + Ttl: 0, + }) + assert.Error(t, err) +} + +func TestConversationDeleteConversation(t *testing.T) { + expectedData := &api.ConversationDeleteSchema{ + Id: 123, + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/123", http.MethodDelete) + data, err := json.Marshal(expectedData) + assert.NoError(t, err) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(data) + }) + defer server.Close() + + res, err := client.Conversation(123).Delete(context.Background()) + + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestConversationDeleteOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/123", http.MethodDelete) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Conversation(123).Delete(context.Background()) + assert.Error(t, err) +} diff --git a/typesense/conversations_test.go b/typesense/conversations_test.go index 0baca83..4bc36e4 100644 --- a/typesense/conversations_test.go +++ b/typesense/conversations_test.go @@ -15,6 +15,15 @@ func newTestServerAndClient(handler func(w http.ResponseWriter, r *http.Request) server := httptest.NewServer(http.HandlerFunc(handler)) return server, NewClient(WithServer(server.URL)) } + +func validateRequestMetadata(t *testing.T, r *http.Request, expectedEndpoint string, expectedMethod string) { + if r.RequestURI != expectedEndpoint { + t.Fatal("Invalid request endpoint!") + } + if r.Method != expectedMethod { + t.Fatal("Invalid HTTP method!") + } +} func TestConversationsRetrieveAllConversations(t *testing.T) { expectedData := api.ConversationsRetrieveSchema{ Conversations: []*api.ConversationSchema{ @@ -29,9 +38,7 @@ func TestConversationsRetrieveAllConversations(t *testing.T) { }, } server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - if r.RequestURI != "/conversations" { - t.Fatal("Invalid request endpoint!") - } + validateRequestMetadata(t, r, "/conversations", http.MethodGet) data, err := json.Marshal(expectedData) assert.NoError(t, err) w.Header().Set("Content-Type", "application/json") @@ -47,9 +54,7 @@ func TestConversationsRetrieveAllConversations(t *testing.T) { func TestConversationsRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - if r.RequestURI != "/conversations" { - t.Fatal("Invalid request endpoint!") - } + validateRequestMetadata(t, r, "/conversations", http.MethodGet) w.WriteHeader(http.StatusConflict) }) defer server.Close() From c2e176f97470f787a687d471150ce40dfa91433f Mon Sep 17 00:00:00 2001 From: Hayden Date: Wed, 10 Jul 2024 17:24:49 +0700 Subject: [PATCH 07/19] test: create & retrieve all conversation models --- typesense/api/client_gen.go | 4 +- typesense/api/generator/generator.yml | 5 +- typesense/api/generator/openapi.yml | 3 +- typesense/api/types_gen.go | 4 +- typesense/conversation_models.go | 4 +- typesense/conversation_models_test.go | 83 +++++++++++++++++++++++++++ typesense/conversation_test.go | 12 ++-- typesense/conversations_test.go | 10 +++- 8 files changed, 106 insertions(+), 19 deletions(-) create mode 100644 typesense/conversation_models_test.go diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index b695e00..a6b2c17 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -6387,7 +6387,7 @@ func (r RetrieveAllConversationModelsResponse) StatusCode() int { type CreateConversationModelResponse struct { Body []byte HTTPResponse *http.Response - JSON201 *ConversationModelSchema + JSON201 *ConversationModelCreateSchema JSON400 *ApiResponse } @@ -8728,7 +8728,7 @@ func ParseCreateConversationModelResponse(rsp *http.Response) (*CreateConversati switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: - var dest ConversationModelSchema + var dest ConversationModelCreateSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index d74081b..964d476 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -298,8 +298,9 @@ components: - $ref: '#/components/schemas/ConversationModelCreateSchema' - properties: id: - readOnly: true type: string + required: + - id type: object ConversationSchema: properties: @@ -2619,7 +2620,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelSchema' + $ref: '#/components/schemas/ConversationModelCreateSchema' description: Created Conversation Model 400: content: diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index 8cbb3d8..af163d8 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -998,7 +998,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelSchema' + $ref: '#/components/schemas/ConversationModelCreateSchema' description: Created Conversation Model 400: content: @@ -3250,7 +3250,6 @@ components: - $ref: '#/components/schemas/ConversationModelSchema' - properties: id: - readOnly: true type: string PresetsRetrieveSchema: type: object diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index 4bc5d89..d8bd881 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -213,8 +213,8 @@ type ConversationModelSchema struct { AccountId *string `json:"account_id,omitempty"` // ApiKey The LLM service's API Key - ApiKey string `json:"api_key"` - Id *string `json:"id,omitempty"` + ApiKey string `json:"api_key"` + Id string `json:"id"` // MaxBytes The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. MaxBytes int `json:"max_bytes"` diff --git a/typesense/conversation_models.go b/typesense/conversation_models.go index 13ce7a5..010cb32 100644 --- a/typesense/conversation_models.go +++ b/typesense/conversation_models.go @@ -8,7 +8,7 @@ import ( // ConversationModelsInterface is a type for ConversationModels API operations type ConversationModelsInterface interface { - Create(ctx context.Context, conversationModelCreateSchema *api.ConversationModelCreateSchema) (*api.ConversationModelSchema, error) + Create(ctx context.Context, conversationModelCreateSchema *api.ConversationModelCreateSchema) (*api.ConversationModelCreateSchema, error) Retrieve(ctx context.Context) ([]*api.ConversationModelSchema, error) } @@ -17,7 +17,7 @@ type conversationModels struct { apiClient APIClientInterface } -func (c *conversationModels) Create(ctx context.Context, conversationModelCreateSchema *api.ConversationModelCreateSchema) (*api.ConversationModelSchema, error) { +func (c *conversationModels) Create(ctx context.Context, conversationModelCreateSchema *api.ConversationModelCreateSchema) (*api.ConversationModelCreateSchema, error) { response, err := c.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*conversationModelCreateSchema)) if err != nil { return nil, err diff --git a/typesense/conversation_models_test.go b/typesense/conversation_models_test.go new file mode 100644 index 0000000..4fd008e --- /dev/null +++ b/typesense/conversation_models_test.go @@ -0,0 +1,83 @@ +package typesense + +import ( + "context" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/typesense/typesense-go/typesense/api" +) + +func TestConversationModelsRetrieve(t *testing.T) { + accountId, systemPrompt := "CLOUDFLARE_ACCOUNT_ID", "..." + expectedData := []*api.ConversationModelSchema{{ + Id: "123", + ModelName: "cf/mistral/mistral-7b-instruct-v0.1", + ApiKey: "CLOUDFLARE_API_KEY", + AccountId: &accountId, + SystemPrompt: &systemPrompt, + MaxBytes: 16384, + }} + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/models", http.MethodGet) + data := jsonEncode(t, expectedData) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(data) + }) + defer server.Close() + + res, err := client.Conversations().Models().Retrieve(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestConversationModelsRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/models", http.MethodGet) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Conversations().Models().Retrieve(context.Background()) + assert.Error(t, err) +} + +func TestConversationModelsCreate(t *testing.T) { + accountId, systemPrompt := "CLOUDFLARE_ACCOUNT_ID", "..." + expectedData := &api.ConversationModelCreateSchema{ + ModelName: "cf/mistral/mistral-7b-instruct-v0.1", + ApiKey: "CLOUDFLARE_API_KEY", + AccountId: &accountId, + SystemPrompt: &systemPrompt, + MaxBytes: 16384, + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/models", http.MethodPost) + data := jsonEncode(t, expectedData) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + w.Write(data) + }) + defer server.Close() + + res, err := client.Conversations().Models().Create(context.Background(), expectedData) + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestConversationModelsCreateOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/models", http.MethodPost) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Conversations().Models().Create(context.Background(), &api.ConversationModelCreateSchema{ + ModelName: "cf/mistral/mistral-7b-instruct-v0.1", + }) + assert.Error(t, err) +} diff --git a/typesense/conversation_test.go b/typesense/conversation_test.go index 7d869a1..e5fc6b8 100644 --- a/typesense/conversation_test.go +++ b/typesense/conversation_test.go @@ -2,7 +2,6 @@ package typesense import ( "context" - "encoding/json" "net/http" "testing" @@ -22,8 +21,7 @@ func TestConversationRetrieveConversation(t *testing.T) { server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations/123", http.MethodGet) - data, err := json.Marshal(expectedData) - assert.NoError(t, err) + data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) @@ -53,8 +51,8 @@ func TestConversationUpdateConversation(t *testing.T) { server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations/123", http.MethodPut) - data, err := json.Marshal(expectedData) - assert.NoError(t, err) + data := jsonEncode(t, expectedData) + w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) w.Write(data) @@ -87,8 +85,8 @@ func TestConversationDeleteConversation(t *testing.T) { server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations/123", http.MethodDelete) - data, err := json.Marshal(expectedData) - assert.NoError(t, err) + data := jsonEncode(t, expectedData) + w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) w.Write(data) diff --git a/typesense/conversations_test.go b/typesense/conversations_test.go index 4bc36e4..de4067c 100644 --- a/typesense/conversations_test.go +++ b/typesense/conversations_test.go @@ -24,6 +24,13 @@ func validateRequestMetadata(t *testing.T, r *http.Request, expectedEndpoint str t.Fatal("Invalid HTTP method!") } } + +func jsonEncode(t *testing.T, v any) []byte { + t.Helper() + data, err := json.Marshal(v) + assert.NoError(t, err) + return data +} func TestConversationsRetrieveAllConversations(t *testing.T) { expectedData := api.ConversationsRetrieveSchema{ Conversations: []*api.ConversationSchema{ @@ -39,8 +46,7 @@ func TestConversationsRetrieveAllConversations(t *testing.T) { } server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations", http.MethodGet) - data, err := json.Marshal(expectedData) - assert.NoError(t, err) + data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) w.Write(data) From dd7f4b161bc6ee5327ddd39a16e009c53e50f118 Mon Sep 17 00:00:00 2001 From: Hayden Date: Wed, 10 Jul 2024 18:14:47 +0700 Subject: [PATCH 08/19] test: retrieve, update, delete a conversation model --- typesense/api/client_gen.go | 8 +- typesense/api/generator/generator.yml | 14 +-- typesense/api/generator/openapi.yml | 21 +++-- typesense/api/types_gen.go | 10 +-- typesense/conversation_model.go | 6 +- typesense/conversation_model_test.go | 122 ++++++++++++++++++++++++++ typesense/conversation_models.go | 6 +- typesense/conversation_models_test.go | 12 ++- typesense/conversation_test.go | 9 +- typesense/conversations.go | 1 + 10 files changed, 178 insertions(+), 31 deletions(-) create mode 100644 typesense/conversation_model_test.go diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index a6b2c17..756519c 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -6387,7 +6387,7 @@ func (r RetrieveAllConversationModelsResponse) StatusCode() int { type CreateConversationModelResponse struct { Body []byte HTTPResponse *http.Response - JSON201 *ConversationModelCreateSchema + JSON201 *ConversationModelCreateAndUpdateSchema JSON400 *ApiResponse } @@ -6454,7 +6454,7 @@ func (r RetrieveConversationModelResponse) StatusCode() int { type UpdateConversationModelResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *ConversationModelCreateSchema + JSON200 *ConversationModelCreateAndUpdateSchema } // Status returns HTTPResponse.Status @@ -8728,7 +8728,7 @@ func ParseCreateConversationModelResponse(rsp *http.Response) (*CreateConversati switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: - var dest ConversationModelCreateSchema + var dest ConversationModelCreateAndUpdateSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -8813,7 +8813,7 @@ func ParseUpdateConversationModelResponse(rsp *http.Response) (*UpdateConversati switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ConversationModelCreateSchema + var dest ConversationModelCreateAndUpdateSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index 964d476..e1de379 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -262,7 +262,7 @@ components: type: integer required: - id - ConversationModelCreateSchema: + ConversationModelCreateAndUpdateSchema: properties: account_id: description: LLM service's account ID (only applicable for Cloudflare) @@ -292,10 +292,12 @@ components: properties: id: type: string + required: + - id type: object ConversationModelSchema: allOf: - - $ref: '#/components/schemas/ConversationModelCreateSchema' + - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - properties: id: type: string @@ -2613,14 +2615,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateSchema' + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' required: true responses: 201: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateSchema' + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' description: Created Conversation Model 400: content: @@ -2685,14 +2687,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateSchema' + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' required: true responses: 200: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateSchema' + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' description: The conversation model was successfully updated summary: Update a conversation model tags: diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index af163d8..61dc1fe 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -991,14 +991,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateSchema' + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' required: true responses: 201: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateSchema' + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' description: Created Conversation Model 400: content: @@ -1036,7 +1036,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateSchema' + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' required: true parameters: - name: modelId @@ -1050,7 +1050,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateSchema' + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' description: The conversation model was successfully updated summary: Update a conversation model tags: @@ -3233,7 +3233,7 @@ components: items: $ref: '#/components/schemas/ConversationSchema' x-go-type: '[]*ConversationSchema' - ConversationModelSchema: + ConversationModelCreateAndUpdateSchema: properties: value: oneOf: @@ -3245,9 +3245,16 @@ components: - system_prompt - max_bytes type: object - ConversationModelResponse: + ConversationModelDeleteSchema: + properties: + id: + type: string + required: + - id + type: object + ConversationModelSchema: allOf: - - $ref: '#/components/schemas/ConversationModelSchema' + - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - properties: id: type: string diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index d8bd881..292cf53 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -181,8 +181,8 @@ type ConversationDeleteSchema struct { Id int `json:"id"` } -// ConversationModelCreateSchema defines model for ConversationModelCreateSchema. -type ConversationModelCreateSchema struct { +// ConversationModelCreateAndUpdateSchema defines model for ConversationModelCreateAndUpdateSchema. +type ConversationModelCreateAndUpdateSchema struct { // AccountId LLM service's account ID (only applicable for Cloudflare) AccountId *string `json:"account_id,omitempty"` @@ -204,7 +204,7 @@ type ConversationModelCreateSchema struct { // ConversationModelDeleteSchema defines model for ConversationModelDeleteSchema. type ConversationModelDeleteSchema struct { - Id *string `json:"id,omitempty"` + Id string `json:"id"` } // ConversationModelSchema defines model for ConversationModelSchema. @@ -1239,10 +1239,10 @@ type UpsertSearchOverrideJSONRequestBody = SearchOverrideSchema type UpsertSearchSynonymJSONRequestBody = SearchSynonymSchema // CreateConversationModelJSONRequestBody defines body for CreateConversationModel for application/json ContentType. -type CreateConversationModelJSONRequestBody = ConversationModelCreateSchema +type CreateConversationModelJSONRequestBody = ConversationModelCreateAndUpdateSchema // UpdateConversationModelJSONRequestBody defines body for UpdateConversationModel for application/json ContentType. -type UpdateConversationModelJSONRequestBody = ConversationModelCreateSchema +type UpdateConversationModelJSONRequestBody = ConversationModelCreateAndUpdateSchema // UpdateConversationJSONRequestBody defines body for UpdateConversation for application/json ContentType. type UpdateConversationJSONRequestBody = ConversationUpdateSchema diff --git a/typesense/conversation_model.go b/typesense/conversation_model.go index 855f20e..b32a434 100644 --- a/typesense/conversation_model.go +++ b/typesense/conversation_model.go @@ -8,7 +8,7 @@ import ( type ConversationModelInterface interface { Retrieve(ctx context.Context) (*api.ConversationModelSchema, error) - Update(ctx context.Context, model *api.ConversationModelCreateSchema) (*api.ConversationModelCreateSchema, error) + Update(ctx context.Context, model *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelCreateAndUpdateSchema, error) Delete(ctx context.Context) (*api.ConversationModelDeleteSchema, error) } @@ -28,8 +28,8 @@ func (c *conversationModel) Retrieve(ctx context.Context) (*api.ConversationMode return response.JSON200, nil } -func (c *conversationModel) Update(ctx context.Context, model *api.ConversationModelCreateSchema) (*api.ConversationModelCreateSchema, error) { - response, err := c.apiClient.UpdateConversationModelWithResponse(ctx, c.modelId, api.UpdateConversationModelJSONRequestBody(*model)) +func (c *conversationModel) Update(ctx context.Context, conversationModelCreateAndUpdateSchema *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelCreateAndUpdateSchema, error) { + response, err := c.apiClient.UpdateConversationModelWithResponse(ctx, c.modelId, api.UpdateConversationModelJSONRequestBody(*conversationModelCreateAndUpdateSchema)) if err != nil { return nil, err } diff --git a/typesense/conversation_model_test.go b/typesense/conversation_model_test.go new file mode 100644 index 0000000..9718db1 --- /dev/null +++ b/typesense/conversation_model_test.go @@ -0,0 +1,122 @@ +package typesense + +import ( + "context" + "encoding/json" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/typesense/typesense-go/typesense/api" +) + +func TestConversationModelRetrieve(t *testing.T) { + accountId, systemPrompt := "CLOUDFLARE_ACCOUNT_ID", "..." + expectedData := &api.ConversationModelSchema{ + Id: "123", + ModelName: "cf/mistral/mistral-7b-instruct-v0.1", + ApiKey: "CLOUDFLARE_API_KEY", + AccountId: &accountId, + SystemPrompt: &systemPrompt, + MaxBytes: 16384, + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/models/123", http.MethodGet) + data := jsonEncode(t, expectedData) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(data) + }) + defer server.Close() + + res, err := client.Conversations().Model("123").Retrieve(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestConversationModelRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/models/123", http.MethodGet) + w.WriteHeader(http.StatusNotFound) + }) + defer server.Close() + + _, err := client.Conversations().Model("123").Retrieve(context.Background()) + assert.Error(t, err) +} + +func TestConversationModelUpdate(t *testing.T) { + accountId, systemPrompt := "CLOUDFLARE_ACCOUNT_ID", "..." + expectedData := &api.ConversationModelCreateAndUpdateSchema{ + ModelName: "cf/mistral/mistral-7b-instruct-v0.1", + ApiKey: "CLOUDFLARE_API_KEY", + AccountId: &accountId, + SystemPrompt: &systemPrompt, + MaxBytes: 16384, + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/models/123", http.MethodPut) + + var reqBody api.ConversationModelCreateAndUpdateSchema + err := json.NewDecoder(r.Body).Decode(&reqBody) + + assert.NoError(t, err) + assert.Equal(t, expectedData, &reqBody) + + data := jsonEncode(t, expectedData) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(data) + }) + defer server.Close() + + res, err := client.Conversations().Model("123").Update(context.Background(), expectedData) + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestConversationModelUpdateOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/models/123", http.MethodPut) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Conversations().Model("123").Update(context.Background(), &api.ConversationModelCreateAndUpdateSchema{ + ModelName: "cf/mistral/mistral-7b-instruct-v0.1", + }) + assert.Error(t, err) +} + +func TestConversationModelDelete(t *testing.T) { + expectedData := &api.ConversationModelDeleteSchema{ + Id: "123", + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/models/123", http.MethodDelete) + + data := jsonEncode(t, expectedData) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(data) + }) + defer server.Close() + + res, err := client.Conversations().Model("123").Delete(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestConversationModelDeleteOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/conversations/models/123", http.MethodDelete) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Conversations().Model("123").Delete(context.Background()) + assert.Error(t, err) +} diff --git a/typesense/conversation_models.go b/typesense/conversation_models.go index 010cb32..c7b3596 100644 --- a/typesense/conversation_models.go +++ b/typesense/conversation_models.go @@ -8,7 +8,7 @@ import ( // ConversationModelsInterface is a type for ConversationModels API operations type ConversationModelsInterface interface { - Create(ctx context.Context, conversationModelCreateSchema *api.ConversationModelCreateSchema) (*api.ConversationModelCreateSchema, error) + Create(ctx context.Context, conversationModelCreateAndUpdateSchema *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelCreateAndUpdateSchema, error) Retrieve(ctx context.Context) ([]*api.ConversationModelSchema, error) } @@ -17,8 +17,8 @@ type conversationModels struct { apiClient APIClientInterface } -func (c *conversationModels) Create(ctx context.Context, conversationModelCreateSchema *api.ConversationModelCreateSchema) (*api.ConversationModelCreateSchema, error) { - response, err := c.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*conversationModelCreateSchema)) +func (c *conversationModels) Create(ctx context.Context, conversationModelCreateAndUpdateSchema *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelCreateAndUpdateSchema, error) { + response, err := c.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*conversationModelCreateAndUpdateSchema)) if err != nil { return nil, err } diff --git a/typesense/conversation_models_test.go b/typesense/conversation_models_test.go index 4fd008e..6420cc1 100644 --- a/typesense/conversation_models_test.go +++ b/typesense/conversation_models_test.go @@ -2,6 +2,7 @@ package typesense import ( "context" + "encoding/json" "net/http" "testing" @@ -47,7 +48,7 @@ func TestConversationModelsRetrieveOnHttpStatusErrorCodeReturnsError(t *testing. func TestConversationModelsCreate(t *testing.T) { accountId, systemPrompt := "CLOUDFLARE_ACCOUNT_ID", "..." - expectedData := &api.ConversationModelCreateSchema{ + expectedData := &api.ConversationModelCreateAndUpdateSchema{ ModelName: "cf/mistral/mistral-7b-instruct-v0.1", ApiKey: "CLOUDFLARE_API_KEY", AccountId: &accountId, @@ -57,6 +58,13 @@ func TestConversationModelsCreate(t *testing.T) { server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations/models", http.MethodPost) + + var reqBody api.ConversationModelCreateAndUpdateSchema + err := json.NewDecoder(r.Body).Decode(&reqBody) + + assert.NoError(t, err) + assert.Equal(t, expectedData, &reqBody) + data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) @@ -76,7 +84,7 @@ func TestConversationModelsCreateOnHttpStatusErrorCodeReturnsError(t *testing.T) }) defer server.Close() - _, err := client.Conversations().Models().Create(context.Background(), &api.ConversationModelCreateSchema{ + _, err := client.Conversations().Models().Create(context.Background(), &api.ConversationModelCreateAndUpdateSchema{ ModelName: "cf/mistral/mistral-7b-instruct-v0.1", }) assert.Error(t, err) diff --git a/typesense/conversation_test.go b/typesense/conversation_test.go index e5fc6b8..3f24f25 100644 --- a/typesense/conversation_test.go +++ b/typesense/conversation_test.go @@ -2,6 +2,7 @@ package typesense import ( "context" + "encoding/json" "net/http" "testing" @@ -51,8 +52,14 @@ func TestConversationUpdateConversation(t *testing.T) { server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations/123", http.MethodPut) - data := jsonEncode(t, expectedData) + var reqBody api.ConversationUpdateSchema + err := json.NewDecoder(r.Body).Decode(&reqBody) + + assert.NoError(t, err) + assert.Equal(t, expectedData, &reqBody) + + data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) w.Write(data) diff --git a/typesense/conversations.go b/typesense/conversations.go index cf13eac..20dcb1e 100644 --- a/typesense/conversations.go +++ b/typesense/conversations.go @@ -10,6 +10,7 @@ import ( type ConversationsInterface interface { Retrieve(ctx context.Context) ([]*api.ConversationSchema, error) Models() ConversationModelsInterface + Model(modelId string) ConversationModelInterface } // conversations is internal implementation of ConversationsInterface From e9aa9472e7625953b77381efe887487f129ac8de Mon Sep 17 00:00:00 2001 From: Hayden Date: Thu, 25 Jul 2024 13:43:56 +0700 Subject: [PATCH 09/19] update API schema, bump to v2 after rebase --- typesense/api/client_gen.go | 64 ++-- typesense/api/generator/generator.yml | 48 +-- typesense/api/generator/openapi.yml | 491 +++++++++++++------------- typesense/api/types_gen.go | 17 +- typesense/client.go | 2 +- typesense/conversation.go | 18 +- typesense/conversation_model.go | 6 +- typesense/conversation_model_test.go | 26 +- typesense/conversation_models.go | 6 +- typesense/conversation_models_test.go | 36 +- typesense/conversation_test.go | 48 +-- typesense/conversations.go | 4 +- typesense/conversations_test.go | 49 +-- typesense/mocks/mock_client.go | 230 ++++++------ 14 files changed, 507 insertions(+), 538 deletions(-) diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index 756519c..917d9bb 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -225,15 +225,15 @@ type ClientInterface interface { UpdateConversationModel(ctx context.Context, modelId string, body UpdateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // DeleteConversation request - DeleteConversation(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*http.Response, error) + DeleteConversation(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*http.Response, error) // RetrieveConversation request - RetrieveConversation(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*http.Response, error) + RetrieveConversation(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*http.Response, error) // UpdateConversationWithBody request with any body - UpdateConversationWithBody(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + UpdateConversationWithBody(ctx context.Context, conversationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - UpdateConversation(ctx context.Context, conversationId int64, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + UpdateConversation(ctx context.Context, conversationId string, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // Debug request Debug(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -889,7 +889,7 @@ func (c *Client) UpdateConversationModel(ctx context.Context, modelId string, bo return c.Client.Do(req) } -func (c *Client) DeleteConversation(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*http.Response, error) { +func (c *Client) DeleteConversation(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewDeleteConversationRequest(c.Server, conversationId) if err != nil { return nil, err @@ -901,7 +901,7 @@ func (c *Client) DeleteConversation(ctx context.Context, conversationId int64, r return c.Client.Do(req) } -func (c *Client) RetrieveConversation(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*http.Response, error) { +func (c *Client) RetrieveConversation(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewRetrieveConversationRequest(c.Server, conversationId) if err != nil { return nil, err @@ -913,7 +913,7 @@ func (c *Client) RetrieveConversation(ctx context.Context, conversationId int64, return c.Client.Do(req) } -func (c *Client) UpdateConversationWithBody(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { +func (c *Client) UpdateConversationWithBody(ctx context.Context, conversationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewUpdateConversationRequestWithBody(c.Server, conversationId, contentType, body) if err != nil { return nil, err @@ -925,7 +925,7 @@ func (c *Client) UpdateConversationWithBody(ctx context.Context, conversationId return c.Client.Do(req) } -func (c *Client) UpdateConversation(ctx context.Context, conversationId int64, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { +func (c *Client) UpdateConversation(ctx context.Context, conversationId string, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewUpdateConversationRequest(c.Server, conversationId, body) if err != nil { return nil, err @@ -3729,7 +3729,7 @@ func NewUpdateConversationModelRequestWithBody(server string, modelId string, co } // NewDeleteConversationRequest generates requests for DeleteConversation -func NewDeleteConversationRequest(server string, conversationId int64) (*http.Request, error) { +func NewDeleteConversationRequest(server string, conversationId string) (*http.Request, error) { var err error var pathParam0 string @@ -3763,7 +3763,7 @@ func NewDeleteConversationRequest(server string, conversationId int64) (*http.Re } // NewRetrieveConversationRequest generates requests for RetrieveConversation -func NewRetrieveConversationRequest(server string, conversationId int64) (*http.Request, error) { +func NewRetrieveConversationRequest(server string, conversationId string) (*http.Request, error) { var err error var pathParam0 string @@ -3797,7 +3797,7 @@ func NewRetrieveConversationRequest(server string, conversationId int64) (*http. } // NewUpdateConversationRequest calls the generic UpdateConversation builder with application/json body -func NewUpdateConversationRequest(server string, conversationId int64, body UpdateConversationJSONRequestBody) (*http.Request, error) { +func NewUpdateConversationRequest(server string, conversationId string, body UpdateConversationJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { @@ -3808,7 +3808,7 @@ func NewUpdateConversationRequest(server string, conversationId int64, body Upda } // NewUpdateConversationRequestWithBody generates requests for UpdateConversation with any type of body -func NewUpdateConversationRequestWithBody(server string, conversationId int64, contentType string, body io.Reader) (*http.Request, error) { +func NewUpdateConversationRequestWithBody(server string, conversationId string, contentType string, body io.Reader) (*http.Request, error) { var err error var pathParam0 string @@ -5547,15 +5547,15 @@ type ClientWithResponsesInterface interface { UpdateConversationModelWithResponse(ctx context.Context, modelId string, body UpdateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationModelResponse, error) // DeleteConversationWithResponse request - DeleteConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*DeleteConversationResponse, error) + DeleteConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*DeleteConversationResponse, error) // RetrieveConversationWithResponse request - RetrieveConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*RetrieveConversationResponse, error) + RetrieveConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*RetrieveConversationResponse, error) // UpdateConversationWithBodyWithResponse request with any body - UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) + UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) - UpdateConversationWithResponse(ctx context.Context, conversationId int64, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) + UpdateConversationWithResponse(ctx context.Context, conversationId string, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) // DebugWithResponse request DebugWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*DebugResponse, error) @@ -6343,7 +6343,7 @@ func (r UpsertSearchSynonymResponse) StatusCode() int { type RetrieveAllConversationsResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *ConversationsRetrieveSchema + JSON200 *[]*ConversationSchema } // Status returns HTTPResponse.Status @@ -6387,7 +6387,7 @@ func (r RetrieveAllConversationModelsResponse) StatusCode() int { type CreateConversationModelResponse struct { Body []byte HTTPResponse *http.Response - JSON201 *ConversationModelCreateAndUpdateSchema + JSON201 *ConversationModelSchema JSON400 *ApiResponse } @@ -6410,7 +6410,7 @@ func (r CreateConversationModelResponse) StatusCode() int { type DeleteConversationModelResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *ConversationModelDeleteSchema + JSON200 *ConversationModelSchema } // Status returns HTTPResponse.Status @@ -6476,7 +6476,7 @@ func (r UpdateConversationModelResponse) StatusCode() int { type DeleteConversationResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *ConversationDeleteSchema + JSON200 *ConversationSchema } // Status returns HTTPResponse.Status @@ -6498,7 +6498,7 @@ func (r DeleteConversationResponse) StatusCode() int { type RetrieveConversationResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *[]*ConversationSchema + JSON200 *ConversationSchema } // Status returns HTTPResponse.Status @@ -6520,7 +6520,7 @@ func (r RetrieveConversationResponse) StatusCode() int { type UpdateConversationResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *ConversationUpdateSchema + JSON200 *ConversationSchema } // Status returns HTTPResponse.Status @@ -7403,7 +7403,7 @@ func (c *ClientWithResponses) UpdateConversationModelWithResponse(ctx context.Co } // DeleteConversationWithResponse request returning *DeleteConversationResponse -func (c *ClientWithResponses) DeleteConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*DeleteConversationResponse, error) { +func (c *ClientWithResponses) DeleteConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*DeleteConversationResponse, error) { rsp, err := c.DeleteConversation(ctx, conversationId, reqEditors...) if err != nil { return nil, err @@ -7412,7 +7412,7 @@ func (c *ClientWithResponses) DeleteConversationWithResponse(ctx context.Context } // RetrieveConversationWithResponse request returning *RetrieveConversationResponse -func (c *ClientWithResponses) RetrieveConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...RequestEditorFn) (*RetrieveConversationResponse, error) { +func (c *ClientWithResponses) RetrieveConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*RetrieveConversationResponse, error) { rsp, err := c.RetrieveConversation(ctx, conversationId, reqEditors...) if err != nil { return nil, err @@ -7421,7 +7421,7 @@ func (c *ClientWithResponses) RetrieveConversationWithResponse(ctx context.Conte } // UpdateConversationWithBodyWithResponse request with arbitrary body returning *UpdateConversationResponse -func (c *ClientWithResponses) UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) { +func (c *ClientWithResponses) UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) { rsp, err := c.UpdateConversationWithBody(ctx, conversationId, contentType, body, reqEditors...) if err != nil { return nil, err @@ -7429,7 +7429,7 @@ func (c *ClientWithResponses) UpdateConversationWithBodyWithResponse(ctx context return ParseUpdateConversationResponse(rsp) } -func (c *ClientWithResponses) UpdateConversationWithResponse(ctx context.Context, conversationId int64, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) { +func (c *ClientWithResponses) UpdateConversationWithResponse(ctx context.Context, conversationId string, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) { rsp, err := c.UpdateConversation(ctx, conversationId, body, reqEditors...) if err != nil { return nil, err @@ -8676,7 +8676,7 @@ func ParseRetrieveAllConversationsResponse(rsp *http.Response) (*RetrieveAllConv switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ConversationsRetrieveSchema + var dest []*ConversationSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -8728,7 +8728,7 @@ func ParseCreateConversationModelResponse(rsp *http.Response) (*CreateConversati switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: - var dest ConversationModelCreateAndUpdateSchema + var dest ConversationModelSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -8761,7 +8761,7 @@ func ParseDeleteConversationModelResponse(rsp *http.Response) (*DeleteConversati switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ConversationModelDeleteSchema + var dest ConversationModelSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -8839,7 +8839,7 @@ func ParseDeleteConversationResponse(rsp *http.Response) (*DeleteConversationRes switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ConversationDeleteSchema + var dest ConversationSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -8865,7 +8865,7 @@ func ParseRetrieveConversationResponse(rsp *http.Response) (*RetrieveConversatio switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest []*ConversationSchema + var dest ConversationSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -8891,7 +8891,7 @@ func ParseUpdateConversationResponse(rsp *http.Response) (*UpdateConversationRes switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ConversationUpdateSchema + var dest ConversationSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index e1de379..2fcfe8f 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -288,13 +288,6 @@ components: - api_key - max_bytes type: object - ConversationModelDeleteSchema: - properties: - id: - type: string - required: - - id - type: object ConversationModelSchema: allOf: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' @@ -311,7 +304,7 @@ components: type: object type: array id: - type: integer + type: string last_updated: type: integer ttl: @@ -330,16 +323,6 @@ components: type: integer required: - ttl - ConversationsRetrieveSchema: - properties: - conversations: - items: - $ref: '#/components/schemas/ConversationSchema' - type: array - x-go-type: '[]*ConversationSchema' - required: - - conversations - type: object ErrorResponse: properties: message: @@ -2513,8 +2496,11 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationsRetrieveSchema' - description: List of all past conversations + items: + $ref: '#/components/schemas/ConversationSchema' + type: array + x-go-type: '[]*ConversationSchema' + description: A list of all past conversations summary: List all past conversations tags: - conversations @@ -2528,14 +2514,13 @@ paths: name: conversationId required: true schema: - format: int64 - type: integer + type: string responses: 200: content: application/json: schema: - $ref: '#/components/schemas/ConversationDeleteSchema' + $ref: '#/components/schemas/ConversationSchema' description: The conversation was successfully deleted summary: Delete a past conversation tags: @@ -2549,17 +2534,13 @@ paths: name: conversationId required: true schema: - format: int64 - type: integer + type: string responses: 200: content: application/json: schema: - items: - $ref: '#/components/schemas/ConversationSchema' - type: array - x-go-type: '[]*ConversationSchema' + $ref: '#/components/schemas/ConversationSchema' description: A past conversation summary: Retrieve a past conversation tags: @@ -2573,8 +2554,7 @@ paths: name: conversationId required: true schema: - format: int64 - type: integer + type: string requestBody: content: application/json: @@ -2586,7 +2566,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationUpdateSchema' + $ref: '#/components/schemas/ConversationSchema' description: The conversation was successfully updated summary: Update the TTL for a past conversation tags: @@ -2622,7 +2602,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' + $ref: '#/components/schemas/ConversationModelSchema' description: Created Conversation Model 400: content: @@ -2648,7 +2628,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelDeleteSchema' + $ref: '#/components/schemas/ConversationModelSchema' description: The conversation model was successfully deleted summary: Delete a conversation model tags: diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index 61dc1fe..ed2011b 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -51,6 +51,11 @@ tags: externalDocs: description: Find out more url: https://typesense.org/docs/26.0/api/search.html#presets + - name: conversations + description: Conversational Search (RAG) + externalDocs: + description: Find out more + url: https://typesense.org/docs/26.0/api/conversational-search-rag.html paths: /collections: get: @@ -879,202 +884,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ApiResponse' - /conversations: - get: - description: Retrieve all past conversations - operationId: retrieveAllConversations - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationsRetrieveSchema' - description: List of all past conversations - summary: List all past conversations - tags: - - conversations - /conversations/{conversationId}: - get: - description: Retrieve a conversation - operationId: retrieveConversation - parameters: - - name: conversationId - in: path - description: The id of the conversation to retrieve - required: true - schema: - type: integer - format: int64 - responses: - 200: - content: - application/json: - schema: - items: - $ref: '#/components/schemas/ConversationSchema' - type: array - x-go-type: '[]*ConversationSchema' - description: A past conversation - summary: Retrieve a past conversation - tags: - - conversations - put: - description: Update the TTL for a conversation - operationId: updateConversation - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationUpdateSchema' - required: true - parameters: - - name: conversationId - in: path - description: The id of the conversation to update - required: true - schema: - type: integer - format: int64 - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationUpdateSchema' - description: The conversation was successfully updated - summary: Update the TTL for a past conversation - tags: - - conversations - delete: - description: Delete a past conversation - operationId: deleteConversation - parameters: - - name: conversationId - in: path - description: The id of the conversation to delete - required: true - schema: - type: integer - format: int64 - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationDeleteSchema' - description: The conversation was successfully deleted - summary: Delete a past conversation - tags: - - conversations - /conversations/models: - get: - description: Retrieve all conversation models - operationId: retrieveAllConversationModels - responses: - 200: - content: - application/json: - schema: - items: - $ref: '#/components/schemas/ConversationModelSchema' - type: array - x-go-type: '[]*ConversationModelSchema' - description: List of all conversation models - summary: List all conversation models - tags: - - conversations - post: - description: Create a Conversation Model - operationId: createConversationModel - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - required: true - responses: - 201: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - description: Created Conversation Model - 400: - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponse' - description: Bad request, see error message for details - tags: - - conversations - /conversations/models/{modelId}: - get: - description: Retrieve a conversation model - operationId: retrieveConversationModel - parameters: - - name: modelId - in: path - description: The id of the conversation model to retrieve - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelSchema' - description: A conversation model - summary: Retrieve a conversation model - tags: - - conversations - put: - description: Update a conversation model - operationId: updateConversationModel - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - required: true - parameters: - - name: modelId - in: path - description: The id of the conversation model to update - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - description: The conversation model was successfully updated - summary: Update a conversation model - tags: - - conversations - delete: - description: Delete a conversation model - operationId: deleteConversationModel - parameters: - - name: modelId - in: path - description: The id of the conversation model to delete - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelDeleteSchema' - description: The conversation model was successfully deleted - summary: Delete a conversation model - tags: - - conversations + $ref: "#/components/schemas/ApiResponse" /keys: get: tags: @@ -1778,6 +1588,198 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' + /conversations: + get: + description: Retrieve all past conversations + operationId: retrieveAllConversations + responses: + 200: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ConversationSchema' + x-go-type: "[]*ConversationSchema" + description: A list of all past conversations + summary: List all past conversations + tags: + - conversations + /conversations/{conversationId}: + get: + description: Retrieve a conversation + operationId: retrieveConversation + parameters: + - name: conversationId + in: path + description: The id of the conversation to retrieve + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationSchema' + description: A past conversation + summary: Retrieve a past conversation + tags: + - conversations + put: + description: Update the TTL for a conversation + operationId: updateConversation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationUpdateSchema' + required: true + parameters: + - name: conversationId + in: path + description: The id of the conversation to update + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationSchema' + description: The conversation was successfully updated + summary: Update the TTL for a past conversation + tags: + - conversations + delete: + description: Delete a past conversation + operationId: deleteConversation + parameters: + - name: conversationId + in: path + description: The id of the conversation to delete + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationSchema' + description: The conversation was successfully deleted + summary: Delete a past conversation + tags: + - conversations + /conversations/models: + get: + description: Retrieve all conversation models + operationId: retrieveAllConversationModels + responses: + 200: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/ConversationModelSchema' + type: array + x-go-type: '[]*ConversationModelSchema' + description: List of all conversation models + summary: List all conversation models + tags: + - conversations + post: + description: Create a Conversation Model + operationId: createConversationModel + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' + required: true + responses: + 201: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + description: Created Conversation Model + 400: + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + description: Bad request, see error message for details + tags: + - conversations + /conversations/models/{modelId}: + get: + description: Retrieve a conversation model + operationId: retrieveConversationModel + parameters: + - name: modelId + in: path + description: The id of the conversation model to retrieve + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + description: A conversation model + summary: Retrieve a conversation model + tags: + - conversations + put: + description: Update a conversation model + operationId: updateConversationModel + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' + required: true + parameters: + - name: modelId + in: path + description: The id of the conversation model to update + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' + description: The conversation model was successfully updated + summary: Update a conversation model + tags: + - conversations + delete: + description: Delete a conversation model + operationId: deleteConversationModel + parameters: + - name: modelId + in: path + description: The id of the conversation model to delete + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + description: The conversation model was successfully deleted + summary: Delete a conversation model + tags: + - conversations components: schemas: CollectionSchema: @@ -3191,10 +3193,44 @@ components: - stopwords example: | {"stopwords": [{"id": "countries", "stopwords": ["Germany", "France", "Italy"], "locale": "en"}]} + PresetUpsertSchema: + properties: + value: + oneOf: + - $ref: '#/components/schemas/SearchParameters' + - $ref: '#/components/schemas/MultiSearchSearchesParameter' + required: + - value + PresetSchema: + allOf: + - $ref: '#/components/schemas/PresetUpsertSchema' + - type: object + required: + - name + properties: + name: + type: string + PresetsRetrieveSchema: + type: object + required: + - presets + properties: + presets: + type: array + items: + $ref: '#/components/schemas/PresetSchema' + x-go-type: '[]*PresetSchema' + PresetDeleteSchema: + type: object + required: + - name + properties: + name: + type: string ConversationSchema: properties: id: - type: integer + type: string conversation: items: type: object @@ -3223,58 +3259,41 @@ components: type: integer required: - id - ConversationsRetrieveSchema: - type: object - required: - - conversations - properties: - conversations: - type: array - items: - $ref: '#/components/schemas/ConversationSchema' - x-go-type: '[]*ConversationSchema' ConversationModelCreateAndUpdateSchema: properties: - value: - oneOf: - - $ref: '#/components/schemas/SearchParameters' - - $ref: '#/components/schemas/MultiSearchSearchesParameter' + model_name: + description: Name of the LLM model offered by OpenAI, Cloudflare or vLLM + type: string + api_key: + description: The LLM service's API Key + type: string + account_id: + description: LLM service's account ID (only applicable for Cloudflare) + type: string + system_prompt: + description: The system prompt that contains special instructions to the LLM + type: string + max_bytes: + description: | + The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. + type: integer + vllm_url: + description: URL of vLLM service + type: string required: - model_name - api_key - - system_prompt - max_bytes type: object - ConversationModelDeleteSchema: - properties: - id: - type: string - required: - - id - type: object ConversationModelSchema: allOf: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - properties: id: type: string - PresetsRetrieveSchema: - type: object - required: - - presets - properties: - presets: - type: array - items: - $ref: '#/components/schemas/PresetSchema' - x-go-type: '[]*PresetSchema' - PresetDeleteSchema: - type: object - required: - - name - properties: - name: - type: string + type: object + required: + - id securitySchemes: api_key_header: type: apiKey diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index 292cf53..d7f7931 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -176,11 +176,6 @@ type CollectionUpdateSchema struct { Fields []Field `json:"fields"` } -// ConversationDeleteSchema defines model for ConversationDeleteSchema. -type ConversationDeleteSchema struct { - Id int `json:"id"` -} - // ConversationModelCreateAndUpdateSchema defines model for ConversationModelCreateAndUpdateSchema. type ConversationModelCreateAndUpdateSchema struct { // AccountId LLM service's account ID (only applicable for Cloudflare) @@ -202,11 +197,6 @@ type ConversationModelCreateAndUpdateSchema struct { VllmUrl *string `json:"vllm_url,omitempty"` } -// ConversationModelDeleteSchema defines model for ConversationModelDeleteSchema. -type ConversationModelDeleteSchema struct { - Id string `json:"id"` -} - // ConversationModelSchema defines model for ConversationModelSchema. type ConversationModelSchema struct { // AccountId LLM service's account ID (only applicable for Cloudflare) @@ -232,7 +222,7 @@ type ConversationModelSchema struct { // ConversationSchema defines model for ConversationSchema. type ConversationSchema struct { Conversation []map[string]interface{} `json:"conversation"` - Id int `json:"id"` + Id string `json:"id"` LastUpdated int `json:"last_updated"` // Ttl Time to live. Conversations are stored by default for 24 hours, and then purged. @@ -245,11 +235,6 @@ type ConversationUpdateSchema struct { Ttl int `json:"ttl"` } -// ConversationsRetrieveSchema defines model for ConversationsRetrieveSchema. -type ConversationsRetrieveSchema struct { - Conversations []*ConversationSchema `json:"conversations"` -} - // FacetCounts defines model for FacetCounts. type FacetCounts struct { Counts *[]struct { diff --git a/typesense/client.go b/typesense/client.go index ac31ab1..d3c9231 100644 --- a/typesense/client.go +++ b/typesense/client.go @@ -48,7 +48,7 @@ func (c *Client) Conversations() ConversationsInterface { return &conversations{apiClient: c.apiClient} } -func (c *Client) Conversation(conversationId int64) ConversationInterface { +func (c *Client) Conversation(conversationId string) ConversationInterface { return &conversation{apiClient: c.apiClient, conversationId: conversationId} } diff --git a/typesense/conversation.go b/typesense/conversation.go index 81e84bc..70e48bb 100644 --- a/typesense/conversation.go +++ b/typesense/conversation.go @@ -3,21 +3,21 @@ package typesense import ( "context" - "github.com/typesense/typesense-go/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api" ) type ConversationInterface interface { - Retrieve(ctx context.Context) ([]*api.ConversationSchema, error) - Update(ctx context.Context, conversation *api.ConversationUpdateSchema) (*api.ConversationUpdateSchema, error) - Delete(ctx context.Context) (*api.ConversationDeleteSchema, error) + Retrieve(ctx context.Context) (*api.ConversationSchema, error) + Update(ctx context.Context, conversation *api.ConversationUpdateSchema) (*api.ConversationSchema, error) + Delete(ctx context.Context) (*api.ConversationSchema, error) } type conversation struct { apiClient APIClientInterface - conversationId int64 + conversationId string } -func (c *conversation) Retrieve(ctx context.Context) ([]*api.ConversationSchema, error) { +func (c *conversation) Retrieve(ctx context.Context) (*api.ConversationSchema, error) { response, err := c.apiClient.RetrieveConversationWithResponse(ctx, c.conversationId) if err != nil { return nil, err @@ -25,10 +25,10 @@ func (c *conversation) Retrieve(ctx context.Context) ([]*api.ConversationSchema, if response.JSON200 == nil { return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} } - return *response.JSON200, nil + return response.JSON200, nil } -func (c *conversation) Update(ctx context.Context, conversation *api.ConversationUpdateSchema) (*api.ConversationUpdateSchema, error) { +func (c *conversation) Update(ctx context.Context, conversation *api.ConversationUpdateSchema) (*api.ConversationSchema, error) { response, err := c.apiClient.UpdateConversationWithResponse(ctx, c.conversationId, api.UpdateConversationJSONRequestBody(*conversation)) if err != nil { return nil, err @@ -39,7 +39,7 @@ func (c *conversation) Update(ctx context.Context, conversation *api.Conversatio return response.JSON200, nil } -func (c *conversation) Delete(ctx context.Context) (*api.ConversationDeleteSchema, error) { +func (c *conversation) Delete(ctx context.Context) (*api.ConversationSchema, error) { response, err := c.apiClient.DeleteConversationWithResponse(ctx, c.conversationId) if err != nil { return nil, err diff --git a/typesense/conversation_model.go b/typesense/conversation_model.go index b32a434..75206cd 100644 --- a/typesense/conversation_model.go +++ b/typesense/conversation_model.go @@ -3,13 +3,13 @@ package typesense import ( "context" - "github.com/typesense/typesense-go/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api" ) type ConversationModelInterface interface { Retrieve(ctx context.Context) (*api.ConversationModelSchema, error) Update(ctx context.Context, model *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelCreateAndUpdateSchema, error) - Delete(ctx context.Context) (*api.ConversationModelDeleteSchema, error) + Delete(ctx context.Context) (*api.ConversationModelSchema, error) } type conversationModel struct { @@ -39,7 +39,7 @@ func (c *conversationModel) Update(ctx context.Context, conversationModelCreateA return response.JSON200, nil } -func (c *conversationModel) Delete(ctx context.Context) (*api.ConversationModelDeleteSchema, error) { +func (c *conversationModel) Delete(ctx context.Context) (*api.ConversationModelSchema, error) { response, err := c.apiClient.DeleteConversationModelWithResponse(ctx, c.modelId) if err != nil { return nil, err diff --git a/typesense/conversation_model_test.go b/typesense/conversation_model_test.go index 9718db1..5a6fd5d 100644 --- a/typesense/conversation_model_test.go +++ b/typesense/conversation_model_test.go @@ -7,17 +7,17 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/typesense/typesense-go/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api/pointer" ) func TestConversationModelRetrieve(t *testing.T) { - accountId, systemPrompt := "CLOUDFLARE_ACCOUNT_ID", "..." expectedData := &api.ConversationModelSchema{ Id: "123", ModelName: "cf/mistral/mistral-7b-instruct-v0.1", ApiKey: "CLOUDFLARE_API_KEY", - AccountId: &accountId, - SystemPrompt: &systemPrompt, + AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), + SystemPrompt: pointer.String("..."), MaxBytes: 16384, } @@ -25,7 +25,6 @@ func TestConversationModelRetrieve(t *testing.T) { validateRequestMetadata(t, r, "/conversations/models/123", http.MethodGet) data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) w.Write(data) }) defer server.Close() @@ -38,21 +37,20 @@ func TestConversationModelRetrieve(t *testing.T) { func TestConversationModelRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations/models/123", http.MethodGet) - w.WriteHeader(http.StatusNotFound) + w.WriteHeader(http.StatusConflict) }) defer server.Close() _, err := client.Conversations().Model("123").Retrieve(context.Background()) - assert.Error(t, err) + assert.ErrorContains(t, err, "status: 409") } func TestConversationModelUpdate(t *testing.T) { - accountId, systemPrompt := "CLOUDFLARE_ACCOUNT_ID", "..." expectedData := &api.ConversationModelCreateAndUpdateSchema{ ModelName: "cf/mistral/mistral-7b-instruct-v0.1", ApiKey: "CLOUDFLARE_API_KEY", - AccountId: &accountId, - SystemPrompt: &systemPrompt, + AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), + SystemPrompt: pointer.String("..."), MaxBytes: 16384, } @@ -67,7 +65,6 @@ func TestConversationModelUpdate(t *testing.T) { data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) w.Write(data) }) defer server.Close() @@ -87,11 +84,11 @@ func TestConversationModelUpdateOnHttpStatusErrorCodeReturnsError(t *testing.T) _, err := client.Conversations().Model("123").Update(context.Background(), &api.ConversationModelCreateAndUpdateSchema{ ModelName: "cf/mistral/mistral-7b-instruct-v0.1", }) - assert.Error(t, err) + assert.ErrorContains(t, err, "status: 409") } func TestConversationModelDelete(t *testing.T) { - expectedData := &api.ConversationModelDeleteSchema{ + expectedData := &api.ConversationModelSchema{ Id: "123", } @@ -100,7 +97,6 @@ func TestConversationModelDelete(t *testing.T) { data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) w.Write(data) }) defer server.Close() @@ -118,5 +114,5 @@ func TestConversationModelDeleteOnHttpStatusErrorCodeReturnsError(t *testing.T) defer server.Close() _, err := client.Conversations().Model("123").Delete(context.Background()) - assert.Error(t, err) + assert.ErrorContains(t, err, "status: 409") } diff --git a/typesense/conversation_models.go b/typesense/conversation_models.go index c7b3596..2e16a55 100644 --- a/typesense/conversation_models.go +++ b/typesense/conversation_models.go @@ -3,12 +3,12 @@ package typesense import ( "context" - "github.com/typesense/typesense-go/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api" ) // ConversationModelsInterface is a type for ConversationModels API operations type ConversationModelsInterface interface { - Create(ctx context.Context, conversationModelCreateAndUpdateSchema *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelCreateAndUpdateSchema, error) + Create(ctx context.Context, conversationModelCreateAndUpdateSchema *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelSchema, error) Retrieve(ctx context.Context) ([]*api.ConversationModelSchema, error) } @@ -17,7 +17,7 @@ type conversationModels struct { apiClient APIClientInterface } -func (c *conversationModels) Create(ctx context.Context, conversationModelCreateAndUpdateSchema *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelCreateAndUpdateSchema, error) { +func (c *conversationModels) Create(ctx context.Context, conversationModelCreateAndUpdateSchema *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelSchema, error) { response, err := c.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*conversationModelCreateAndUpdateSchema)) if err != nil { return nil, err diff --git a/typesense/conversation_models_test.go b/typesense/conversation_models_test.go index 6420cc1..61200f1 100644 --- a/typesense/conversation_models_test.go +++ b/typesense/conversation_models_test.go @@ -7,17 +7,17 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/typesense/typesense-go/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api/pointer" ) func TestConversationModelsRetrieve(t *testing.T) { - accountId, systemPrompt := "CLOUDFLARE_ACCOUNT_ID", "..." expectedData := []*api.ConversationModelSchema{{ Id: "123", ModelName: "cf/mistral/mistral-7b-instruct-v0.1", ApiKey: "CLOUDFLARE_API_KEY", - AccountId: &accountId, - SystemPrompt: &systemPrompt, + AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), + SystemPrompt: pointer.String("..."), MaxBytes: 16384, }} @@ -25,7 +25,6 @@ func TestConversationModelsRetrieve(t *testing.T) { validateRequestMetadata(t, r, "/conversations/models", http.MethodGet) data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) w.Write(data) }) defer server.Close() @@ -43,18 +42,25 @@ func TestConversationModelsRetrieveOnHttpStatusErrorCodeReturnsError(t *testing. defer server.Close() _, err := client.Conversations().Models().Retrieve(context.Background()) - assert.Error(t, err) + assert.ErrorContains(t, err, "status: 409") } func TestConversationModelsCreate(t *testing.T) { - accountId, systemPrompt := "CLOUDFLARE_ACCOUNT_ID", "..." - expectedData := &api.ConversationModelCreateAndUpdateSchema{ + model := &api.ConversationModelCreateAndUpdateSchema{ ModelName: "cf/mistral/mistral-7b-instruct-v0.1", ApiKey: "CLOUDFLARE_API_KEY", - AccountId: &accountId, - SystemPrompt: &systemPrompt, + AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), + SystemPrompt: pointer.String("..."), MaxBytes: 16384, } + expectedData := &api.ConversationModelSchema{ + Id: "123", + ModelName: model.ModelName, + ApiKey: model.ApiKey, + AccountId: model.AccountId, + SystemPrompt: model.SystemPrompt, + MaxBytes: model.MaxBytes, + } server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations/models", http.MethodPost) @@ -63,7 +69,7 @@ func TestConversationModelsCreate(t *testing.T) { err := json.NewDecoder(r.Body).Decode(&reqBody) assert.NoError(t, err) - assert.Equal(t, expectedData, &reqBody) + assert.Equal(t, model, &reqBody) data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") @@ -72,7 +78,7 @@ func TestConversationModelsCreate(t *testing.T) { }) defer server.Close() - res, err := client.Conversations().Models().Create(context.Background(), expectedData) + res, err := client.Conversations().Models().Create(context.Background(), model) assert.NoError(t, err) assert.Equal(t, expectedData, res) } @@ -84,8 +90,6 @@ func TestConversationModelsCreateOnHttpStatusErrorCodeReturnsError(t *testing.T) }) defer server.Close() - _, err := client.Conversations().Models().Create(context.Background(), &api.ConversationModelCreateAndUpdateSchema{ - ModelName: "cf/mistral/mistral-7b-instruct-v0.1", - }) - assert.Error(t, err) + _, err := client.Conversations().Models().Create(context.Background(), &api.ConversationModelCreateAndUpdateSchema{}) + assert.ErrorContains(t, err, "status: 409") } diff --git a/typesense/conversation_test.go b/typesense/conversation_test.go index 3f24f25..b6f92b1 100644 --- a/typesense/conversation_test.go +++ b/typesense/conversation_test.go @@ -7,30 +7,33 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/typesense/typesense-go/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api" ) func TestConversationRetrieveConversation(t *testing.T) { - expectedData := []*api.ConversationSchema{{ - Id: 1, + expectedData := &api.ConversationSchema{ + Id: "123", Conversation: []map[string]any{ - {"any": "any"}, - }, + { + "user": "can you suggest an action series", + }, + { + "assistant": "...", + }}, LastUpdated: 12, Ttl: 34, - }} + } server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations/123", http.MethodGet) data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) w.Write(data) }) defer server.Close() - res, err := client.Conversation(123).Retrieve(context.Background()) + res, err := client.Conversation(expectedData.Id).Retrieve(context.Background()) assert.NoError(t, err) assert.Equal(t, expectedData, res) } @@ -42,11 +45,14 @@ func TestConversationRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { }) defer server.Close() - _, err := client.Conversation(123).Retrieve(context.Background()) - assert.Error(t, err) + _, err := client.Conversation("123").Retrieve(context.Background()) + assert.ErrorContains(t, err, "status: 409") } func TestConversationUpdateConversation(t *testing.T) { - expectedData := &api.ConversationUpdateSchema{ + expectedData := &api.ConversationSchema{ + Id: "123", + } + updateData := &api.ConversationUpdateSchema{ Ttl: 3000, } @@ -57,16 +63,15 @@ func TestConversationUpdateConversation(t *testing.T) { err := json.NewDecoder(r.Body).Decode(&reqBody) assert.NoError(t, err) - assert.Equal(t, expectedData, &reqBody) + assert.Equal(t, updateData, &reqBody) data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) w.Write(data) }) defer server.Close() - res, err := client.Conversation(123).Update(context.Background(), expectedData) + res, err := client.Conversation("123").Update(context.Background(), updateData) assert.NoError(t, err) assert.Equal(t, expectedData, res) @@ -79,15 +84,15 @@ func TestConversationUpdateOnHttpStatusErrorCodeReturnsError(t *testing.T) { }) defer server.Close() - _, err := client.Conversation(123).Update(context.Background(), &api.ConversationUpdateSchema{ + _, err := client.Conversation("123").Update(context.Background(), &api.ConversationUpdateSchema{ Ttl: 0, }) - assert.Error(t, err) + assert.ErrorContains(t, err, "status: 409") } func TestConversationDeleteConversation(t *testing.T) { - expectedData := &api.ConversationDeleteSchema{ - Id: 123, + expectedData := &api.ConversationSchema{ + Id: "123", } server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { @@ -95,12 +100,11 @@ func TestConversationDeleteConversation(t *testing.T) { data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) w.Write(data) }) defer server.Close() - res, err := client.Conversation(123).Delete(context.Background()) + res, err := client.Conversation("123").Delete(context.Background()) assert.NoError(t, err) assert.Equal(t, expectedData, res) @@ -113,6 +117,6 @@ func TestConversationDeleteOnHttpStatusErrorCodeReturnsError(t *testing.T) { }) defer server.Close() - _, err := client.Conversation(123).Delete(context.Background()) - assert.Error(t, err) + _, err := client.Conversation("123").Delete(context.Background()) + assert.ErrorContains(t, err, "status: 409") } diff --git a/typesense/conversations.go b/typesense/conversations.go index 20dcb1e..2837bb5 100644 --- a/typesense/conversations.go +++ b/typesense/conversations.go @@ -3,7 +3,7 @@ package typesense import ( "context" - "github.com/typesense/typesense-go/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api" ) // ConversationsInterface is a type for Conversations API operations @@ -26,7 +26,7 @@ func (c *conversations) Retrieve(ctx context.Context) ([]*api.ConversationSchema if response.JSON200 == nil { return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} } - return response.JSON200.Conversations, nil + return *response.JSON200, nil } func (c *conversations) Models() ConversationModelsInterface { diff --git a/typesense/conversations_test.go b/typesense/conversations_test.go index de4067c..9168dcd 100644 --- a/typesense/conversations_test.go +++ b/typesense/conversations_test.go @@ -2,60 +2,41 @@ package typesense import ( "context" - "encoding/json" "net/http" - "net/http/httptest" "testing" "github.com/stretchr/testify/assert" - "github.com/typesense/typesense-go/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api" ) -func newTestServerAndClient(handler func(w http.ResponseWriter, r *http.Request)) (*httptest.Server, *Client) { - server := httptest.NewServer(http.HandlerFunc(handler)) - return server, NewClient(WithServer(server.URL)) -} - -func validateRequestMetadata(t *testing.T, r *http.Request, expectedEndpoint string, expectedMethod string) { - if r.RequestURI != expectedEndpoint { - t.Fatal("Invalid request endpoint!") - } - if r.Method != expectedMethod { - t.Fatal("Invalid HTTP method!") - } -} - -func jsonEncode(t *testing.T, v any) []byte { - t.Helper() - data, err := json.Marshal(v) - assert.NoError(t, err) - return data -} func TestConversationsRetrieveAllConversations(t *testing.T) { - expectedData := api.ConversationsRetrieveSchema{ - Conversations: []*api.ConversationSchema{ - { - Id: 1, - Conversation: []map[string]any{ - {"any": "any"}, + expectedData := []*api.ConversationSchema{ + { + Id: "abc", + Conversation: []map[string]any{ + { + "user": "can you suggest an action series", + }, + { + "assistant": "...", }, - LastUpdated: 12, - Ttl: 34, }, + LastUpdated: 12, + Ttl: 86400, }, } + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations", http.MethodGet) data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) w.Write(data) }) defer server.Close() res, err := client.Conversations().Retrieve(context.Background()) assert.NoError(t, err) - assert.Equal(t, expectedData.Conversations, res) + assert.Equal(t, expectedData, res) } func TestConversationsRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { @@ -66,5 +47,5 @@ func TestConversationsRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { defer server.Close() _, err := client.Conversations().Retrieve(context.Background()) - assert.NotNil(t, err) + assert.ErrorContains(t, err, "status: 409") } diff --git a/typesense/mocks/mock_client.go b/typesense/mocks/mock_client.go index 5baa8f4..65c436f 100644 --- a/typesense/mocks/mock_client.go +++ b/typesense/mocks/mock_client.go @@ -523,7 +523,7 @@ func (mr *MockAPIClientInterfaceMockRecorder) DeleteCollectionWithResponse(ctx, } // DeleteConversation mocks base method. -func (m *MockAPIClientInterface) DeleteConversation(ctx context.Context, conversationId int64, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +func (m *MockAPIClientInterface) DeleteConversation(ctx context.Context, conversationId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() varargs := []any{ctx, conversationId} for _, a := range reqEditors { @@ -583,7 +583,7 @@ func (mr *MockAPIClientInterfaceMockRecorder) DeleteConversationModelWithRespons } // DeleteConversationWithResponse mocks base method. -func (m *MockAPIClientInterface) DeleteConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...api.RequestEditorFn) (*api.DeleteConversationResponse, error) { +func (m *MockAPIClientInterface) DeleteConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...api.RequestEditorFn) (*api.DeleteConversationResponse, error) { m.ctrl.T.Helper() varargs := []any{ctx, conversationId} for _, a := range reqEditors { @@ -1642,124 +1642,124 @@ func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAPIStatsWithResponse(ctx a return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAPIStatsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAPIStatsWithResponse), varargs...) } -// RetrieveAllPresets mocks base method. -func (m *MockAPIClientInterface) RetrieveAllPresets(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// RetrieveAllConversationModels mocks base method. +func (m *MockAPIClientInterface) RetrieveAllConversationModels(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() varargs := []any{ctx} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveAllPresets", varargs...) + ret := m.ctrl.Call(m, "RetrieveAllConversationModels", varargs...) ret0, _ := ret[0].(*http.Response) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveAllPresets indicates an expected call of RetrieveAllPresets. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllPresets(ctx any, reqEditors ...any) *gomock.Call { +// RetrieveAllConversationModels indicates an expected call of RetrieveAllConversationModels. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationModels(ctx any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]any{ctx}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllPresets", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllPresets), varargs...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationModels", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationModels), varargs...) } -// RetrieveAllPresetsWithResponse mocks base method. -func (m *MockAPIClientInterface) RetrieveAllPresetsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveAllPresetsResponse, error) { +// RetrieveAllConversationModelsWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrieveAllConversationModelsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveAllConversationModelsResponse, error) { m.ctrl.T.Helper() varargs := []any{ctx} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveAllPresetsWithResponse", varargs...) - ret0, _ := ret[0].(*api.RetrieveAllPresetsResponse) + ret := m.ctrl.Call(m, "RetrieveAllConversationModelsWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrieveAllConversationModelsResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveAllPresetsWithResponse indicates an expected call of RetrieveAllPresetsWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllPresetsWithResponse(ctx any, reqEditors ...any) *gomock.Call { +// RetrieveAllConversationModelsWithResponse indicates an expected call of RetrieveAllConversationModelsWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationModelsWithResponse(ctx any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]any{ctx}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllPresetsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllPresetsWithResponse), varargs...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationModelsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationModelsWithResponse), varargs...) } -// RetrieveAllConversationModels mocks base method. -func (m *MockAPIClientInterface) RetrieveAllConversationModels(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// RetrieveAllConversations mocks base method. +func (m *MockAPIClientInterface) RetrieveAllConversations(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() varargs := []any{ctx} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveAllConversationModels", varargs...) + ret := m.ctrl.Call(m, "RetrieveAllConversations", varargs...) ret0, _ := ret[0].(*http.Response) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveAllConversationModels indicates an expected call of RetrieveAllConversationModels. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationModels(ctx any, reqEditors ...any) *gomock.Call { +// RetrieveAllConversations indicates an expected call of RetrieveAllConversations. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversations(ctx any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]any{ctx}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationModels", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationModels), varargs...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversations", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversations), varargs...) } -// RetrieveAllConversationModelsWithResponse mocks base method. -func (m *MockAPIClientInterface) RetrieveAllConversationModelsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveAllConversationModelsResponse, error) { +// RetrieveAllConversationsWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrieveAllConversationsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveAllConversationsResponse, error) { m.ctrl.T.Helper() varargs := []any{ctx} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveAllConversationModelsWithResponse", varargs...) - ret0, _ := ret[0].(*api.RetrieveAllConversationModelsResponse) + ret := m.ctrl.Call(m, "RetrieveAllConversationsWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrieveAllConversationsResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveAllConversationModelsWithResponse indicates an expected call of RetrieveAllConversationModelsWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationModelsWithResponse(ctx any, reqEditors ...any) *gomock.Call { +// RetrieveAllConversationsWithResponse indicates an expected call of RetrieveAllConversationsWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationsWithResponse(ctx any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]any{ctx}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationModelsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationModelsWithResponse), varargs...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationsWithResponse), varargs...) } -// RetrieveAllConversations mocks base method. -func (m *MockAPIClientInterface) RetrieveAllConversations(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// RetrieveAllPresets mocks base method. +func (m *MockAPIClientInterface) RetrieveAllPresets(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() varargs := []any{ctx} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveAllConversations", varargs...) + ret := m.ctrl.Call(m, "RetrieveAllPresets", varargs...) ret0, _ := ret[0].(*http.Response) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveAllConversations indicates an expected call of RetrieveAllConversations. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversations(ctx any, reqEditors ...any) *gomock.Call { +// RetrieveAllPresets indicates an expected call of RetrieveAllPresets. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllPresets(ctx any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]any{ctx}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversations", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversations), varargs...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllPresets", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllPresets), varargs...) } -// RetrieveAllConversationsWithResponse mocks base method. -func (m *MockAPIClientInterface) RetrieveAllConversationsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveAllConversationsResponse, error) { +// RetrieveAllPresetsWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrieveAllPresetsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveAllPresetsResponse, error) { m.ctrl.T.Helper() varargs := []any{ctx} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveAllConversationsWithResponse", varargs...) - ret0, _ := ret[0].(*api.RetrieveAllConversationsResponse) + ret := m.ctrl.Call(m, "RetrieveAllPresetsWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrieveAllPresetsResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveAllConversationsWithResponse indicates an expected call of RetrieveAllConversationsWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationsWithResponse(ctx any, reqEditors ...any) *gomock.Call { +// RetrieveAllPresetsWithResponse indicates an expected call of RetrieveAllPresetsWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllPresetsWithResponse(ctx any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]any{ctx}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationsWithResponse), varargs...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllPresetsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllPresetsWithResponse), varargs...) } // RetrieveAnalyticsRule mocks base method. @@ -1842,164 +1842,164 @@ func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAnalyticsRulesWithResponse return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAnalyticsRulesWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAnalyticsRulesWithResponse), varargs...) } -// RetrieveMetrics mocks base method. -func (m *MockAPIClientInterface) RetrieveMetrics(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// RetrieveConversation mocks base method. +func (m *MockAPIClientInterface) RetrieveConversation(ctx context.Context, conversationId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() - varargs := []any{ctx} + varargs := []any{ctx, conversationId} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveMetrics", varargs...) + ret := m.ctrl.Call(m, "RetrieveConversation", varargs...) ret0, _ := ret[0].(*http.Response) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveMetrics indicates an expected call of RetrieveMetrics. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveMetrics(ctx any, reqEditors ...any) *gomock.Call { +// RetrieveConversation indicates an expected call of RetrieveConversation. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversation(ctx, conversationId any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveMetrics", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveMetrics), varargs...) + varargs := append([]any{ctx, conversationId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversation), varargs...) } -// RetrieveMetricsWithResponse mocks base method. -func (m *MockAPIClientInterface) RetrieveMetricsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveMetricsResponse, error) { +// RetrieveConversationModel mocks base method. +func (m *MockAPIClientInterface) RetrieveConversationModel(ctx context.Context, modelId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() - varargs := []any{ctx} + varargs := []any{ctx, modelId} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveMetricsWithResponse", varargs...) - ret0, _ := ret[0].(*api.RetrieveMetricsResponse) + ret := m.ctrl.Call(m, "RetrieveConversationModel", varargs...) + ret0, _ := ret[0].(*http.Response) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveMetricsWithResponse indicates an expected call of RetrieveMetricsWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveMetricsWithResponse(ctx any, reqEditors ...any) *gomock.Call { +// RetrieveConversationModel indicates an expected call of RetrieveConversationModel. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationModel(ctx, modelId any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveMetricsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveMetricsWithResponse), varargs...) + varargs := append([]any{ctx, modelId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationModel", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationModel), varargs...) } -// RetrievePreset mocks base method. -func (m *MockAPIClientInterface) RetrievePreset(ctx context.Context, presetId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// RetrieveConversationModelWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrieveConversationModelWithResponse(ctx context.Context, modelId string, reqEditors ...api.RequestEditorFn) (*api.RetrieveConversationModelResponse, error) { m.ctrl.T.Helper() - varargs := []any{ctx, presetId} + varargs := []any{ctx, modelId} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrievePreset", varargs...) - ret0, _ := ret[0].(*http.Response) + ret := m.ctrl.Call(m, "RetrieveConversationModelWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrieveConversationModelResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrievePreset indicates an expected call of RetrievePreset. -func (mr *MockAPIClientInterfaceMockRecorder) RetrievePreset(ctx, presetId any, reqEditors ...any) *gomock.Call { +// RetrieveConversationModelWithResponse indicates an expected call of RetrieveConversationModelWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationModelWithResponse(ctx, modelId any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, presetId}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrievePreset", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrievePreset), varargs...) + varargs := append([]any{ctx, modelId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationModelWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationModelWithResponse), varargs...) } -// RetrievePresetWithResponse mocks base method. -func (m *MockAPIClientInterface) RetrievePresetWithResponse(ctx context.Context, presetId string, reqEditors ...api.RequestEditorFn) (*api.RetrievePresetResponse, error) { +// RetrieveConversationWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrieveConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...api.RequestEditorFn) (*api.RetrieveConversationResponse, error) { m.ctrl.T.Helper() - varargs := []any{ctx, presetId} + varargs := []any{ctx, conversationId} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrievePresetWithResponse", varargs...) - ret0, _ := ret[0].(*api.RetrievePresetResponse) + ret := m.ctrl.Call(m, "RetrieveConversationWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrieveConversationResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrievePresetWithResponse indicates an expected call of RetrievePresetWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) RetrievePresetWithResponse(ctx, presetId any, reqEditors ...any) *gomock.Call { +// RetrieveConversationWithResponse indicates an expected call of RetrieveConversationWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationWithResponse(ctx, conversationId any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, presetId}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrievePresetWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrievePresetWithResponse), varargs...) + varargs := append([]any{ctx, conversationId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationWithResponse), varargs...) } -// RetrieveConversation mocks base method. -func (m *MockAPIClientInterface) RetrieveConversation(ctx context.Context, conversationId int64, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// RetrieveMetrics mocks base method. +func (m *MockAPIClientInterface) RetrieveMetrics(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() - varargs := []any{ctx, conversationId} + varargs := []any{ctx} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveConversation", varargs...) + ret := m.ctrl.Call(m, "RetrieveMetrics", varargs...) ret0, _ := ret[0].(*http.Response) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveConversation indicates an expected call of RetrieveConversation. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversation(ctx, conversationId any, reqEditors ...any) *gomock.Call { +// RetrieveMetrics indicates an expected call of RetrieveMetrics. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveMetrics(ctx any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, conversationId}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversation), varargs...) + varargs := append([]any{ctx}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveMetrics", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveMetrics), varargs...) } -// RetrieveConversationModel mocks base method. -func (m *MockAPIClientInterface) RetrieveConversationModel(ctx context.Context, modelId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// RetrieveMetricsWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrieveMetricsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveMetricsResponse, error) { m.ctrl.T.Helper() - varargs := []any{ctx, modelId} + varargs := []any{ctx} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveConversationModel", varargs...) - ret0, _ := ret[0].(*http.Response) + ret := m.ctrl.Call(m, "RetrieveMetricsWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrieveMetricsResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveConversationModel indicates an expected call of RetrieveConversationModel. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationModel(ctx, modelId any, reqEditors ...any) *gomock.Call { +// RetrieveMetricsWithResponse indicates an expected call of RetrieveMetricsWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrieveMetricsWithResponse(ctx any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, modelId}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationModel", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationModel), varargs...) + varargs := append([]any{ctx}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveMetricsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveMetricsWithResponse), varargs...) } -// RetrieveConversationModelWithResponse mocks base method. -func (m *MockAPIClientInterface) RetrieveConversationModelWithResponse(ctx context.Context, modelId string, reqEditors ...api.RequestEditorFn) (*api.RetrieveConversationModelResponse, error) { +// RetrievePreset mocks base method. +func (m *MockAPIClientInterface) RetrievePreset(ctx context.Context, presetId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() - varargs := []any{ctx, modelId} + varargs := []any{ctx, presetId} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveConversationModelWithResponse", varargs...) - ret0, _ := ret[0].(*api.RetrieveConversationModelResponse) + ret := m.ctrl.Call(m, "RetrievePreset", varargs...) + ret0, _ := ret[0].(*http.Response) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveConversationModelWithResponse indicates an expected call of RetrieveConversationModelWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationModelWithResponse(ctx, modelId any, reqEditors ...any) *gomock.Call { +// RetrievePreset indicates an expected call of RetrievePreset. +func (mr *MockAPIClientInterfaceMockRecorder) RetrievePreset(ctx, presetId any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, modelId}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationModelWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationModelWithResponse), varargs...) + varargs := append([]any{ctx, presetId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrievePreset", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrievePreset), varargs...) } -// RetrieveConversationWithResponse mocks base method. -func (m *MockAPIClientInterface) RetrieveConversationWithResponse(ctx context.Context, conversationId int64, reqEditors ...api.RequestEditorFn) (*api.RetrieveConversationResponse, error) { +// RetrievePresetWithResponse mocks base method. +func (m *MockAPIClientInterface) RetrievePresetWithResponse(ctx context.Context, presetId string, reqEditors ...api.RequestEditorFn) (*api.RetrievePresetResponse, error) { m.ctrl.T.Helper() - varargs := []any{ctx, conversationId} + varargs := []any{ctx, presetId} for _, a := range reqEditors { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RetrieveConversationWithResponse", varargs...) - ret0, _ := ret[0].(*api.RetrieveConversationResponse) + ret := m.ctrl.Call(m, "RetrievePresetWithResponse", varargs...) + ret0, _ := ret[0].(*api.RetrievePresetResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// RetrieveConversationWithResponse indicates an expected call of RetrieveConversationWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationWithResponse(ctx, conversationId any, reqEditors ...any) *gomock.Call { +// RetrievePresetWithResponse indicates an expected call of RetrievePresetWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) RetrievePresetWithResponse(ctx, presetId any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, conversationId}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationWithResponse), varargs...) + varargs := append([]any{ctx, presetId}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrievePresetWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrievePresetWithResponse), varargs...) } // RetrieveStopwordsSet mocks base method. @@ -2243,7 +2243,7 @@ func (mr *MockAPIClientInterfaceMockRecorder) UpdateCollectionWithResponse(ctx, } // UpdateConversation mocks base method. -func (m *MockAPIClientInterface) UpdateConversation(ctx context.Context, conversationId int64, body api.UpdateConversationJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +func (m *MockAPIClientInterface) UpdateConversation(ctx context.Context, conversationId string, body api.UpdateConversationJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() varargs := []any{ctx, conversationId, body} for _, a := range reqEditors { @@ -2343,7 +2343,7 @@ func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationModelWithRespons } // UpdateConversationWithBody mocks base method. -func (m *MockAPIClientInterface) UpdateConversationWithBody(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +func (m *MockAPIClientInterface) UpdateConversationWithBody(ctx context.Context, conversationId, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() varargs := []any{ctx, conversationId, contentType, body} for _, a := range reqEditors { @@ -2363,7 +2363,7 @@ func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationWithBody(ctx, co } // UpdateConversationWithBodyWithResponse mocks base method. -func (m *MockAPIClientInterface) UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId int64, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*api.UpdateConversationResponse, error) { +func (m *MockAPIClientInterface) UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*api.UpdateConversationResponse, error) { m.ctrl.T.Helper() varargs := []any{ctx, conversationId, contentType, body} for _, a := range reqEditors { @@ -2383,7 +2383,7 @@ func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationWithBodyWithResp } // UpdateConversationWithResponse mocks base method. -func (m *MockAPIClientInterface) UpdateConversationWithResponse(ctx context.Context, conversationId int64, body api.UpdateConversationJSONRequestBody, reqEditors ...api.RequestEditorFn) (*api.UpdateConversationResponse, error) { +func (m *MockAPIClientInterface) UpdateConversationWithResponse(ctx context.Context, conversationId string, body api.UpdateConversationJSONRequestBody, reqEditors ...api.RequestEditorFn) (*api.UpdateConversationResponse, error) { m.ctrl.T.Helper() varargs := []any{ctx, conversationId, body} for _, a := range reqEditors { From ac813b8f2f8ffa91d51896ff2bea037365a0dbb6 Mon Sep 17 00:00:00 2001 From: Hayden Date: Sun, 15 Sep 2024 16:24:34 +0700 Subject: [PATCH 10/19] feat: Typesense v27 conversation API --- typesense/api/client_gen.go | 877 ++++++++++++-------------- typesense/api/generator/generator.yml | 515 ++++++++++----- typesense/api/generator/openapi.yml | 698 ++++++++++++-------- typesense/api/types_gen.go | 356 +++++++++-- typesense/client.go | 4 - typesense/conversation.go | 51 -- typesense/conversation_model.go | 6 +- typesense/conversation_model_test.go | 39 +- typesense/conversation_models.go | 10 +- typesense/conversation_models_test.go | 46 +- typesense/conversation_test.go | 122 ---- typesense/conversations.go | 18 - typesense/conversations_test.go | 51 -- typesense/documents_test.go | 48 ++ typesense/mocks/mock_client.go | 280 +++----- typesense/multi_search_test.go | 51 ++ 16 files changed, 1731 insertions(+), 1441 deletions(-) delete mode 100644 typesense/conversation.go delete mode 100644 typesense/conversation_test.go delete mode 100644 typesense/conversations_test.go diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index 917d9bb..55a2c3d 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -103,6 +103,11 @@ type ClientInterface interface { UpsertAlias(ctx context.Context, aliasName string, body UpsertAliasJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // CreateAnalyticsEventWithBody request with any body + CreateAnalyticsEventWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + CreateAnalyticsEvent(ctx context.Context, body CreateAnalyticsEventJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // RetrieveAnalyticsRules request RetrieveAnalyticsRules(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -202,9 +207,6 @@ type ClientInterface interface { UpsertSearchSynonym(ctx context.Context, collectionName string, synonymId string, body UpsertSearchSynonymJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // RetrieveAllConversations request - RetrieveAllConversations(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - // RetrieveAllConversationModels request RetrieveAllConversationModels(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -224,17 +226,6 @@ type ClientInterface interface { UpdateConversationModel(ctx context.Context, modelId string, body UpdateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // DeleteConversation request - DeleteConversation(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*http.Response, error) - - // RetrieveConversation request - RetrieveConversation(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*http.Response, error) - - // UpdateConversationWithBody request with any body - UpdateConversationWithBody(ctx context.Context, conversationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - UpdateConversation(ctx context.Context, conversationId string, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // Debug request Debug(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -361,6 +352,30 @@ func (c *Client) UpsertAlias(ctx context.Context, aliasName string, body UpsertA return c.Client.Do(req) } +func (c *Client) CreateAnalyticsEventWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateAnalyticsEventRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreateAnalyticsEvent(ctx context.Context, body CreateAnalyticsEventJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateAnalyticsEventRequest(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) RetrieveAnalyticsRules(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewRetrieveAnalyticsRulesRequest(c.Server) if err != nil { @@ -793,18 +808,6 @@ func (c *Client) UpsertSearchSynonym(ctx context.Context, collectionName string, return c.Client.Do(req) } -func (c *Client) RetrieveAllConversations(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewRetrieveAllConversationsRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - func (c *Client) RetrieveAllConversationModels(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewRetrieveAllConversationModelsRequest(c.Server) if err != nil { @@ -889,54 +892,6 @@ func (c *Client) UpdateConversationModel(ctx context.Context, modelId string, bo return c.Client.Do(req) } -func (c *Client) DeleteConversation(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteConversationRequest(c.Server, conversationId) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) RetrieveConversation(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewRetrieveConversationRequest(c.Server, conversationId) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) UpdateConversationWithBody(ctx context.Context, conversationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateConversationRequestWithBody(c.Server, conversationId, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) UpdateConversation(ctx context.Context, conversationId string, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateConversationRequest(c.Server, conversationId, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - func (c *Client) Debug(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewDebugRequest(c.Server) if err != nil { @@ -1355,6 +1310,46 @@ func NewUpsertAliasRequestWithBody(server string, aliasName string, contentType return req, nil } +// NewCreateAnalyticsEventRequest calls the generic CreateAnalyticsEvent builder with application/json body +func NewCreateAnalyticsEventRequest(server string, body CreateAnalyticsEventJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewCreateAnalyticsEventRequestWithBody(server, "application/json", bodyReader) +} + +// NewCreateAnalyticsEventRequestWithBody generates requests for CreateAnalyticsEvent with any type of body +func NewCreateAnalyticsEventRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/analytics/events") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewRetrieveAnalyticsRulesRequest generates requests for RetrieveAnalyticsRules func NewRetrieveAnalyticsRulesRequest(server string) (*http.Request, error) { var err error @@ -1780,6 +1775,22 @@ func NewDeleteDocumentsRequest(server string, collectionName string, params *Del } + if params.IgnoreNotFound != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "ignore_not_found", runtime.ParamLocationQuery, *params.IgnoreNotFound); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + queryURL.RawQuery = queryValues.Encode() } @@ -1916,6 +1927,22 @@ func NewIndexDocumentRequestWithBody(server string, collectionName string, param } + if params.DirtyValues != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "dirty_values", runtime.ParamLocationQuery, *params.DirtyValues); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + queryURL.RawQuery = queryValues.Encode() } @@ -2110,6 +2137,38 @@ func NewImportDocumentsRequestWithBody(server string, collectionName string, par } + if params.ReturnDoc != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "return_doc", runtime.ParamLocationQuery, *params.ReturnDoc); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.ReturnId != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "return_id", runtime.ParamLocationQuery, *params.ReturnId); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + queryURL.RawQuery = queryValues.Encode() } @@ -2168,6 +2227,54 @@ func NewSearchCollectionRequest(server string, collectionName string, params *Se } + if params.Conversation != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "conversation", runtime.ParamLocationQuery, *params.Conversation); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.ConversationId != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "conversation_id", runtime.ParamLocationQuery, *params.ConversationId); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.ConversationModelId != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "conversation_model_id", runtime.ParamLocationQuery, *params.ConversationModelId); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.DropTokensThreshold != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "drop_tokens_threshold", runtime.ParamLocationQuery, *params.DropTokensThreshold); err != nil { @@ -2376,6 +2483,22 @@ func NewSearchCollectionRequest(server string, collectionName string, params *Se } + if params.GroupMissingValues != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "group_missing_values", runtime.ParamLocationQuery, *params.GroupMissingValues); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.HiddenHits != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "hidden_hits", runtime.ParamLocationQuery, *params.HiddenHits); err != nil { @@ -3032,6 +3155,22 @@ func NewSearchCollectionRequest(server string, collectionName string, params *Se } + if params.VoiceQuery != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "voice_query", runtime.ParamLocationQuery, *params.VoiceQuery); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + queryURL.RawQuery = queryValues.Encode() } @@ -3519,8 +3658,8 @@ func NewUpsertSearchSynonymRequestWithBody(server string, collectionName string, return req, nil } -// NewRetrieveAllConversationsRequest generates requests for RetrieveAllConversations -func NewRetrieveAllConversationsRequest(server string) (*http.Request, error) { +// NewRetrieveAllConversationModelsRequest generates requests for RetrieveAllConversationModels +func NewRetrieveAllConversationModelsRequest(server string) (*http.Request, error) { var err error serverURL, err := url.Parse(server) @@ -3528,7 +3667,7 @@ func NewRetrieveAllConversationsRequest(server string) (*http.Request, error) { return nil, err } - operationPath := fmt.Sprintf("/conversations") + operationPath := fmt.Sprintf("/conversations/models") if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -3546,43 +3685,16 @@ func NewRetrieveAllConversationsRequest(server string) (*http.Request, error) { return req, nil } -// NewRetrieveAllConversationModelsRequest generates requests for RetrieveAllConversationModels -func NewRetrieveAllConversationModelsRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) +// NewCreateConversationModelRequest calls the generic CreateConversationModel builder with application/json body +func NewCreateConversationModelRequest(server string, body CreateConversationModelJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) if err != nil { return nil, err } - - operationPath := fmt.Sprintf("/conversations/models") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewCreateConversationModelRequest calls the generic CreateConversationModel builder with application/json body -func NewCreateConversationModelRequest(server string, body CreateConversationModelJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewCreateConversationModelRequestWithBody(server, "application/json", bodyReader) -} + bodyReader = bytes.NewReader(buf) + return NewCreateConversationModelRequestWithBody(server, "application/json", bodyReader) +} // NewCreateConversationModelRequestWithBody generates requests for CreateConversationModel with any type of body func NewCreateConversationModelRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { @@ -3728,121 +3840,6 @@ func NewUpdateConversationModelRequestWithBody(server string, modelId string, co return req, nil } -// NewDeleteConversationRequest generates requests for DeleteConversation -func NewDeleteConversationRequest(server string, conversationId string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "conversationId", runtime.ParamLocationPath, conversationId) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/conversations/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("DELETE", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewRetrieveConversationRequest generates requests for RetrieveConversation -func NewRetrieveConversationRequest(server string, conversationId string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "conversationId", runtime.ParamLocationPath, conversationId) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/conversations/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewUpdateConversationRequest calls the generic UpdateConversation builder with application/json body -func NewUpdateConversationRequest(server string, conversationId string, body UpdateConversationJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewUpdateConversationRequestWithBody(server, conversationId, "application/json", bodyReader) -} - -// NewUpdateConversationRequestWithBody generates requests for UpdateConversation with any type of body -func NewUpdateConversationRequestWithBody(server string, conversationId string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "conversationId", runtime.ParamLocationPath, conversationId) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/conversations/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("PUT", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - // NewDebugRequest generates requests for Debug func NewDebugRequest(server string) (*http.Request, error) { var err error @@ -4108,6 +4105,54 @@ func NewMultiSearchRequestWithBody(server string, params *MultiSearchParams, con } + if params.Conversation != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "conversation", runtime.ParamLocationQuery, *params.Conversation); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.ConversationId != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "conversation_id", runtime.ParamLocationQuery, *params.ConversationId); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.ConversationModelId != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "conversation_model_id", runtime.ParamLocationQuery, *params.ConversationModelId); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.DropTokensThreshold != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "drop_tokens_threshold", runtime.ParamLocationQuery, *params.DropTokensThreshold); err != nil { @@ -4316,6 +4361,22 @@ func NewMultiSearchRequestWithBody(server string, params *MultiSearchParams, con } + if params.GroupMissingValues != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "group_missing_values", runtime.ParamLocationQuery, *params.GroupMissingValues); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.HiddenHits != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "hidden_hits", runtime.ParamLocationQuery, *params.HiddenHits); err != nil { @@ -4972,6 +5033,22 @@ func NewMultiSearchRequestWithBody(server string, params *MultiSearchParams, con } + if params.VoiceQuery != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "voice_query", runtime.ParamLocationQuery, *params.VoiceQuery); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + queryURL.RawQuery = queryValues.Encode() } @@ -5425,6 +5502,11 @@ type ClientWithResponsesInterface interface { UpsertAliasWithResponse(ctx context.Context, aliasName string, body UpsertAliasJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertAliasResponse, error) + // CreateAnalyticsEventWithBodyWithResponse request with any body + CreateAnalyticsEventWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateAnalyticsEventResponse, error) + + CreateAnalyticsEventWithResponse(ctx context.Context, body CreateAnalyticsEventJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateAnalyticsEventResponse, error) + // RetrieveAnalyticsRulesWithResponse request RetrieveAnalyticsRulesWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAnalyticsRulesResponse, error) @@ -5524,9 +5606,6 @@ type ClientWithResponsesInterface interface { UpsertSearchSynonymWithResponse(ctx context.Context, collectionName string, synonymId string, body UpsertSearchSynonymJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertSearchSynonymResponse, error) - // RetrieveAllConversationsWithResponse request - RetrieveAllConversationsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAllConversationsResponse, error) - // RetrieveAllConversationModelsWithResponse request RetrieveAllConversationModelsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAllConversationModelsResponse, error) @@ -5546,17 +5625,6 @@ type ClientWithResponsesInterface interface { UpdateConversationModelWithResponse(ctx context.Context, modelId string, body UpdateConversationModelJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationModelResponse, error) - // DeleteConversationWithResponse request - DeleteConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*DeleteConversationResponse, error) - - // RetrieveConversationWithResponse request - RetrieveConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*RetrieveConversationResponse, error) - - // UpdateConversationWithBodyWithResponse request with any body - UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) - - UpdateConversationWithResponse(ctx context.Context, conversationId string, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) - // DebugWithResponse request DebugWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*DebugResponse, error) @@ -5715,6 +5783,29 @@ func (r UpsertAliasResponse) StatusCode() int { return 0 } +type CreateAnalyticsEventResponse struct { + Body []byte + HTTPResponse *http.Response + JSON201 *AnalyticsEventCreateResponse + JSON400 *ApiResponse +} + +// Status returns HTTPResponse.Status +func (r CreateAnalyticsEventResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CreateAnalyticsEventResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type RetrieveAnalyticsRulesResponse struct { Body []byte HTTPResponse *http.Response @@ -5763,7 +5854,7 @@ func (r CreateAnalyticsRuleResponse) StatusCode() int { type DeleteAnalyticsRuleResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *AnalyticsRuleSchema + JSON200 *AnalyticsRuleDeleteResponse JSON404 *ApiResponse } @@ -5809,7 +5900,7 @@ func (r RetrieveAnalyticsRuleResponse) StatusCode() int { type UpsertAnalyticsRuleResponse struct { Body []byte HTTPResponse *http.Response - JSON201 *AnalyticsRuleSchema + JSON200 *AnalyticsRuleSchema JSON400 *ApiResponse } @@ -6340,28 +6431,6 @@ func (r UpsertSearchSynonymResponse) StatusCode() int { return 0 } -type RetrieveAllConversationsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *[]*ConversationSchema -} - -// Status returns HTTPResponse.Status -func (r RetrieveAllConversationsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r RetrieveAllConversationsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - type RetrieveAllConversationModelsResponse struct { Body []byte HTTPResponse *http.Response @@ -6387,7 +6456,7 @@ func (r RetrieveAllConversationModelsResponse) StatusCode() int { type CreateConversationModelResponse struct { Body []byte HTTPResponse *http.Response - JSON201 *ConversationModelSchema + JSON200 *ConversationModelSchema JSON400 *ApiResponse } @@ -6454,7 +6523,7 @@ func (r RetrieveConversationModelResponse) StatusCode() int { type UpdateConversationModelResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *ConversationModelCreateAndUpdateSchema + JSON200 *ConversationModelSchema } // Status returns HTTPResponse.Status @@ -6473,72 +6542,6 @@ func (r UpdateConversationModelResponse) StatusCode() int { return 0 } -type DeleteConversationResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ConversationSchema -} - -// Status returns HTTPResponse.Status -func (r DeleteConversationResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r DeleteConversationResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type RetrieveConversationResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ConversationSchema -} - -// Status returns HTTPResponse.Status -func (r RetrieveConversationResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r RetrieveConversationResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type UpdateConversationResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ConversationSchema -} - -// Status returns HTTPResponse.Status -func (r UpdateConversationResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r UpdateConversationResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - type DebugResponse struct { Body []byte HTTPResponse *http.Response @@ -7017,6 +7020,23 @@ func (c *ClientWithResponses) UpsertAliasWithResponse(ctx context.Context, alias return ParseUpsertAliasResponse(rsp) } +// CreateAnalyticsEventWithBodyWithResponse request with arbitrary body returning *CreateAnalyticsEventResponse +func (c *ClientWithResponses) CreateAnalyticsEventWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateAnalyticsEventResponse, error) { + rsp, err := c.CreateAnalyticsEventWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateAnalyticsEventResponse(rsp) +} + +func (c *ClientWithResponses) CreateAnalyticsEventWithResponse(ctx context.Context, body CreateAnalyticsEventJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateAnalyticsEventResponse, error) { + rsp, err := c.CreateAnalyticsEvent(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateAnalyticsEventResponse(rsp) +} + // RetrieveAnalyticsRulesWithResponse request returning *RetrieveAnalyticsRulesResponse func (c *ClientWithResponses) RetrieveAnalyticsRulesWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAnalyticsRulesResponse, error) { rsp, err := c.RetrieveAnalyticsRules(ctx, reqEditors...) @@ -7332,15 +7352,6 @@ func (c *ClientWithResponses) UpsertSearchSynonymWithResponse(ctx context.Contex return ParseUpsertSearchSynonymResponse(rsp) } -// RetrieveAllConversationsWithResponse request returning *RetrieveAllConversationsResponse -func (c *ClientWithResponses) RetrieveAllConversationsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAllConversationsResponse, error) { - rsp, err := c.RetrieveAllConversations(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParseRetrieveAllConversationsResponse(rsp) -} - // RetrieveAllConversationModelsWithResponse request returning *RetrieveAllConversationModelsResponse func (c *ClientWithResponses) RetrieveAllConversationModelsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*RetrieveAllConversationModelsResponse, error) { rsp, err := c.RetrieveAllConversationModels(ctx, reqEditors...) @@ -7402,41 +7413,6 @@ func (c *ClientWithResponses) UpdateConversationModelWithResponse(ctx context.Co return ParseUpdateConversationModelResponse(rsp) } -// DeleteConversationWithResponse request returning *DeleteConversationResponse -func (c *ClientWithResponses) DeleteConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*DeleteConversationResponse, error) { - rsp, err := c.DeleteConversation(ctx, conversationId, reqEditors...) - if err != nil { - return nil, err - } - return ParseDeleteConversationResponse(rsp) -} - -// RetrieveConversationWithResponse request returning *RetrieveConversationResponse -func (c *ClientWithResponses) RetrieveConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...RequestEditorFn) (*RetrieveConversationResponse, error) { - rsp, err := c.RetrieveConversation(ctx, conversationId, reqEditors...) - if err != nil { - return nil, err - } - return ParseRetrieveConversationResponse(rsp) -} - -// UpdateConversationWithBodyWithResponse request with arbitrary body returning *UpdateConversationResponse -func (c *ClientWithResponses) UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) { - rsp, err := c.UpdateConversationWithBody(ctx, conversationId, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseUpdateConversationResponse(rsp) -} - -func (c *ClientWithResponses) UpdateConversationWithResponse(ctx context.Context, conversationId string, body UpdateConversationJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateConversationResponse, error) { - rsp, err := c.UpdateConversation(ctx, conversationId, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseUpdateConversationResponse(rsp) -} - // DebugWithResponse request returning *DebugResponse func (c *ClientWithResponses) DebugWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*DebugResponse, error) { rsp, err := c.Debug(ctx, reqEditors...) @@ -7772,6 +7748,39 @@ func ParseUpsertAliasResponse(rsp *http.Response) (*UpsertAliasResponse, error) return response, nil } +// ParseCreateAnalyticsEventResponse parses an HTTP response from a CreateAnalyticsEventWithResponse call +func ParseCreateAnalyticsEventResponse(rsp *http.Response) (*CreateAnalyticsEventResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CreateAnalyticsEventResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: + var dest AnalyticsEventCreateResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON201 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest ApiResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + + return response, nil +} + // ParseRetrieveAnalyticsRulesResponse parses an HTTP response from a RetrieveAnalyticsRulesWithResponse call func ParseRetrieveAnalyticsRulesResponse(rsp *http.Response) (*RetrieveAnalyticsRulesResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -7846,7 +7855,7 @@ func ParseDeleteAnalyticsRuleResponse(rsp *http.Response) (*DeleteAnalyticsRuleR switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AnalyticsRuleSchema + var dest AnalyticsRuleDeleteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -7911,12 +7920,12 @@ func ParseUpsertAnalyticsRuleResponse(rsp *http.Response) (*UpsertAnalyticsRuleR } switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: var dest AnalyticsRuleSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON201 = &dest + response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: var dest ApiResponse @@ -8661,32 +8670,6 @@ func ParseUpsertSearchSynonymResponse(rsp *http.Response) (*UpsertSearchSynonymR return response, nil } -// ParseRetrieveAllConversationsResponse parses an HTTP response from a RetrieveAllConversationsWithResponse call -func ParseRetrieveAllConversationsResponse(rsp *http.Response) (*RetrieveAllConversationsResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &RetrieveAllConversationsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest []*ConversationSchema - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - // ParseRetrieveAllConversationModelsResponse parses an HTTP response from a RetrieveAllConversationModelsWithResponse call func ParseRetrieveAllConversationModelsResponse(rsp *http.Response) (*RetrieveAllConversationModelsResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -8727,12 +8710,12 @@ func ParseCreateConversationModelResponse(rsp *http.Response) (*CreateConversati } switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: var dest ConversationModelSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON201 = &dest + response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: var dest ApiResponse @@ -8813,85 +8796,7 @@ func ParseUpdateConversationModelResponse(rsp *http.Response) (*UpdateConversati switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ConversationModelCreateAndUpdateSchema - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParseDeleteConversationResponse parses an HTTP response from a DeleteConversationWithResponse call -func ParseDeleteConversationResponse(rsp *http.Response) (*DeleteConversationResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &DeleteConversationResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ConversationSchema - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParseRetrieveConversationResponse parses an HTTP response from a RetrieveConversationWithResponse call -func ParseRetrieveConversationResponse(rsp *http.Response) (*RetrieveConversationResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &RetrieveConversationResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ConversationSchema - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParseUpdateConversationResponse parses an HTTP response from a UpdateConversationWithResponse call -func ParseUpdateConversationResponse(rsp *http.Response) (*UpdateConversationResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &UpdateConversationResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ConversationSchema + var dest ConversationModelSchema if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index 2fcfe8f..5a8e3c4 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -42,37 +42,101 @@ components: format: double type: number type: object + AnalyticsEventCreateResponse: + properties: + ok: + type: boolean + required: + - ok + type: object + AnalyticsEventCreateSchema: + properties: + data: + type: object + name: + type: string + type: + type: string + required: + - type + - name + - data + type: object + AnalyticsRuleDeleteResponse: + properties: + name: + type: string + required: + - name + type: object AnalyticsRuleParameters: properties: destination: - properties: - collection: - type: string - type: object + $ref: '#/components/schemas/AnalyticsRuleParametersDestination' + expand_query: + type: boolean limit: type: integer source: - properties: - collections: - items: - type: string - type: array - type: object + $ref: '#/components/schemas/AnalyticsRuleParametersSource' required: - source - destination - - limit type: object - AnalyticsRuleSchema: + AnalyticsRuleParametersDestination: properties: - name: + collection: + type: string + counter_field: type: string + required: + - collection + type: object + AnalyticsRuleParametersSource: + properties: + collections: + items: + type: string + type: array + events: + items: + properties: + name: + type: string + type: + type: string + weight: + format: float + type: number + required: + - type + - weight + - name + type: object + type: array + required: + - collections + type: object + AnalyticsRuleSchema: + allOf: + - $ref: '#/components/schemas/AnalyticsRuleUpsertSchema' + - properties: + name: + type: string + required: + - name + type: object + AnalyticsRuleUpsertSchema: + properties: params: $ref: '#/components/schemas/AnalyticsRuleParameters' type: + enum: + - popular_queries + - nohits_queries + - counter type: string required: - - name - type - params type: object @@ -82,6 +146,7 @@ components: items: $ref: '#/components/schemas/AnalyticsRuleSchema' type: array + x-go-type: '[]*AnalyticsRuleSchema' type: object ApiKey: allOf: @@ -232,6 +297,8 @@ components: minLength: 1 type: string type: array + voice_query_model: + $ref: '#/components/schemas/VoiceQueryModelCollectionConfig' required: - name - fields @@ -256,13 +323,39 @@ components: required: - fields type: object - ConversationDeleteSchema: - properties: - id: - type: integer + ConversationModelCreateSchema: + allOf: + - $ref: '#/components/schemas/ConversationModelUpdateSchema' + - properties: + history_collection: + description: Typesense collection that stores the historical conversations + type: string + max_bytes: + description: | + The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. + type: integer + model_name: + description: Name of the LLM model offered by OpenAI, Cloudflare or vLLM + type: string + required: + - model_name + - max_bytes + - history_collection + type: object required: - - id - ConversationModelCreateAndUpdateSchema: + - model_name + - max_bytes + ConversationModelSchema: + allOf: + - $ref: '#/components/schemas/ConversationModelCreateSchema' + - properties: + id: + description: An explicit id for the model, otherwise the API will return a response with an auto-generated conversation model id. + type: string + required: + - id + type: object + ConversationModelUpdateSchema: properties: account_id: description: LLM service's account ID (only applicable for Cloudflare) @@ -270,6 +363,12 @@ components: api_key: description: The LLM service's API Key type: string + history_collection: + description: Typesense collection that stores the historical conversations + type: string + id: + description: An explicit id for the model, otherwise the API will return a response with an auto-generated conversation model id. + type: string max_bytes: description: | The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. @@ -280,49 +379,31 @@ components: system_prompt: description: The system prompt that contains special instructions to the LLM type: string + ttl: + description: | + Time interval in seconds after which the messages would be deleted. Default: 86400 (24 hours) + type: integer vllm_url: description: URL of vLLM service type: string - required: - - model_name - - api_key - - max_bytes type: object - ConversationModelSchema: - allOf: - - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - - properties: - id: - type: string - required: - - id - type: object - ConversationSchema: + DocumentIndexParameters: properties: - conversation: - items: - type: object - type: array - id: + action: + enum: + - create + - update + - upsert + - emplace + type: string + dirty_values: + enum: + - coerce_or_reject + - coerce_or_drop + - drop + - reject type: string - last_updated: - type: integer - ttl: - description: Time to live. Conversations are stored by default for 24 hours, and then purged. - type: integer - required: - - id - - conversation - - last_updated - - ttl type: object - ConversationUpdateSchema: - properties: - ttl: - description: Time to live. Conversations are stored by default for 24 hours, and then purged. - type: integer - required: - - ttl ErrorResponse: properties: message: @@ -424,6 +505,10 @@ components: sort: example: true type: boolean + store: + description: | + Whether to store the image on disk. + type: boolean type: example: string type: string @@ -457,6 +542,18 @@ components: description: | The duration (in seconds) that determines how long the search query is cached. This value can be set on a per-query basis. Default: 60. type: integer + conversation: + description: | + Enable conversational search. + type: boolean + conversation_id: + description: | + The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM. + type: string + conversation_model_id: + description: | + The Id of Conversation Model to be used. + type: string drop_tokens_threshold: description: | If the number of results found for a specific query is less than this number, Typesense will attempt to drop the tokens in the query until enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 @@ -503,6 +600,10 @@ components: description: | Maximum number of hits to be returned for every group. If the `group_limit` is set as `K` then only the top K hits in each group are returned in the response. Default: 3 type: integer + group_missing_values: + description: | + Setting this parameter to true will place all documents that have a null value in the group_by field, into a single group. Setting this parameter to false, will cause each document with a null value in the group_by field to not be grouped with other documents. Default: true + type: boolean hidden_hits: description: | A list of records to unconditionally hide from search results. A list of `record_id`s to hide. Eg: to hide records with IDs 123 and 456, you'd specify `123,456`. @@ -650,9 +751,15 @@ components: description: | Vector query expression for fetching documents "closest" to a given query/document vector. type: string + voice_query: + description: | + The base64 encoded audio file in 16 khz 16-bit WAV format. + type: string type: object MultiSearchResult: properties: + conversation: + $ref: '#/components/schemas/SearchResultConversation' results: items: $ref: '#/components/schemas/SearchResult' @@ -800,6 +907,10 @@ components: type: object SearchOverrideRule: properties: + filter_by: + description: | + Indicates that the override should apply when the filter_by parameter in a search query exactly matches the string specified here (including backticks, spaces, brackets, etc). + type: string match: description: | Indicates whether the match on the query term should be `exact` or `contains`. If we want to match all queries that contained the word `apple`, we will use the `contains` match instead. @@ -811,16 +922,21 @@ components: description: Indicates what search queries should be overridden type: string tags: - description: List of tags. + description: List of tag values to associate with this override rule. items: type: string type: array - required: - - query - - match type: object SearchOverrideSchema: properties: + effective_from_ts: + description: | + A Unix timestamp that indicates the date/time from which the override will be active. You can use this to create override rules that start applying from a future point in time. + type: integer + effective_to_ts: + description: | + A Unix timestamp that indicates the date/time until which the override will be active. You can use this to create override rules that stop applying after a period of time. + type: integer excludes: description: List of document `id`s that should be excluded from the search results. items: @@ -830,17 +946,37 @@ components: description: | A filter by clause that is applied to any search query that matches the override rule. type: string + filter_curated_hits: + description: | + When set to true, the filter conditions of the query is applied to the curated records as well. Default: false. + type: boolean includes: description: List of document `id`s that should be included in the search results with their corresponding `position`s. items: $ref: '#/components/schemas/SearchOverrideInclude' type: array + metadata: + description: | + Return a custom JSON object in the Search API response, when this rule is triggered. This can can be used to display a pre-defined message (eg: a promotion banner) on the front-end when a particular rule is triggered. + type: object remove_matched_tokens: description: | Indicates whether search query tokens that exist in the override's rule should be removed from the search query. type: boolean + replace_query: + description: | + Replaces the current search query with this value, when the search query matches the override rule. + type: string rule: $ref: '#/components/schemas/SearchOverrideRule' + sort_by: + description: | + A sort by clause that is applied to any search query that matches the override rule. + type: string + stop_processing: + description: | + When set to true, override processing will stop at the first matching rule. When set to false override processing will continue and multiple override actions will be triggered in sequence. Overrides are processed in the lexical sort order of their id field. Default: true. + type: boolean required: - rule type: object @@ -860,6 +996,18 @@ components: description: | The duration (in seconds) that determines how long the search query is cached. This value can be set on a per-query basis. Default: 60. type: integer + conversation: + description: | + Enable conversational search. + type: boolean + conversation_id: + description: | + The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM. + type: string + conversation_model_id: + description: | + The Id of Conversation Model to be used. + type: string drop_tokens_threshold: description: | If the number of results found for a specific query is less than this number, Typesense will attempt to drop the tokens in the query until enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 @@ -911,6 +1059,10 @@ components: description: | Maximum number of hits to be returned for every group. If the `group_limit` is set as `K` then only the top K hits in each group are returned in the response. Default: 3 type: integer + group_missing_values: + description: | + Setting this parameter to true will place all documents that have a null value in the group_by field, into a single group. Setting this parameter to false, will cause each document with a null value in the group_by field to not be grouped with other documents. Default: true + type: boolean hidden_hits: description: | A list of records to unconditionally hide from search results. A list of `record_id`s to hide. Eg: to hide records with IDs 123 and 456, you'd specify `123,456`. @@ -1066,12 +1218,18 @@ components: description: | Vector query expression for fetching documents "closest" to a given query/document vector. type: string + voice_query: + description: | + The base64 encoded audio file in 16 khz 16-bit WAV format. + type: string required: - q - query_by type: object SearchResult: properties: + conversation: + $ref: '#/components/schemas/SearchResultConversation' facet_counts: items: $ref: '#/components/schemas/FacetCounts' @@ -1102,6 +1260,11 @@ components: type: integer q: type: string + voice_query: + properties: + transcribed_query: + type: string + type: object required: - collection_name - q @@ -1114,6 +1277,24 @@ components: description: The number of milliseconds the search took type: integer type: object + SearchResultConversation: + properties: + answer: + type: string + conversation_history: + items: + type: object + type: array + conversation_id: + type: string + query: + type: string + required: + - answer + - conversation_history + - conversation_id + - query + type: object SearchResultHit: example: document: @@ -1164,9 +1345,17 @@ components: type: object SearchSynonymSchema: properties: + locale: + description: Locale for the synonym, leave blank to use the standard tokenizer. + type: string root: description: For 1-way synonyms, indicates the root word that words in the `synonyms` parameter map to. type: string + symbols_to_index: + description: By default, special characters are dropped from synonyms. Use this attribute to specify which special characters should be indexed as is. + items: + type: string + type: array synonyms: description: Array of words that should be considered as synonyms. items: @@ -1246,6 +1435,14 @@ components: required: - success type: object + VoiceQueryModelCollectionConfig: + description: | + Configuration for the voice query model + properties: + model_name: + example: ts/whisper/base.en + type: string + type: object securitySchemes: api_key_header: in: header @@ -1257,7 +1454,7 @@ externalDocs: info: description: An open source search engine for building delightful search experiences. title: Typesense API - version: "26.0" + version: "27.0" openapi: 3.0.3 paths: /aliases: @@ -1364,6 +1561,33 @@ paths: summary: Create or update a collection alias tags: - collections + /analytics/events: + post: + description: Sending events for analytics e.g rank search results based on popularity. + operationId: createAnalyticsEvent + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AnalyticsEventCreateSchema' + description: The Analytics event to be created + required: true + responses: + 201: + content: + application/json: + schema: + $ref: '#/components/schemas/AnalyticsEventCreateResponse' + description: Analytics event successfully created + 400: + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + description: Bad request, see error message for details + summary: Create an analytics event + tags: + - analytics /analytics/rules: get: description: Retrieve the details of all analytics rules @@ -1420,7 +1644,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AnalyticsRuleSchema' + $ref: '#/components/schemas/AnalyticsRuleDeleteResponse' description: Analytics rule deleted 404: content: @@ -1471,11 +1695,11 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AnalyticsRuleSchema' + $ref: '#/components/schemas/AnalyticsRuleUpsertSchema' description: The Analytics rule to be upserted required: true responses: - 201: + 200: content: application/json: schema: @@ -1650,6 +1874,10 @@ paths: name: filter_by schema: type: string + - in: query + name: ignore_not_found + schema: + type: boolean responses: 200: content: @@ -1741,6 +1969,16 @@ paths: - upsert example: upsert type: string + - description: Dealing with Dirty Data + in: query + name: dirty_values + schema: + enum: + - coerce_or_reject + - coerce_or_drop + - drop + - reject + type: string requestBody: content: application/json: @@ -1933,6 +2171,11 @@ paths: - in: query name: action schema: + enum: + - create + - update + - upsert + - emplace type: string - in: query name: batch_size @@ -1951,6 +2194,14 @@ paths: name: remote_embedding_batch_size schema: type: integer + - in: query + name: return_doc + schema: + type: boolean + - in: query + name: return_id + schema: + type: boolean requestBody: content: application/octet-stream: @@ -1999,6 +2250,18 @@ paths: name: cache_ttl schema: type: integer + - in: query + name: conversation + schema: + type: boolean + - in: query + name: conversation_id + schema: + type: string + - in: query + name: conversation_model_id + schema: + type: string - in: query name: drop_tokens_threshold schema: @@ -2051,6 +2314,10 @@ paths: name: group_limit schema: type: integer + - in: query + name: group_missing_values + schema: + type: boolean - in: query name: hidden_hits schema: @@ -2215,6 +2482,10 @@ paths: name: vector_query schema: type: string + - in: query + name: voice_query + schema: + type: string responses: 200: content: @@ -2487,90 +2758,6 @@ paths: summary: Create or update a synonym tags: - documents - /conversations: - get: - description: Retrieve all past conversations - operationId: retrieveAllConversations - responses: - 200: - content: - application/json: - schema: - items: - $ref: '#/components/schemas/ConversationSchema' - type: array - x-go-type: '[]*ConversationSchema' - description: A list of all past conversations - summary: List all past conversations - tags: - - conversations - /conversations/{conversationId}: - delete: - description: Delete a past conversation - operationId: deleteConversation - parameters: - - description: The id of the conversation to delete - in: path - name: conversationId - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationSchema' - description: The conversation was successfully deleted - summary: Delete a past conversation - tags: - - conversations - get: - description: Retrieve a conversation - operationId: retrieveConversation - parameters: - - description: The id of the conversation to retrieve - in: path - name: conversationId - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationSchema' - description: A past conversation - summary: Retrieve a past conversation - tags: - - conversations - put: - description: Update the TTL for a conversation - operationId: updateConversation - parameters: - - description: The id of the conversation to update - in: path - name: conversationId - required: true - schema: - type: string - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationUpdateSchema' - required: true - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationSchema' - description: The conversation was successfully updated - summary: Update the TTL for a past conversation - tags: - - conversations /conversations/models: get: description: Retrieve all conversation models @@ -2595,10 +2782,10 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' + $ref: '#/components/schemas/ConversationModelCreateSchema' required: true responses: - 201: + 200: content: application/json: schema: @@ -2667,14 +2854,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' + $ref: '#/components/schemas/ConversationModelUpdateSchema' required: true responses: 200: content: application/json: schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' + $ref: '#/components/schemas/ConversationModelSchema' description: The conversation model was successfully updated summary: Update a conversation model tags: @@ -2837,6 +3024,18 @@ paths: name: cache_ttl schema: type: integer + - in: query + name: conversation + schema: + type: boolean + - in: query + name: conversation_id + schema: + type: string + - in: query + name: conversation_model_id + schema: + type: string - in: query name: drop_tokens_threshold schema: @@ -2889,6 +3088,10 @@ paths: name: group_limit schema: type: integer + - in: query + name: group_missing_values + schema: + type: boolean - in: query name: hidden_hits schema: @@ -3053,6 +3256,10 @@ paths: name: vector_query schema: type: string + - in: query + name: voice_query + schema: + type: string requestBody: content: application/json: @@ -3357,7 +3564,7 @@ tags: - description: Typesense can aggregate search queries for both analytics purposes and for query suggestions. externalDocs: description: Find out more - url: https://typesense.org/docs/0.25.0/api/analytics-query-suggestions.html + url: https://typesense.org/docs/26.0/api/analytics-query-suggestions.html name: analytics - description: Manage API Keys with fine-grain access control externalDocs: @@ -3384,5 +3591,5 @@ tags: - description: Conversational Search (RAG) externalDocs: description: Find out more - url: https://typesense.org/docs/26.0/api/conversational-search-rag.html + url: https://typesense.org/docs/27.0/api/conversational-search-rag.html name: conversations diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index ed2011b..aa92458 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -2,7 +2,7 @@ openapi: 3.0.3 info: title: Typesense API description: "An open source search engine for building delightful search experiences." - version: '26.0' + version: '27.0' externalDocs: description: Find out more about Typsesense url: https://typesense.org @@ -28,7 +28,7 @@ tags: description: Typesense can aggregate search queries for both analytics purposes and for query suggestions. externalDocs: description: Find out more - url: https://typesense.org/docs/0.25.0/api/analytics-query-suggestions.html + url: https://typesense.org/docs/26.0/api/analytics-query-suggestions.html - name: keys description: Manage API Keys with fine-grain access control externalDocs: @@ -55,7 +55,7 @@ tags: description: Conversational Search (RAG) externalDocs: description: Find out more - url: https://typesense.org/docs/26.0/api/conversational-search-rag.html + url: https://typesense.org/docs/27.0/api/conversational-search-rag.html paths: /collections: get: @@ -230,6 +230,16 @@ paths: example: upsert enum: - upsert + - name: dirty_values + in: query + description: Dealing with Dirty Data + schema: + type: string + enum: + - coerce_or_reject + - coerce_or_drop + - drop + - reject requestBody: description: The document object to be indexed content: @@ -334,6 +344,8 @@ paths: in: query schema: type: object + required: + - filter_by properties: filter_by: type: string @@ -344,6 +356,8 @@ paths: at a time. A larger value will speed up deletions, but will impact performance of other operations running on the server. type: integer + ignore_not_found: + type: boolean responses: 200: description: Documents successfully deleted @@ -671,9 +685,6 @@ paths: in: query schema: type: object - required: - - include_fields - - exclude_fields properties: filter_by: description: @@ -728,8 +739,19 @@ paths: properties: action: type: string + enum: + - create + - update + - upsert + - emplace batch_size: type: integer + return_id: + type: boolean + description: + Returning the id of the imported documents. If you want the + import response to return the ingested document's id in the + response, you can use the return_id parameter. dirty_values: type: string enum: @@ -739,6 +761,8 @@ paths: - reject remote_embedding_batch_size: type: integer + return_doc: + type: boolean requestBody: description: The json array of documents or the JSONL file to import content: @@ -885,6 +909,114 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiResponse" + /conversations/models: + get: + description: Retrieve all conversation models + operationId: retrieveAllConversationModels + responses: + 200: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/ConversationModelSchema' + type: array + x-go-type: '[]*ConversationModelSchema' + description: List of all conversation models + summary: List all conversation models + tags: + - conversations + post: + description: Create a Conversation Model + operationId: createConversationModel + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelCreateSchema' + required: true + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + description: Created Conversation Model + 400: + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + description: Bad request, see error message for details + tags: + - conversations + /conversations/models/{modelId}: + get: + description: Retrieve a conversation model + operationId: retrieveConversationModel + parameters: + - name: modelId + in: path + description: The id of the conversation model to retrieve + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + description: A conversation model + summary: Retrieve a conversation model + tags: + - conversations + put: + description: Update a conversation model + operationId: updateConversationModel + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelUpdateSchema' + required: true + parameters: + - name: modelId + in: path + description: The id of the conversation model to update + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + description: The conversation model was successfully updated + summary: Update a conversation model + tags: + - conversations + delete: + description: Delete a conversation model + operationId: deleteConversationModel + parameters: + - name: modelId + in: path + description: The id of the conversation model to delete + required: true + schema: + type: string + responses: + 200: + content: + application/json: + schema: + $ref: '#/components/schemas/ConversationModelSchema' + description: The conversation model was successfully deleted + summary: Delete a conversation model + tags: + - conversations /keys: get: tags: @@ -1210,6 +1342,33 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiResponse" + /analytics/events: + post: + tags: + - analytics + summary: Create an analytics event + description: Sending events for analytics e.g rank search results based on popularity. + operationId: createAnalyticsEvent + requestBody: + description: The Analytics event to be created + content: + application/json: + schema: + $ref: '#/components/schemas/AnalyticsEventCreateSchema' + required: true + responses: + 201: + description: Analytics event successfully created + content: + application/json: + schema: + $ref: '#/components/schemas/AnalyticsEventCreateResponse' + 400: + description: Bad request, see error message for details + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' /analytics/rules: post: tags: @@ -1272,10 +1431,10 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/AnalyticsRuleSchema" + $ref: "#/components/schemas/AnalyticsRuleUpsertSchema" required: true responses: - 201: + 200: description: Analytics rule successfully upserted content: application/json: @@ -1334,7 +1493,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/AnalyticsRuleSchema" + $ref: "#/components/schemas/AnalyticsRuleDeleteResponse" 404: description: Analytics rule not found content: @@ -1588,198 +1747,6 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiResponse' - /conversations: - get: - description: Retrieve all past conversations - operationId: retrieveAllConversations - responses: - 200: - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ConversationSchema' - x-go-type: "[]*ConversationSchema" - description: A list of all past conversations - summary: List all past conversations - tags: - - conversations - /conversations/{conversationId}: - get: - description: Retrieve a conversation - operationId: retrieveConversation - parameters: - - name: conversationId - in: path - description: The id of the conversation to retrieve - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationSchema' - description: A past conversation - summary: Retrieve a past conversation - tags: - - conversations - put: - description: Update the TTL for a conversation - operationId: updateConversation - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationUpdateSchema' - required: true - parameters: - - name: conversationId - in: path - description: The id of the conversation to update - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationSchema' - description: The conversation was successfully updated - summary: Update the TTL for a past conversation - tags: - - conversations - delete: - description: Delete a past conversation - operationId: deleteConversation - parameters: - - name: conversationId - in: path - description: The id of the conversation to delete - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationSchema' - description: The conversation was successfully deleted - summary: Delete a past conversation - tags: - - conversations - /conversations/models: - get: - description: Retrieve all conversation models - operationId: retrieveAllConversationModels - responses: - 200: - content: - application/json: - schema: - items: - $ref: '#/components/schemas/ConversationModelSchema' - type: array - x-go-type: '[]*ConversationModelSchema' - description: List of all conversation models - summary: List all conversation models - tags: - - conversations - post: - description: Create a Conversation Model - operationId: createConversationModel - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - required: true - responses: - 201: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelSchema' - description: Created Conversation Model - 400: - content: - application/json: - schema: - $ref: '#/components/schemas/ApiResponse' - description: Bad request, see error message for details - tags: - - conversations - /conversations/models/{modelId}: - get: - description: Retrieve a conversation model - operationId: retrieveConversationModel - parameters: - - name: modelId - in: path - description: The id of the conversation model to retrieve - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelSchema' - description: A conversation model - summary: Retrieve a conversation model - tags: - - conversations - put: - description: Update a conversation model - operationId: updateConversationModel - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - required: true - parameters: - - name: modelId - in: path - description: The id of the conversation model to update - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - description: The conversation model was successfully updated - summary: Update a conversation model - tags: - - conversations - delete: - description: Delete a conversation model - operationId: deleteConversationModel - parameters: - - name: modelId - in: path - description: The id of the conversation model to delete - required: true - schema: - type: string - responses: - 200: - content: - application/json: - schema: - $ref: '#/components/schemas/ConversationModelSchema' - description: The conversation model was successfully deleted - summary: Delete a conversation model - tags: - - conversations components: schemas: CollectionSchema: @@ -1845,6 +1812,8 @@ components: minLength: 1 maxLength: 1 default: [] + voice_query_model: + $ref: "#/components/schemas/VoiceQueryModelCollectionConfig" CollectionUpdateSchema: required: - fields @@ -1925,6 +1894,10 @@ components: type: boolean example: true # omitting default value since we want it to be null + store: + type: boolean + description: > + Whether to store the image on disk. embed: type: object required: @@ -1952,6 +1925,14 @@ components: type: string project_id: type: string + VoiceQueryModelCollectionConfig: + type: object + description: > + Configuration for the voice query model + properties: + model_name: + type: string + example: "ts/whisper/base.en" CollectionAliasSchema: type: object required: @@ -2027,7 +2008,31 @@ components: type: string per_page: type: integer - + voice_query: + type: object + properties: + transcribed_query: + type: string + conversation: + $ref: "#/components/schemas/SearchResultConversation" + SearchResultConversation: + type: object + required: + - answer + - conversation_history + - conversation_id + - query + properties: + answer: + type: string + conversation_history: + type: array + items: + type: object + conversation_id: + type: string + query: + type: string SearchGroupedHit: type: object required: @@ -2154,6 +2159,37 @@ components: type: boolean description: > Indicates whether search query tokens that exist in the override's rule should be removed from the search query. + metadata: + type: object + description: > + Return a custom JSON object in the Search API response, when this rule is triggered. This can can be used to display a pre-defined message (eg: a promotion banner) on the front-end when a particular rule is triggered. + sort_by: + type: string + description: > + A sort by clause that is applied to any search query that matches the override rule. + replace_query: + type: string + description: > + Replaces the current search query with this value, when the search query matches the override rule. + filter_curated_hits: + type: boolean + description: > + When set to true, the filter conditions of the query is applied to the curated records as well. + Default: false. + effective_from_ts: + type: integer + description: > + A Unix timestamp that indicates the date/time from which the override will be active. You can use this to create override rules that start applying from a future point in time. + effective_to_ts: + type: integer + description: > + A Unix timestamp that indicates the date/time until which the override will be active. You can use this to create override rules that stop applying after a period of time. + stop_processing: + type: boolean + description: > + When set to true, override processing will stop at the first matching rule. When set to false override processing will continue and multiple override actions will be triggered in sequence. + Overrides are processed in the lexical sort order of their id field. + Default: true. SearchOverride: allOf: - $ref: "#/components/schemas/SearchOverrideSchema" @@ -2166,10 +2202,12 @@ components: readOnly: true SearchOverrideRule: type: object - required: - - query - - match properties: + tags: + type: array + description: List of tag values to associate with this override rule. + items: + type: string query: type: string description: Indicates what search queries should be overridden @@ -2182,11 +2220,10 @@ components: enum: - exact - contains - tags: - type: array - description: List of tags. - items: - type: string + filter_by: + type: string + description: > + Indicates that the override should apply when the filter_by parameter in a search query exactly matches the string specified here (including backticks, spaces, brackets, etc). SearchOverrideInclude: type: object required: @@ -2230,6 +2267,14 @@ components: description: Array of words that should be considered as synonyms. items: type: string + locale: + type: string + description: Locale for the synonym, leave blank to use the standard tokenizer. + symbols_to_index: + type: array + description: By default, special characters are dropped from synonyms. Use this attribute to specify which special characters should be indexed as is. + items: + type: string SearchSynonym: allOf: - $ref: "#/components/schemas/SearchSynonymSchema" @@ -2342,6 +2387,8 @@ components: type: array items: $ref: "#/components/schemas/SearchResult" + conversation: + $ref: "#/components/schemas/SearchResultConversation" SearchParameters: type: object required: @@ -2480,6 +2527,13 @@ components: Default: 3 type: integer + group_missing_values: + description: > + Setting this parameter to true will place all documents that have a null value in the group_by field, into a single group. + Setting this parameter to false, will cause each document with a null value in the group_by field to not be grouped with other documents. + Default: true + type: boolean + include_fields: description: List of fields from the document to include in the search result type: string @@ -2682,6 +2736,22 @@ components: description: > Comma separated string of nested facet fields whose parent object should be returned in facet response. type: string + voice_query: + description: > + The base64 encoded audio file in 16 khz 16-bit WAV format. + type: string + conversation: + description: > + Enable conversational search. + type: boolean + conversation_model_id: + description: > + The Id of Conversation Model to be used. + type: string + conversation_id: + description: > + The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM. + type: string MultiSearchParameters: description: > @@ -2818,6 +2888,13 @@ components: Default: 3 type: integer + group_missing_values: + description: > + Setting this parameter to true will place all documents that have a null value in the group_by field, into a single group. + Setting this parameter to false, will cause each document with a null value in the group_by field to not be grouped with other documents. + Default: true + type: boolean + include_fields: description: List of fields from the document to include in the search result type: string @@ -3006,6 +3083,22 @@ components: description: > Comma separated string of nested facet fields whose parent object should be returned in facet response. type: string + voice_query: + description: > + The base64 encoded audio file in 16 khz 16-bit WAV format. + type: string + conversation: + description: > + Enable conversational search. + type: boolean + conversation_model_id: + description: > + The Id of Conversation Model to be used. + type: string + conversation_id: + description: > + The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM. + type: string MultiSearchSearchesParameter: type: object required: @@ -3061,17 +3154,38 @@ components: avg: type: number format: double - AnalyticsRuleSchema: + AnalyticsEventCreateResponse: + type: object + required: + - ok + properties: + ok: + type: boolean + AnalyticsEventCreateSchema: type: object required: - - name - type - - params + - name + - data properties: + type: + type: string name: type: string + data: + type: object + AnalyticsRuleUpsertSchema: + type: object + required: + - type + - params + properties: type: type: string + enum: + - popular_queries + - nohits_queries + - counter params: $ref: "#/components/schemas/AnalyticsRuleParameters" AnalyticsRuleParameters: @@ -3079,22 +3193,65 @@ components: required: - source - destination - - limit properties: source: - type: object - properties: - collections: - type: array - items: - type: string + $ref: '#/components/schemas/AnalyticsRuleParametersSource' destination: - type: object - properties: - collection: - type: string + $ref: '#/components/schemas/AnalyticsRuleParametersDestination' limit: type: integer + expand_query: + type: boolean + AnalyticsRuleParametersSource: + type: object + required: + - collections + properties: + collections: + type: array + items: + type: string + events: + type: array + items: + type: object + required: + - type + - weight + - name + properties: + type: + type: string + weight: + type: number + format: float + name: + type: string + AnalyticsRuleParametersDestination: + type: object + required: + - collection + properties: + collection: + type: string + counter_field: + type: string + AnalyticsRuleDeleteResponse: + type: object + required: + - name + properties: + name: + type: string + AnalyticsRuleSchema: + allOf: + - $ref: '#/components/schemas/AnalyticsRuleUpsertSchema' + - type: object + required: + - name + properties: + name: + type: string AnalyticsRulesRetrieveSchema: type: object properties: @@ -3102,6 +3259,7 @@ components: type: array items: $ref: "#/components/schemas/AnalyticsRuleSchema" + x-go-type: '[]*AnalyticsRuleSchema' APIStatsResponse: type: object properties: @@ -3227,52 +3385,70 @@ components: properties: name: type: string - ConversationSchema: - properties: - id: - type: string - conversation: - items: - type: object - type: array - last_updated: - type: integer - ttl: - description: Time to live. Conversations are stored by default for 24 hours, and then purged. - type: integer + DocumentIndexParameters: type: object - required: - - id - - conversation - - last_updated - - ttl - ConversationUpdateSchema: properties: - ttl: - description: Time to live. Conversations are stored by default for 24 hours, and then purged. - type: integer + action: + type: string + enum: + - create + - update + - upsert + - emplace + dirty_values: + type: string + enum: + - coerce_or_reject + - coerce_or_drop + - drop + - reject + ConversationModelCreateSchema: required: - - ttl - ConversationDeleteSchema: + - model_name + - max_bytes + allOf: + - $ref: '#/components/schemas/ConversationModelUpdateSchema' + - type: object + required: + - model_name + - max_bytes + - history_collection + properties: + model_name: + description: Name of the LLM model offered by OpenAI, Cloudflare or vLLM + type: string + max_bytes: + description: | + The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. + type: integer + history_collection: + type: string + description: Typesense collection that stores the historical conversations + ConversationModelUpdateSchema: + type: object properties: id: - type: integer - required: - - id - ConversationModelCreateAndUpdateSchema: - properties: + type: string + description: An explicit id for the model, otherwise the API will return a response with an auto-generated conversation model id. model_name: description: Name of the LLM model offered by OpenAI, Cloudflare or vLLM type: string api_key: description: The LLM service's API Key type: string + history_collection: + type: string + description: Typesense collection that stores the historical conversations account_id: description: LLM service's account ID (only applicable for Cloudflare) type: string system_prompt: description: The system prompt that contains special instructions to the LLM type: string + ttl: + type: integer + description: | + Time interval in seconds after which the messages would be deleted. Default: 86400 (24 hours) max_bytes: description: | The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. @@ -3280,20 +3456,16 @@ components: vllm_url: description: URL of vLLM service type: string - required: - - model_name - - api_key - - max_bytes - type: object ConversationModelSchema: allOf: - - $ref: '#/components/schemas/ConversationModelCreateAndUpdateSchema' - - properties: - id: - type: string - type: object + - $ref: '#/components/schemas/ConversationModelCreateSchema' + - type: object required: - id + properties: + id: + type: string + description: An explicit id for the model, otherwise the API will return a response with an auto-generated conversation model id. securitySchemes: api_key_header: type: apiKey diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index d7f7931..5d5c603 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -13,6 +13,20 @@ const ( Api_key_headerScopes = "api_key_header.Scopes" ) +// Defines values for AnalyticsRuleSchemaType. +const ( + AnalyticsRuleSchemaTypeCounter AnalyticsRuleSchemaType = "counter" + AnalyticsRuleSchemaTypeNohitsQueries AnalyticsRuleSchemaType = "nohits_queries" + AnalyticsRuleSchemaTypePopularQueries AnalyticsRuleSchemaType = "popular_queries" +) + +// Defines values for AnalyticsRuleUpsertSchemaType. +const ( + AnalyticsRuleUpsertSchemaTypeCounter AnalyticsRuleUpsertSchemaType = "counter" + AnalyticsRuleUpsertSchemaTypeNohitsQueries AnalyticsRuleUpsertSchemaType = "nohits_queries" + AnalyticsRuleUpsertSchemaTypePopularQueries AnalyticsRuleUpsertSchemaType = "popular_queries" +) + // Defines values for SearchOverrideRuleMatch. const ( Contains SearchOverrideRuleMatch = "contains" @@ -21,15 +35,31 @@ const ( // Defines values for IndexDocumentParamsAction. const ( - Upsert IndexDocumentParamsAction = "upsert" + IndexDocumentParamsActionUpsert IndexDocumentParamsAction = "upsert" +) + +// Defines values for IndexDocumentParamsDirtyValues. +const ( + IndexDocumentParamsDirtyValuesCoerceOrDrop IndexDocumentParamsDirtyValues = "coerce_or_drop" + IndexDocumentParamsDirtyValuesCoerceOrReject IndexDocumentParamsDirtyValues = "coerce_or_reject" + IndexDocumentParamsDirtyValuesDrop IndexDocumentParamsDirtyValues = "drop" + IndexDocumentParamsDirtyValuesReject IndexDocumentParamsDirtyValues = "reject" +) + +// Defines values for ImportDocumentsParamsAction. +const ( + ImportDocumentsParamsActionCreate ImportDocumentsParamsAction = "create" + ImportDocumentsParamsActionEmplace ImportDocumentsParamsAction = "emplace" + ImportDocumentsParamsActionUpdate ImportDocumentsParamsAction = "update" + ImportDocumentsParamsActionUpsert ImportDocumentsParamsAction = "upsert" ) // Defines values for ImportDocumentsParamsDirtyValues. const ( - CoerceOrDrop ImportDocumentsParamsDirtyValues = "coerce_or_drop" - CoerceOrReject ImportDocumentsParamsDirtyValues = "coerce_or_reject" - Drop ImportDocumentsParamsDirtyValues = "drop" - Reject ImportDocumentsParamsDirtyValues = "reject" + ImportDocumentsParamsDirtyValuesCoerceOrDrop ImportDocumentsParamsDirtyValues = "coerce_or_drop" + ImportDocumentsParamsDirtyValuesCoerceOrReject ImportDocumentsParamsDirtyValues = "coerce_or_reject" + ImportDocumentsParamsDirtyValuesDrop ImportDocumentsParamsDirtyValues = "drop" + ImportDocumentsParamsDirtyValuesReject ImportDocumentsParamsDirtyValues = "reject" ) // APIStatsResponse defines model for APIStatsResponse. @@ -49,27 +79,69 @@ type APIStatsResponse struct { WriteRequestsPerSecond *float64 `json:"write_requests_per_second,omitempty"` } +// AnalyticsEventCreateResponse defines model for AnalyticsEventCreateResponse. +type AnalyticsEventCreateResponse struct { + Ok bool `json:"ok"` +} + +// AnalyticsEventCreateSchema defines model for AnalyticsEventCreateSchema. +type AnalyticsEventCreateSchema struct { + Data map[string]interface{} `json:"data"` + Name string `json:"name"` + Type string `json:"type"` +} + +// AnalyticsRuleDeleteResponse defines model for AnalyticsRuleDeleteResponse. +type AnalyticsRuleDeleteResponse struct { + Name string `json:"name"` +} + // AnalyticsRuleParameters defines model for AnalyticsRuleParameters. type AnalyticsRuleParameters struct { - Destination struct { - Collection *string `json:"collection,omitempty"` - } `json:"destination"` - Limit int `json:"limit"` - Source struct { - Collections *[]string `json:"collections,omitempty"` - } `json:"source"` + Destination AnalyticsRuleParametersDestination `json:"destination"` + ExpandQuery *bool `json:"expand_query,omitempty"` + Limit *int `json:"limit,omitempty"` + Source AnalyticsRuleParametersSource `json:"source"` +} + +// AnalyticsRuleParametersDestination defines model for AnalyticsRuleParametersDestination. +type AnalyticsRuleParametersDestination struct { + Collection string `json:"collection"` + CounterField *string `json:"counter_field,omitempty"` +} + +// AnalyticsRuleParametersSource defines model for AnalyticsRuleParametersSource. +type AnalyticsRuleParametersSource struct { + Collections []string `json:"collections"` + Events *[]struct { + Name string `json:"name"` + Type string `json:"type"` + Weight float32 `json:"weight"` + } `json:"events,omitempty"` } // AnalyticsRuleSchema defines model for AnalyticsRuleSchema. type AnalyticsRuleSchema struct { Name string `json:"name"` Params AnalyticsRuleParameters `json:"params"` - Type string `json:"type"` + Type AnalyticsRuleSchemaType `json:"type"` } +// AnalyticsRuleSchemaType defines model for AnalyticsRuleSchema.Type. +type AnalyticsRuleSchemaType string + +// AnalyticsRuleUpsertSchema defines model for AnalyticsRuleUpsertSchema. +type AnalyticsRuleUpsertSchema struct { + Params AnalyticsRuleParameters `json:"params"` + Type AnalyticsRuleUpsertSchemaType `json:"type"` +} + +// AnalyticsRuleUpsertSchemaType defines model for AnalyticsRuleUpsertSchema.Type. +type AnalyticsRuleUpsertSchemaType string + // AnalyticsRulesRetrieveSchema defines model for AnalyticsRulesRetrieveSchema. type AnalyticsRulesRetrieveSchema struct { - Rules *[]AnalyticsRuleSchema `json:"rules,omitempty"` + Rules *[]*AnalyticsRuleSchema `json:"rules,omitempty"` } // ApiKey defines model for ApiKey. @@ -147,6 +219,9 @@ type CollectionResponse struct { // TokenSeparators List of symbols or special characters to be used for splitting the text into individual words in addition to space and new-line characters. TokenSeparators *[]string `json:"token_separators,omitempty"` + + // VoiceQueryModel Configuration for the voice query model + VoiceQueryModel *VoiceQueryModelCollectionConfig `json:"voice_query_model,omitempty"` } // CollectionSchema defines model for CollectionSchema. @@ -168,6 +243,9 @@ type CollectionSchema struct { // TokenSeparators List of symbols or special characters to be used for splitting the text into individual words in addition to space and new-line characters. TokenSeparators *[]string `json:"token_separators,omitempty"` + + // VoiceQueryModel Configuration for the voice query model + VoiceQueryModel *VoiceQueryModelCollectionConfig `json:"voice_query_model,omitempty"` } // CollectionUpdateSchema defines model for CollectionUpdateSchema. @@ -176,13 +254,19 @@ type CollectionUpdateSchema struct { Fields []Field `json:"fields"` } -// ConversationModelCreateAndUpdateSchema defines model for ConversationModelCreateAndUpdateSchema. -type ConversationModelCreateAndUpdateSchema struct { +// ConversationModelCreateSchema defines model for ConversationModelCreateSchema. +type ConversationModelCreateSchema struct { // AccountId LLM service's account ID (only applicable for Cloudflare) AccountId *string `json:"account_id,omitempty"` // ApiKey The LLM service's API Key - ApiKey string `json:"api_key"` + ApiKey *string `json:"api_key,omitempty"` + + // HistoryCollection Typesense collection that stores the historical conversations + HistoryCollection string `json:"history_collection"` + + // Id An explicit id for the model, otherwise the API will return a response with an auto-generated conversation model id. + Id *string `json:"id,omitempty"` // MaxBytes The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. MaxBytes int `json:"max_bytes"` @@ -193,6 +277,9 @@ type ConversationModelCreateAndUpdateSchema struct { // SystemPrompt The system prompt that contains special instructions to the LLM SystemPrompt *string `json:"system_prompt,omitempty"` + // Ttl Time interval in seconds after which the messages would be deleted. Default: 86400 (24 hours) + Ttl *int `json:"ttl,omitempty"` + // VllmUrl URL of vLLM service VllmUrl *string `json:"vllm_url,omitempty"` } @@ -203,8 +290,13 @@ type ConversationModelSchema struct { AccountId *string `json:"account_id,omitempty"` // ApiKey The LLM service's API Key - ApiKey string `json:"api_key"` - Id string `json:"id"` + ApiKey *string `json:"api_key,omitempty"` + + // HistoryCollection Typesense collection that stores the historical conversations + HistoryCollection string `json:"history_collection"` + + // Id An explicit id for the model, otherwise the API will return a response with an auto-generated conversation model id. + Id string `json:"id"` // MaxBytes The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. MaxBytes int `json:"max_bytes"` @@ -215,24 +307,41 @@ type ConversationModelSchema struct { // SystemPrompt The system prompt that contains special instructions to the LLM SystemPrompt *string `json:"system_prompt,omitempty"` + // Ttl Time interval in seconds after which the messages would be deleted. Default: 86400 (24 hours) + Ttl *int `json:"ttl,omitempty"` + // VllmUrl URL of vLLM service VllmUrl *string `json:"vllm_url,omitempty"` } -// ConversationSchema defines model for ConversationSchema. -type ConversationSchema struct { - Conversation []map[string]interface{} `json:"conversation"` - Id string `json:"id"` - LastUpdated int `json:"last_updated"` +// ConversationModelUpdateSchema defines model for ConversationModelUpdateSchema. +type ConversationModelUpdateSchema struct { + // AccountId LLM service's account ID (only applicable for Cloudflare) + AccountId *string `json:"account_id,omitempty"` + + // ApiKey The LLM service's API Key + ApiKey *string `json:"api_key,omitempty"` - // Ttl Time to live. Conversations are stored by default for 24 hours, and then purged. - Ttl int `json:"ttl"` -} + // HistoryCollection Typesense collection that stores the historical conversations + HistoryCollection *string `json:"history_collection,omitempty"` + + // Id An explicit id for the model, otherwise the API will return a response with an auto-generated conversation model id. + Id *string `json:"id,omitempty"` + + // MaxBytes The maximum number of bytes to send to the LLM in every API call. Consult the LLM's documentation on the number of bytes supported in the context window. + MaxBytes *int `json:"max_bytes,omitempty"` + + // ModelName Name of the LLM model offered by OpenAI, Cloudflare or vLLM + ModelName *string `json:"model_name,omitempty"` + + // SystemPrompt The system prompt that contains special instructions to the LLM + SystemPrompt *string `json:"system_prompt,omitempty"` -// ConversationUpdateSchema defines model for ConversationUpdateSchema. -type ConversationUpdateSchema struct { - // Ttl Time to live. Conversations are stored by default for 24 hours, and then purged. - Ttl int `json:"ttl"` + // Ttl Time interval in seconds after which the messages would be deleted. Default: 86400 (24 hours) + Ttl *int `json:"ttl,omitempty"` + + // VllmUrl URL of vLLM service + VllmUrl *string `json:"vllm_url,omitempty"` } // FacetCounts defines model for FacetCounts. @@ -276,7 +385,10 @@ type Field struct { Optional *bool `json:"optional,omitempty"` Reference *string `json:"reference,omitempty"` Sort *bool `json:"sort,omitempty"` - Type string `json:"type"` + + // Store Whether to store the image on disk. + Store *bool `json:"store,omitempty"` + Type string `json:"type"` } // HealthStatus defines model for HealthStatus. @@ -292,6 +404,15 @@ type MultiSearchCollectionParameters struct { // Collection The collection to search in. Collection string `json:"collection"` + // Conversation Enable conversational search. + Conversation *bool `json:"conversation,omitempty"` + + // ConversationId The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM. + ConversationId *string `json:"conversation_id,omitempty"` + + // ConversationModelId The Id of Conversation Model to be used. + ConversationModelId *string `json:"conversation_model_id,omitempty"` + // DropTokensThreshold If the number of results found for a specific query is less than this number, Typesense will attempt to drop the tokens in the query until enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 DropTokensThreshold *int `json:"drop_tokens_threshold,omitempty"` @@ -328,6 +449,9 @@ type MultiSearchCollectionParameters struct { // GroupLimit Maximum number of hits to be returned for every group. If the `group_limit` is set as `K` then only the top K hits in each group are returned in the response. Default: 3 GroupLimit *int `json:"group_limit,omitempty"` + // GroupMissingValues Setting this parameter to true will place all documents that have a null value in the group_by field, into a single group. Setting this parameter to false, will cause each document with a null value in the group_by field to not be grouped with other documents. Default: true + GroupMissingValues *bool `json:"group_missing_values,omitempty"` + // HiddenHits A list of records to unconditionally hide from search results. A list of `record_id`s to hide. Eg: to hide records with IDs 123 and 456, you'd specify `123,456`. // You could also use the Overrides feature to override search results based on rules. Overrides are applied first, followed by `pinned_hits` and finally `hidden_hits`. HiddenHits *string `json:"hidden_hits,omitempty"` @@ -447,6 +571,9 @@ type MultiSearchCollectionParameters struct { // VectorQuery Vector query expression for fetching documents "closest" to a given query/document vector. VectorQuery *string `json:"vector_query,omitempty"` + + // VoiceQuery The base64 encoded audio file in 16 khz 16-bit WAV format. + VoiceQuery *string `json:"voice_query,omitempty"` } // MultiSearchParameters Parameters for the multi search API. @@ -454,6 +581,15 @@ type MultiSearchParameters struct { // CacheTtl The duration (in seconds) that determines how long the search query is cached. This value can be set on a per-query basis. Default: 60. CacheTtl *int `json:"cache_ttl,omitempty"` + // Conversation Enable conversational search. + Conversation *bool `json:"conversation,omitempty"` + + // ConversationId The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM. + ConversationId *string `json:"conversation_id,omitempty"` + + // ConversationModelId The Id of Conversation Model to be used. + ConversationModelId *string `json:"conversation_model_id,omitempty"` + // DropTokensThreshold If the number of results found for a specific query is less than this number, Typesense will attempt to drop the tokens in the query until enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 DropTokensThreshold *int `json:"drop_tokens_threshold,omitempty"` @@ -490,6 +626,9 @@ type MultiSearchParameters struct { // GroupLimit Maximum number of hits to be returned for every group. If the `group_limit` is set as `K` then only the top K hits in each group are returned in the response. Default: 3 GroupLimit *int `json:"group_limit,omitempty"` + // GroupMissingValues Setting this parameter to true will place all documents that have a null value in the group_by field, into a single group. Setting this parameter to false, will cause each document with a null value in the group_by field to not be grouped with other documents. Default: true + GroupMissingValues *bool `json:"group_missing_values,omitempty"` + // HiddenHits A list of records to unconditionally hide from search results. A list of `record_id`s to hide. Eg: to hide records with IDs 123 and 456, you'd specify `123,456`. // You could also use the Overrides feature to override search results based on rules. Overrides are applied first, followed by `pinned_hits` and finally `hidden_hits`. HiddenHits *string `json:"hidden_hits,omitempty"` @@ -609,11 +748,15 @@ type MultiSearchParameters struct { // VectorQuery Vector query expression for fetching documents "closest" to a given query/document vector. VectorQuery *string `json:"vector_query,omitempty"` + + // VoiceQuery The base64 encoded audio file in 16 khz 16-bit WAV format. + VoiceQuery *string `json:"voice_query,omitempty"` } // MultiSearchResult defines model for MultiSearchResult. type MultiSearchResult struct { - Results []SearchResult `json:"results"` + Conversation *SearchResultConversation `json:"conversation,omitempty"` + Results []SearchResult `json:"results"` } // MultiSearchSearchesParameter defines model for MultiSearchSearchesParameter. @@ -684,19 +827,40 @@ type SearchHighlight struct { // SearchOverride defines model for SearchOverride. type SearchOverride struct { + // EffectiveFromTs A Unix timestamp that indicates the date/time from which the override will be active. You can use this to create override rules that start applying from a future point in time. + EffectiveFromTs *int `json:"effective_from_ts,omitempty"` + + // EffectiveToTs A Unix timestamp that indicates the date/time until which the override will be active. You can use this to create override rules that stop applying after a period of time. + EffectiveToTs *int `json:"effective_to_ts,omitempty"` + // Excludes List of document `id`s that should be excluded from the search results. Excludes *[]SearchOverrideExclude `json:"excludes,omitempty"` // FilterBy A filter by clause that is applied to any search query that matches the override rule. FilterBy *string `json:"filter_by,omitempty"` - Id *string `json:"id,omitempty"` + + // FilterCuratedHits When set to true, the filter conditions of the query is applied to the curated records as well. Default: false. + FilterCuratedHits *bool `json:"filter_curated_hits,omitempty"` + Id *string `json:"id,omitempty"` // Includes List of document `id`s that should be included in the search results with their corresponding `position`s. Includes *[]SearchOverrideInclude `json:"includes,omitempty"` + // Metadata Return a custom JSON object in the Search API response, when this rule is triggered. This can can be used to display a pre-defined message (eg: a promotion banner) on the front-end when a particular rule is triggered. + Metadata *map[string]interface{} `json:"metadata,omitempty"` + // RemoveMatchedTokens Indicates whether search query tokens that exist in the override's rule should be removed from the search query. - RemoveMatchedTokens *bool `json:"remove_matched_tokens,omitempty"` - Rule SearchOverrideRule `json:"rule"` + RemoveMatchedTokens *bool `json:"remove_matched_tokens,omitempty"` + + // ReplaceQuery Replaces the current search query with this value, when the search query matches the override rule. + ReplaceQuery *string `json:"replace_query,omitempty"` + Rule SearchOverrideRule `json:"rule"` + + // SortBy A sort by clause that is applied to any search query that matches the override rule. + SortBy *string `json:"sort_by,omitempty"` + + // StopProcessing When set to true, override processing will stop at the first matching rule. When set to false override processing will continue and multiple override actions will be triggered in sequence. Overrides are processed in the lexical sort order of their id field. Default: true. + StopProcessing *bool `json:"stop_processing,omitempty"` } // SearchOverrideExclude defines model for SearchOverrideExclude. @@ -716,13 +880,16 @@ type SearchOverrideInclude struct { // SearchOverrideRule defines model for SearchOverrideRule. type SearchOverrideRule struct { + // FilterBy Indicates that the override should apply when the filter_by parameter in a search query exactly matches the string specified here (including backticks, spaces, brackets, etc). + FilterBy *string `json:"filter_by,omitempty"` + // Match Indicates whether the match on the query term should be `exact` or `contains`. If we want to match all queries that contained the word `apple`, we will use the `contains` match instead. - Match SearchOverrideRuleMatch `json:"match"` + Match *SearchOverrideRuleMatch `json:"match,omitempty"` // Query Indicates what search queries should be overridden - Query string `json:"query"` + Query *string `json:"query,omitempty"` - // Tags List of tags. + // Tags List of tag values to associate with this override rule. Tags *[]string `json:"tags,omitempty"` } @@ -731,18 +898,39 @@ type SearchOverrideRuleMatch string // SearchOverrideSchema defines model for SearchOverrideSchema. type SearchOverrideSchema struct { + // EffectiveFromTs A Unix timestamp that indicates the date/time from which the override will be active. You can use this to create override rules that start applying from a future point in time. + EffectiveFromTs *int `json:"effective_from_ts,omitempty"` + + // EffectiveToTs A Unix timestamp that indicates the date/time until which the override will be active. You can use this to create override rules that stop applying after a period of time. + EffectiveToTs *int `json:"effective_to_ts,omitempty"` + // Excludes List of document `id`s that should be excluded from the search results. Excludes *[]SearchOverrideExclude `json:"excludes,omitempty"` // FilterBy A filter by clause that is applied to any search query that matches the override rule. FilterBy *string `json:"filter_by,omitempty"` + // FilterCuratedHits When set to true, the filter conditions of the query is applied to the curated records as well. Default: false. + FilterCuratedHits *bool `json:"filter_curated_hits,omitempty"` + // Includes List of document `id`s that should be included in the search results with their corresponding `position`s. Includes *[]SearchOverrideInclude `json:"includes,omitempty"` + // Metadata Return a custom JSON object in the Search API response, when this rule is triggered. This can can be used to display a pre-defined message (eg: a promotion banner) on the front-end when a particular rule is triggered. + Metadata *map[string]interface{} `json:"metadata,omitempty"` + // RemoveMatchedTokens Indicates whether search query tokens that exist in the override's rule should be removed from the search query. - RemoveMatchedTokens *bool `json:"remove_matched_tokens,omitempty"` - Rule SearchOverrideRule `json:"rule"` + RemoveMatchedTokens *bool `json:"remove_matched_tokens,omitempty"` + + // ReplaceQuery Replaces the current search query with this value, when the search query matches the override rule. + ReplaceQuery *string `json:"replace_query,omitempty"` + Rule SearchOverrideRule `json:"rule"` + + // SortBy A sort by clause that is applied to any search query that matches the override rule. + SortBy *string `json:"sort_by,omitempty"` + + // StopProcessing When set to true, override processing will stop at the first matching rule. When set to false override processing will continue and multiple override actions will be triggered in sequence. Overrides are processed in the lexical sort order of their id field. Default: true. + StopProcessing *bool `json:"stop_processing,omitempty"` } // SearchOverridesResponse defines model for SearchOverridesResponse. @@ -755,6 +943,15 @@ type SearchParameters struct { // CacheTtl The duration (in seconds) that determines how long the search query is cached. This value can be set on a per-query basis. Default: 60. CacheTtl *int `json:"cache_ttl,omitempty"` + // Conversation Enable conversational search. + Conversation *bool `json:"conversation,omitempty"` + + // ConversationId The Id of a previous conversation to continue, this tells Typesense to include prior context when communicating with the LLM. + ConversationId *string `json:"conversation_id,omitempty"` + + // ConversationModelId The Id of Conversation Model to be used. + ConversationModelId *string `json:"conversation_model_id,omitempty"` + // DropTokensThreshold If the number of results found for a specific query is less than this number, Typesense will attempt to drop the tokens in the query until enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 DropTokensThreshold *int `json:"drop_tokens_threshold,omitempty"` @@ -794,6 +991,9 @@ type SearchParameters struct { // GroupLimit Maximum number of hits to be returned for every group. If the `group_limit` is set as `K` then only the top K hits in each group are returned in the response. Default: 3 GroupLimit *int `json:"group_limit,omitempty"` + // GroupMissingValues Setting this parameter to true will place all documents that have a null value in the group_by field, into a single group. Setting this parameter to false, will cause each document with a null value in the group_by field to not be grouped with other documents. Default: true + GroupMissingValues *bool `json:"group_missing_values,omitempty"` + // HiddenHits A list of records to unconditionally hide from search results. A list of `record_id`s to hide. Eg: to hide records with IDs 123 and 456, you'd specify `123,456`. // You could also use the Overrides feature to override search results based on rules. Overrides are applied first, followed by `pinned_hits` and finally `hidden_hits`. HiddenHits *string `json:"hidden_hits,omitempty"` @@ -919,11 +1119,15 @@ type SearchParameters struct { // VectorQuery Vector query expression for fetching documents "closest" to a given query/document vector. VectorQuery *string `json:"vector_query,omitempty"` + + // VoiceQuery The base64 encoded audio file in 16 khz 16-bit WAV format. + VoiceQuery *string `json:"voice_query,omitempty"` } // SearchResult defines model for SearchResult. type SearchResult struct { - FacetCounts *[]FacetCounts `json:"facet_counts,omitempty"` + Conversation *SearchResultConversation `json:"conversation,omitempty"` + FacetCounts *[]FacetCounts `json:"facet_counts,omitempty"` // Found The number of documents found Found *int `json:"found,omitempty"` @@ -941,6 +1145,9 @@ type SearchResult struct { CollectionName string `json:"collection_name"` PerPage int `json:"per_page"` Q string `json:"q"` + VoiceQuery *struct { + TranscribedQuery *string `json:"transcribed_query,omitempty"` + } `json:"voice_query,omitempty"` } `json:"request_params,omitempty"` // SearchCutoff Whether the search was cut off @@ -950,6 +1157,14 @@ type SearchResult struct { SearchTimeMs *int `json:"search_time_ms,omitempty"` } +// SearchResultConversation defines model for SearchResultConversation. +type SearchResultConversation struct { + Answer string `json:"answer"` + ConversationHistory []map[string]interface{} `json:"conversation_history"` + ConversationId string `json:"conversation_id"` + Query string `json:"query"` +} + // SearchResultHit defines model for SearchResultHit. type SearchResultHit struct { // Document Can be any key-value pair @@ -973,18 +1188,30 @@ type SearchResultHit struct { type SearchSynonym struct { Id *string `json:"id,omitempty"` + // Locale Locale for the synonym, leave blank to use the standard tokenizer. + Locale *string `json:"locale,omitempty"` + // Root For 1-way synonyms, indicates the root word that words in the `synonyms` parameter map to. Root *string `json:"root,omitempty"` + // SymbolsToIndex By default, special characters are dropped from synonyms. Use this attribute to specify which special characters should be indexed as is. + SymbolsToIndex *[]string `json:"symbols_to_index,omitempty"` + // Synonyms Array of words that should be considered as synonyms. Synonyms []string `json:"synonyms"` } // SearchSynonymSchema defines model for SearchSynonymSchema. type SearchSynonymSchema struct { + // Locale Locale for the synonym, leave blank to use the standard tokenizer. + Locale *string `json:"locale,omitempty"` + // Root For 1-way synonyms, indicates the root word that words in the `synonyms` parameter map to. Root *string `json:"root,omitempty"` + // SymbolsToIndex By default, special characters are dropped from synonyms. Use this attribute to specify which special characters should be indexed as is. + SymbolsToIndex *[]string `json:"symbols_to_index,omitempty"` + // Synonyms Array of words that should be considered as synonyms. Synonyms []string `json:"synonyms"` } @@ -1022,10 +1249,16 @@ type SuccessStatus struct { Success bool `json:"success"` } +// VoiceQueryModelCollectionConfig Configuration for the voice query model +type VoiceQueryModelCollectionConfig struct { + ModelName *string `json:"model_name,omitempty"` +} + // DeleteDocumentsParams defines parameters for DeleteDocuments. type DeleteDocumentsParams struct { - BatchSize *int `form:"batch_size,omitempty" json:"batch_size,omitempty"` - FilterBy *string `form:"filter_by,omitempty" json:"filter_by,omitempty"` + BatchSize *int `form:"batch_size,omitempty" json:"batch_size,omitempty"` + FilterBy *string `form:"filter_by,omitempty" json:"filter_by,omitempty"` + IgnoreNotFound *bool `form:"ignore_not_found,omitempty" json:"ignore_not_found,omitempty"` } // UpdateDocumentsJSONBody defines parameters for UpdateDocuments. @@ -1043,11 +1276,17 @@ type IndexDocumentJSONBody = interface{} type IndexDocumentParams struct { // Action Additional action to perform Action *IndexDocumentParamsAction `form:"action,omitempty" json:"action,omitempty"` + + // DirtyValues Dealing with Dirty Data + DirtyValues *IndexDocumentParamsDirtyValues `form:"dirty_values,omitempty" json:"dirty_values,omitempty"` } // IndexDocumentParamsAction defines parameters for IndexDocument. type IndexDocumentParamsAction string +// IndexDocumentParamsDirtyValues defines parameters for IndexDocument. +type IndexDocumentParamsDirtyValues string + // ExportDocumentsParams defines parameters for ExportDocuments. type ExportDocumentsParams struct { ExcludeFields *string `form:"exclude_fields,omitempty" json:"exclude_fields,omitempty"` @@ -1057,18 +1296,26 @@ type ExportDocumentsParams struct { // ImportDocumentsParams defines parameters for ImportDocuments. type ImportDocumentsParams struct { - Action *string `form:"action,omitempty" json:"action,omitempty"` + Action *ImportDocumentsParamsAction `form:"action,omitempty" json:"action,omitempty"` BatchSize *int `form:"batch_size,omitempty" json:"batch_size,omitempty"` DirtyValues *ImportDocumentsParamsDirtyValues `form:"dirty_values,omitempty" json:"dirty_values,omitempty"` RemoteEmbeddingBatchSize *int `form:"remote_embedding_batch_size,omitempty" json:"remote_embedding_batch_size,omitempty"` + ReturnDoc *bool `form:"return_doc,omitempty" json:"return_doc,omitempty"` + ReturnId *bool `form:"return_id,omitempty" json:"return_id,omitempty"` } +// ImportDocumentsParamsAction defines parameters for ImportDocuments. +type ImportDocumentsParamsAction string + // ImportDocumentsParamsDirtyValues defines parameters for ImportDocuments. type ImportDocumentsParamsDirtyValues string // SearchCollectionParams defines parameters for SearchCollection. type SearchCollectionParams struct { CacheTtl *int `form:"cache_ttl,omitempty" json:"cache_ttl,omitempty"` + Conversation *bool `form:"conversation,omitempty" json:"conversation,omitempty"` + ConversationId *string `form:"conversation_id,omitempty" json:"conversation_id,omitempty"` + ConversationModelId *string `form:"conversation_model_id,omitempty" json:"conversation_model_id,omitempty"` DropTokensThreshold *int `form:"drop_tokens_threshold,omitempty" json:"drop_tokens_threshold,omitempty"` EnableHighlightV1 *bool `form:"enable_highlight_v1,omitempty" json:"enable_highlight_v1,omitempty"` EnableOverrides *bool `form:"enable_overrides,omitempty" json:"enable_overrides,omitempty"` @@ -1082,6 +1329,7 @@ type SearchCollectionParams struct { FilterBy *string `form:"filter_by,omitempty" json:"filter_by,omitempty"` GroupBy *string `form:"group_by,omitempty" json:"group_by,omitempty"` GroupLimit *int `form:"group_limit,omitempty" json:"group_limit,omitempty"` + GroupMissingValues *bool `form:"group_missing_values,omitempty" json:"group_missing_values,omitempty"` HiddenHits *string `form:"hidden_hits,omitempty" json:"hidden_hits,omitempty"` HighlightAffixNumTokens *int `form:"highlight_affix_num_tokens,omitempty" json:"highlight_affix_num_tokens,omitempty"` HighlightEndTag *string `form:"highlight_end_tag,omitempty" json:"highlight_end_tag,omitempty"` @@ -1123,6 +1371,7 @@ type SearchCollectionParams struct { TypoTokensThreshold *int `form:"typo_tokens_threshold,omitempty" json:"typo_tokens_threshold,omitempty"` UseCache *bool `form:"use_cache,omitempty" json:"use_cache,omitempty"` VectorQuery *string `form:"vector_query,omitempty" json:"vector_query,omitempty"` + VoiceQuery *string `form:"voice_query,omitempty" json:"voice_query,omitempty"` } // UpdateDocumentJSONBody defines parameters for UpdateDocument. @@ -1131,6 +1380,9 @@ type UpdateDocumentJSONBody = interface{} // MultiSearchParams defines parameters for MultiSearch. type MultiSearchParams struct { CacheTtl *int `form:"cache_ttl,omitempty" json:"cache_ttl,omitempty"` + Conversation *bool `form:"conversation,omitempty" json:"conversation,omitempty"` + ConversationId *string `form:"conversation_id,omitempty" json:"conversation_id,omitempty"` + ConversationModelId *string `form:"conversation_model_id,omitempty" json:"conversation_model_id,omitempty"` DropTokensThreshold *int `form:"drop_tokens_threshold,omitempty" json:"drop_tokens_threshold,omitempty"` EnableHighlightV1 *bool `form:"enable_highlight_v1,omitempty" json:"enable_highlight_v1,omitempty"` EnableOverrides *bool `form:"enable_overrides,omitempty" json:"enable_overrides,omitempty"` @@ -1144,6 +1396,7 @@ type MultiSearchParams struct { FilterBy *string `form:"filter_by,omitempty" json:"filter_by,omitempty"` GroupBy *string `form:"group_by,omitempty" json:"group_by,omitempty"` GroupLimit *int `form:"group_limit,omitempty" json:"group_limit,omitempty"` + GroupMissingValues *bool `form:"group_missing_values,omitempty" json:"group_missing_values,omitempty"` HiddenHits *string `form:"hidden_hits,omitempty" json:"hidden_hits,omitempty"` HighlightAffixNumTokens *int `form:"highlight_affix_num_tokens,omitempty" json:"highlight_affix_num_tokens,omitempty"` HighlightEndTag *string `form:"highlight_end_tag,omitempty" json:"highlight_end_tag,omitempty"` @@ -1185,6 +1438,7 @@ type MultiSearchParams struct { TypoTokensThreshold *int `form:"typo_tokens_threshold,omitempty" json:"typo_tokens_threshold,omitempty"` UseCache *bool `form:"use_cache,omitempty" json:"use_cache,omitempty"` VectorQuery *string `form:"vector_query,omitempty" json:"vector_query,omitempty"` + VoiceQuery *string `form:"voice_query,omitempty" json:"voice_query,omitempty"` } // TakeSnapshotParams defines parameters for TakeSnapshot. @@ -1196,11 +1450,14 @@ type TakeSnapshotParams struct { // UpsertAliasJSONRequestBody defines body for UpsertAlias for application/json ContentType. type UpsertAliasJSONRequestBody = CollectionAliasSchema +// CreateAnalyticsEventJSONRequestBody defines body for CreateAnalyticsEvent for application/json ContentType. +type CreateAnalyticsEventJSONRequestBody = AnalyticsEventCreateSchema + // CreateAnalyticsRuleJSONRequestBody defines body for CreateAnalyticsRule for application/json ContentType. type CreateAnalyticsRuleJSONRequestBody = AnalyticsRuleSchema // UpsertAnalyticsRuleJSONRequestBody defines body for UpsertAnalyticsRule for application/json ContentType. -type UpsertAnalyticsRuleJSONRequestBody = AnalyticsRuleSchema +type UpsertAnalyticsRuleJSONRequestBody = AnalyticsRuleUpsertSchema // CreateCollectionJSONRequestBody defines body for CreateCollection for application/json ContentType. type CreateCollectionJSONRequestBody = CollectionSchema @@ -1224,13 +1481,10 @@ type UpsertSearchOverrideJSONRequestBody = SearchOverrideSchema type UpsertSearchSynonymJSONRequestBody = SearchSynonymSchema // CreateConversationModelJSONRequestBody defines body for CreateConversationModel for application/json ContentType. -type CreateConversationModelJSONRequestBody = ConversationModelCreateAndUpdateSchema +type CreateConversationModelJSONRequestBody = ConversationModelCreateSchema // UpdateConversationModelJSONRequestBody defines body for UpdateConversationModel for application/json ContentType. -type UpdateConversationModelJSONRequestBody = ConversationModelCreateAndUpdateSchema - -// UpdateConversationJSONRequestBody defines body for UpdateConversation for application/json ContentType. -type UpdateConversationJSONRequestBody = ConversationUpdateSchema +type UpdateConversationModelJSONRequestBody = ConversationModelUpdateSchema // CreateKeyJSONRequestBody defines body for CreateKey for application/json ContentType. type CreateKeyJSONRequestBody = ApiKeySchema diff --git a/typesense/client.go b/typesense/client.go index d3c9231..2cf897a 100644 --- a/typesense/client.go +++ b/typesense/client.go @@ -48,10 +48,6 @@ func (c *Client) Conversations() ConversationsInterface { return &conversations{apiClient: c.apiClient} } -func (c *Client) Conversation(conversationId string) ConversationInterface { - return &conversation{apiClient: c.apiClient, conversationId: conversationId} -} - func (c *Client) Keys() KeysInterface { return &keys{apiClient: c.apiClient} } diff --git a/typesense/conversation.go b/typesense/conversation.go deleted file mode 100644 index 70e48bb..0000000 --- a/typesense/conversation.go +++ /dev/null @@ -1,51 +0,0 @@ -package typesense - -import ( - "context" - - "github.com/typesense/typesense-go/v2/typesense/api" -) - -type ConversationInterface interface { - Retrieve(ctx context.Context) (*api.ConversationSchema, error) - Update(ctx context.Context, conversation *api.ConversationUpdateSchema) (*api.ConversationSchema, error) - Delete(ctx context.Context) (*api.ConversationSchema, error) -} - -type conversation struct { - apiClient APIClientInterface - conversationId string -} - -func (c *conversation) Retrieve(ctx context.Context) (*api.ConversationSchema, error) { - response, err := c.apiClient.RetrieveConversationWithResponse(ctx, c.conversationId) - if err != nil { - return nil, err - } - if response.JSON200 == nil { - return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} - } - return response.JSON200, nil -} - -func (c *conversation) Update(ctx context.Context, conversation *api.ConversationUpdateSchema) (*api.ConversationSchema, error) { - response, err := c.apiClient.UpdateConversationWithResponse(ctx, c.conversationId, api.UpdateConversationJSONRequestBody(*conversation)) - if err != nil { - return nil, err - } - if response.JSON200 == nil { - return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} - } - return response.JSON200, nil -} - -func (c *conversation) Delete(ctx context.Context) (*api.ConversationSchema, error) { - response, err := c.apiClient.DeleteConversationWithResponse(ctx, c.conversationId) - if err != nil { - return nil, err - } - if response.JSON200 == nil { - return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} - } - return response.JSON200, nil -} diff --git a/typesense/conversation_model.go b/typesense/conversation_model.go index 75206cd..ce888b6 100644 --- a/typesense/conversation_model.go +++ b/typesense/conversation_model.go @@ -8,7 +8,7 @@ import ( type ConversationModelInterface interface { Retrieve(ctx context.Context) (*api.ConversationModelSchema, error) - Update(ctx context.Context, model *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelCreateAndUpdateSchema, error) + Update(ctx context.Context, schema *api.ConversationModelUpdateSchema) (*api.ConversationModelSchema, error) Delete(ctx context.Context) (*api.ConversationModelSchema, error) } @@ -28,8 +28,8 @@ func (c *conversationModel) Retrieve(ctx context.Context) (*api.ConversationMode return response.JSON200, nil } -func (c *conversationModel) Update(ctx context.Context, conversationModelCreateAndUpdateSchema *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelCreateAndUpdateSchema, error) { - response, err := c.apiClient.UpdateConversationModelWithResponse(ctx, c.modelId, api.UpdateConversationModelJSONRequestBody(*conversationModelCreateAndUpdateSchema)) +func (c *conversationModel) Update(ctx context.Context, schema *api.ConversationModelUpdateSchema) (*api.ConversationModelSchema, error) { + response, err := c.apiClient.UpdateConversationModelWithResponse(ctx, c.modelId, api.UpdateConversationModelJSONRequestBody(*schema)) if err != nil { return nil, err } diff --git a/typesense/conversation_model_test.go b/typesense/conversation_model_test.go index 5a6fd5d..278f6d4 100644 --- a/typesense/conversation_model_test.go +++ b/typesense/conversation_model_test.go @@ -14,8 +14,8 @@ import ( func TestConversationModelRetrieve(t *testing.T) { expectedData := &api.ConversationModelSchema{ Id: "123", - ModelName: "cf/mistral/mistral-7b-instruct-v0.1", - ApiKey: "CLOUDFLARE_API_KEY", + ModelName: "cloudflare/@cf/mistral/mistral-7b-instruct-v0.1", + ApiKey: pointer.String("CLOUDFLARE_API_KEY"), AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), SystemPrompt: pointer.String("..."), MaxBytes: 16384, @@ -46,22 +46,30 @@ func TestConversationModelRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T } func TestConversationModelUpdate(t *testing.T) { - expectedData := &api.ConversationModelCreateAndUpdateSchema{ - ModelName: "cf/mistral/mistral-7b-instruct-v0.1", - ApiKey: "CLOUDFLARE_API_KEY", + model := &api.ConversationModelUpdateSchema{ + ModelName: pointer.String("cf/mistral/mistral-7b-instruct-v0.1"), + ApiKey: pointer.String("CLOUDFLARE_API_KEY"), AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), SystemPrompt: pointer.String("..."), - MaxBytes: 16384, + MaxBytes: pointer.Int(16384), + } + expectedData := &api.ConversationModelSchema{ + Id: "123", + ModelName: *model.ModelName, + ApiKey: model.ApiKey, + AccountId: model.AccountId, + SystemPrompt: model.SystemPrompt, + MaxBytes: *model.MaxBytes, } server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations/models/123", http.MethodPut) - var reqBody api.ConversationModelCreateAndUpdateSchema + var reqBody api.ConversationModelUpdateSchema err := json.NewDecoder(r.Body).Decode(&reqBody) assert.NoError(t, err) - assert.Equal(t, expectedData, &reqBody) + assert.Equal(t, model, &reqBody) data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") @@ -69,7 +77,7 @@ func TestConversationModelUpdate(t *testing.T) { }) defer server.Close() - res, err := client.Conversations().Model("123").Update(context.Background(), expectedData) + res, err := client.Conversations().Model("123").Update(context.Background(), model) assert.NoError(t, err) assert.Equal(t, expectedData, res) } @@ -81,15 +89,20 @@ func TestConversationModelUpdateOnHttpStatusErrorCodeReturnsError(t *testing.T) }) defer server.Close() - _, err := client.Conversations().Model("123").Update(context.Background(), &api.ConversationModelCreateAndUpdateSchema{ - ModelName: "cf/mistral/mistral-7b-instruct-v0.1", - }) + _, err := client.Conversations().Model("123").Update(context.Background(), &api.ConversationModelUpdateSchema{}) assert.ErrorContains(t, err, "status: 409") } func TestConversationModelDelete(t *testing.T) { expectedData := &api.ConversationModelSchema{ - Id: "123", + Id: "123", + ModelName: "cf/mistral/mistral-7b-instruct-v0.1", + ApiKey: pointer.String("CLOUDFLARE_API_KEY"), + AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), + SystemPrompt: pointer.String("..."), + MaxBytes: 16384, + HistoryCollection: "conversation-store", + Ttl: pointer.Int(10000), } server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { diff --git a/typesense/conversation_models.go b/typesense/conversation_models.go index 2e16a55..bda1d89 100644 --- a/typesense/conversation_models.go +++ b/typesense/conversation_models.go @@ -8,7 +8,7 @@ import ( // ConversationModelsInterface is a type for ConversationModels API operations type ConversationModelsInterface interface { - Create(ctx context.Context, conversationModelCreateAndUpdateSchema *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelSchema, error) + Create(ctx context.Context, schema *api.ConversationModelCreateSchema) (*api.ConversationModelSchema, error) Retrieve(ctx context.Context) ([]*api.ConversationModelSchema, error) } @@ -17,15 +17,15 @@ type conversationModels struct { apiClient APIClientInterface } -func (c *conversationModels) Create(ctx context.Context, conversationModelCreateAndUpdateSchema *api.ConversationModelCreateAndUpdateSchema) (*api.ConversationModelSchema, error) { - response, err := c.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*conversationModelCreateAndUpdateSchema)) +func (c *conversationModels) Create(ctx context.Context, schema *api.ConversationModelCreateSchema) (*api.ConversationModelSchema, error) { + response, err := c.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*schema)) if err != nil { return nil, err } - if response.JSON201 == nil { + if response.JSON200 == nil { return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} } - return response.JSON201, nil + return response.JSON200, nil } func (c *conversationModels) Retrieve(ctx context.Context) ([]*api.ConversationModelSchema, error) { diff --git a/typesense/conversation_models_test.go b/typesense/conversation_models_test.go index 61200f1..0852759 100644 --- a/typesense/conversation_models_test.go +++ b/typesense/conversation_models_test.go @@ -13,12 +13,14 @@ import ( func TestConversationModelsRetrieve(t *testing.T) { expectedData := []*api.ConversationModelSchema{{ - Id: "123", - ModelName: "cf/mistral/mistral-7b-instruct-v0.1", - ApiKey: "CLOUDFLARE_API_KEY", - AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), - SystemPrompt: pointer.String("..."), - MaxBytes: 16384, + Id: "123", + ModelName: "cf/mistral/mistral-7b-instruct-v0.1", + ApiKey: pointer.String("CLOUDFLARE_API_KEY"), + AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), + SystemPrompt: pointer.String("..."), + MaxBytes: 16384, + HistoryCollection: "conversation-store", + Ttl: pointer.Int(10000), }} server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { @@ -46,26 +48,30 @@ func TestConversationModelsRetrieveOnHttpStatusErrorCodeReturnsError(t *testing. } func TestConversationModelsCreate(t *testing.T) { - model := &api.ConversationModelCreateAndUpdateSchema{ - ModelName: "cf/mistral/mistral-7b-instruct-v0.1", - ApiKey: "CLOUDFLARE_API_KEY", - AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), - SystemPrompt: pointer.String("..."), - MaxBytes: 16384, + model := &api.ConversationModelCreateSchema{ + ModelName: "cf/mistral/mistral-7b-instruct-v0.1", + ApiKey: pointer.String("CLOUDFLARE_API_KEY"), + AccountId: pointer.String("CLOUDFLARE_ACCOUNT_ID"), + SystemPrompt: pointer.String("..."), + MaxBytes: 16384, + HistoryCollection: "conversation-store", + Ttl: pointer.Int(10000), } expectedData := &api.ConversationModelSchema{ - Id: "123", - ModelName: model.ModelName, - ApiKey: model.ApiKey, - AccountId: model.AccountId, - SystemPrompt: model.SystemPrompt, - MaxBytes: model.MaxBytes, + Id: "123", + ModelName: model.ModelName, + ApiKey: model.ApiKey, + AccountId: model.AccountId, + SystemPrompt: model.SystemPrompt, + MaxBytes: model.MaxBytes, + HistoryCollection: model.HistoryCollection, + Ttl: pointer.Int(10000), } server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { validateRequestMetadata(t, r, "/conversations/models", http.MethodPost) - var reqBody api.ConversationModelCreateAndUpdateSchema + var reqBody api.ConversationModelCreateSchema err := json.NewDecoder(r.Body).Decode(&reqBody) assert.NoError(t, err) @@ -90,6 +96,6 @@ func TestConversationModelsCreateOnHttpStatusErrorCodeReturnsError(t *testing.T) }) defer server.Close() - _, err := client.Conversations().Models().Create(context.Background(), &api.ConversationModelCreateAndUpdateSchema{}) + _, err := client.Conversations().Models().Create(context.Background(), &api.ConversationModelCreateSchema{}) assert.ErrorContains(t, err, "status: 409") } diff --git a/typesense/conversation_test.go b/typesense/conversation_test.go deleted file mode 100644 index b6f92b1..0000000 --- a/typesense/conversation_test.go +++ /dev/null @@ -1,122 +0,0 @@ -package typesense - -import ( - "context" - "encoding/json" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/typesense/typesense-go/v2/typesense/api" -) - -func TestConversationRetrieveConversation(t *testing.T) { - expectedData := &api.ConversationSchema{ - Id: "123", - Conversation: []map[string]any{ - { - "user": "can you suggest an action series", - }, - { - "assistant": "...", - }}, - LastUpdated: 12, - Ttl: 34, - } - - server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - validateRequestMetadata(t, r, "/conversations/123", http.MethodGet) - data := jsonEncode(t, expectedData) - - w.Header().Set("Content-Type", "application/json") - w.Write(data) - }) - defer server.Close() - - res, err := client.Conversation(expectedData.Id).Retrieve(context.Background()) - assert.NoError(t, err) - assert.Equal(t, expectedData, res) -} - -func TestConversationRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { - server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - validateRequestMetadata(t, r, "/conversations/123", http.MethodGet) - w.WriteHeader(http.StatusConflict) - }) - defer server.Close() - - _, err := client.Conversation("123").Retrieve(context.Background()) - assert.ErrorContains(t, err, "status: 409") -} -func TestConversationUpdateConversation(t *testing.T) { - expectedData := &api.ConversationSchema{ - Id: "123", - } - updateData := &api.ConversationUpdateSchema{ - Ttl: 3000, - } - - server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - validateRequestMetadata(t, r, "/conversations/123", http.MethodPut) - - var reqBody api.ConversationUpdateSchema - err := json.NewDecoder(r.Body).Decode(&reqBody) - - assert.NoError(t, err) - assert.Equal(t, updateData, &reqBody) - - data := jsonEncode(t, expectedData) - w.Header().Set("Content-Type", "application/json") - w.Write(data) - }) - defer server.Close() - - res, err := client.Conversation("123").Update(context.Background(), updateData) - - assert.NoError(t, err) - assert.Equal(t, expectedData, res) -} - -func TestConversationUpdateOnHttpStatusErrorCodeReturnsError(t *testing.T) { - server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - validateRequestMetadata(t, r, "/conversations/123", http.MethodPut) - w.WriteHeader(http.StatusConflict) - }) - defer server.Close() - - _, err := client.Conversation("123").Update(context.Background(), &api.ConversationUpdateSchema{ - Ttl: 0, - }) - assert.ErrorContains(t, err, "status: 409") -} - -func TestConversationDeleteConversation(t *testing.T) { - expectedData := &api.ConversationSchema{ - Id: "123", - } - - server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - validateRequestMetadata(t, r, "/conversations/123", http.MethodDelete) - data := jsonEncode(t, expectedData) - - w.Header().Set("Content-Type", "application/json") - w.Write(data) - }) - defer server.Close() - - res, err := client.Conversation("123").Delete(context.Background()) - - assert.NoError(t, err) - assert.Equal(t, expectedData, res) -} - -func TestConversationDeleteOnHttpStatusErrorCodeReturnsError(t *testing.T) { - server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - validateRequestMetadata(t, r, "/conversations/123", http.MethodDelete) - w.WriteHeader(http.StatusConflict) - }) - defer server.Close() - - _, err := client.Conversation("123").Delete(context.Background()) - assert.ErrorContains(t, err, "status: 409") -} diff --git a/typesense/conversations.go b/typesense/conversations.go index 2837bb5..a00c9f1 100644 --- a/typesense/conversations.go +++ b/typesense/conversations.go @@ -1,14 +1,7 @@ package typesense -import ( - "context" - - "github.com/typesense/typesense-go/v2/typesense/api" -) - // ConversationsInterface is a type for Conversations API operations type ConversationsInterface interface { - Retrieve(ctx context.Context) ([]*api.ConversationSchema, error) Models() ConversationModelsInterface Model(modelId string) ConversationModelInterface } @@ -18,17 +11,6 @@ type conversations struct { apiClient APIClientInterface } -func (c *conversations) Retrieve(ctx context.Context) ([]*api.ConversationSchema, error) { - response, err := c.apiClient.RetrieveAllConversationsWithResponse(ctx) - if err != nil { - return nil, err - } - if response.JSON200 == nil { - return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} - } - return *response.JSON200, nil -} - func (c *conversations) Models() ConversationModelsInterface { return &conversationModels{apiClient: c.apiClient} } diff --git a/typesense/conversations_test.go b/typesense/conversations_test.go deleted file mode 100644 index 9168dcd..0000000 --- a/typesense/conversations_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package typesense - -import ( - "context" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/typesense/typesense-go/v2/typesense/api" -) - -func TestConversationsRetrieveAllConversations(t *testing.T) { - expectedData := []*api.ConversationSchema{ - { - Id: "abc", - Conversation: []map[string]any{ - { - "user": "can you suggest an action series", - }, - { - "assistant": "...", - }, - }, - LastUpdated: 12, - Ttl: 86400, - }, - } - - server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - validateRequestMetadata(t, r, "/conversations", http.MethodGet) - data := jsonEncode(t, expectedData) - w.Header().Set("Content-Type", "application/json") - w.Write(data) - }) - defer server.Close() - - res, err := client.Conversations().Retrieve(context.Background()) - assert.NoError(t, err) - assert.Equal(t, expectedData, res) -} - -func TestConversationsRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { - server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - validateRequestMetadata(t, r, "/conversations", http.MethodGet) - w.WriteHeader(http.StatusConflict) - }) - defer server.Close() - - _, err := client.Conversations().Retrieve(context.Background()) - assert.ErrorContains(t, err, "status: 409") -} diff --git a/typesense/documents_test.go b/typesense/documents_test.go index b8e09c0..49f2424 100644 --- a/typesense/documents_test.go +++ b/typesense/documents_test.go @@ -338,3 +338,51 @@ func TestDocumentsExportOnHttpStatusErrorCodeReturnsError(t *testing.T) { _, err := client.Collection("companies").Documents().Export(context.Background()) assert.NotNil(t, err) } + +func TestSingleCollectionSearchRAG(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/collections/test/documents/search?q=can+you+suggest&conversation=true&conversation_model_id=conv-1&conversation_id=123", http.MethodPost) + w.Header().Set("Content-Type", "application/json") + w.Write([]byte(` + { + "conversation": { + "answer": "Based on the context provided,...", + "conversation_history": [ + { + "user": "can you suggest an action series" + }, + { + "assistant": "Based on the context provided,..." + } + ], + "conversation_id": "abc", + "query": "can you suggest" + } + }`)) + }) + defer server.Close() + + res, err := client.Collection("test").Documents().Search(context.Background(), &api.SearchCollectionParams{ + Q: pointer.String("can you suggest"), + Conversation: pointer.True(), + ConversationModelId: pointer.String("conv-1"), + ConversationId: pointer.String("123"), + }) + + assert.NotNil(t, err) + assert.Equal(t, &api.SearchResult{ + Conversation: &api.SearchResultConversation{ + Answer: "Based on the context provided,...", + ConversationHistory: []map[string]interface{}{ + { + "user": "can you suggest an action series", + }, + { + "assistant": "Based on the context provided,...", + }, + }, + ConversationId: "abc", + Query: "can you suggest", + }, + }, res) +} diff --git a/typesense/mocks/mock_client.go b/typesense/mocks/mock_client.go index 65c436f..7092a9a 100644 --- a/typesense/mocks/mock_client.go +++ b/typesense/mocks/mock_client.go @@ -42,6 +42,86 @@ func (m *MockAPIClientInterface) EXPECT() *MockAPIClientInterfaceMockRecorder { return m.recorder } +// CreateAnalyticsEvent mocks base method. +func (m *MockAPIClientInterface) CreateAnalyticsEvent(ctx context.Context, body api.CreateAnalyticsEventJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CreateAnalyticsEvent", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateAnalyticsEvent indicates an expected call of CreateAnalyticsEvent. +func (mr *MockAPIClientInterfaceMockRecorder) CreateAnalyticsEvent(ctx, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAnalyticsEvent", reflect.TypeOf((*MockAPIClientInterface)(nil).CreateAnalyticsEvent), varargs...) +} + +// CreateAnalyticsEventWithBody mocks base method. +func (m *MockAPIClientInterface) CreateAnalyticsEventWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, contentType, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CreateAnalyticsEventWithBody", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateAnalyticsEventWithBody indicates an expected call of CreateAnalyticsEventWithBody. +func (mr *MockAPIClientInterfaceMockRecorder) CreateAnalyticsEventWithBody(ctx, contentType, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, contentType, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAnalyticsEventWithBody", reflect.TypeOf((*MockAPIClientInterface)(nil).CreateAnalyticsEventWithBody), varargs...) +} + +// CreateAnalyticsEventWithBodyWithResponse mocks base method. +func (m *MockAPIClientInterface) CreateAnalyticsEventWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*api.CreateAnalyticsEventResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, contentType, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CreateAnalyticsEventWithBodyWithResponse", varargs...) + ret0, _ := ret[0].(*api.CreateAnalyticsEventResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateAnalyticsEventWithBodyWithResponse indicates an expected call of CreateAnalyticsEventWithBodyWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) CreateAnalyticsEventWithBodyWithResponse(ctx, contentType, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, contentType, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAnalyticsEventWithBodyWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).CreateAnalyticsEventWithBodyWithResponse), varargs...) +} + +// CreateAnalyticsEventWithResponse mocks base method. +func (m *MockAPIClientInterface) CreateAnalyticsEventWithResponse(ctx context.Context, body api.CreateAnalyticsEventJSONRequestBody, reqEditors ...api.RequestEditorFn) (*api.CreateAnalyticsEventResponse, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, body} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CreateAnalyticsEventWithResponse", varargs...) + ret0, _ := ret[0].(*api.CreateAnalyticsEventResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateAnalyticsEventWithResponse indicates an expected call of CreateAnalyticsEventWithResponse. +func (mr *MockAPIClientInterfaceMockRecorder) CreateAnalyticsEventWithResponse(ctx, body any, reqEditors ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, body}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAnalyticsEventWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).CreateAnalyticsEventWithResponse), varargs...) +} + // CreateAnalyticsRule mocks base method. func (m *MockAPIClientInterface) CreateAnalyticsRule(ctx context.Context, body api.CreateAnalyticsRuleJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -522,26 +602,6 @@ func (mr *MockAPIClientInterfaceMockRecorder) DeleteCollectionWithResponse(ctx, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCollectionWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).DeleteCollectionWithResponse), varargs...) } -// DeleteConversation mocks base method. -func (m *MockAPIClientInterface) DeleteConversation(ctx context.Context, conversationId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { - m.ctrl.T.Helper() - varargs := []any{ctx, conversationId} - for _, a := range reqEditors { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "DeleteConversation", varargs...) - ret0, _ := ret[0].(*http.Response) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DeleteConversation indicates an expected call of DeleteConversation. -func (mr *MockAPIClientInterfaceMockRecorder) DeleteConversation(ctx, conversationId any, reqEditors ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, conversationId}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).DeleteConversation), varargs...) -} - // DeleteConversationModel mocks base method. func (m *MockAPIClientInterface) DeleteConversationModel(ctx context.Context, modelId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -582,26 +642,6 @@ func (mr *MockAPIClientInterfaceMockRecorder) DeleteConversationModelWithRespons return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConversationModelWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).DeleteConversationModelWithResponse), varargs...) } -// DeleteConversationWithResponse mocks base method. -func (m *MockAPIClientInterface) DeleteConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...api.RequestEditorFn) (*api.DeleteConversationResponse, error) { - m.ctrl.T.Helper() - varargs := []any{ctx, conversationId} - for _, a := range reqEditors { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "DeleteConversationWithResponse", varargs...) - ret0, _ := ret[0].(*api.DeleteConversationResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DeleteConversationWithResponse indicates an expected call of DeleteConversationWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) DeleteConversationWithResponse(ctx, conversationId any, reqEditors ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, conversationId}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConversationWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).DeleteConversationWithResponse), varargs...) -} - // DeleteDocument mocks base method. func (m *MockAPIClientInterface) DeleteDocument(ctx context.Context, collectionName, documentId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -1682,46 +1722,6 @@ func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationModelsWithR return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationModelsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationModelsWithResponse), varargs...) } -// RetrieveAllConversations mocks base method. -func (m *MockAPIClientInterface) RetrieveAllConversations(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { - m.ctrl.T.Helper() - varargs := []any{ctx} - for _, a := range reqEditors { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "RetrieveAllConversations", varargs...) - ret0, _ := ret[0].(*http.Response) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RetrieveAllConversations indicates an expected call of RetrieveAllConversations. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversations(ctx any, reqEditors ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversations", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversations), varargs...) -} - -// RetrieveAllConversationsWithResponse mocks base method. -func (m *MockAPIClientInterface) RetrieveAllConversationsWithResponse(ctx context.Context, reqEditors ...api.RequestEditorFn) (*api.RetrieveAllConversationsResponse, error) { - m.ctrl.T.Helper() - varargs := []any{ctx} - for _, a := range reqEditors { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "RetrieveAllConversationsWithResponse", varargs...) - ret0, _ := ret[0].(*api.RetrieveAllConversationsResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RetrieveAllConversationsWithResponse indicates an expected call of RetrieveAllConversationsWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAllConversationsWithResponse(ctx any, reqEditors ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAllConversationsWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAllConversationsWithResponse), varargs...) -} - // RetrieveAllPresets mocks base method. func (m *MockAPIClientInterface) RetrieveAllPresets(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -1842,26 +1842,6 @@ func (mr *MockAPIClientInterfaceMockRecorder) RetrieveAnalyticsRulesWithResponse return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveAnalyticsRulesWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveAnalyticsRulesWithResponse), varargs...) } -// RetrieveConversation mocks base method. -func (m *MockAPIClientInterface) RetrieveConversation(ctx context.Context, conversationId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { - m.ctrl.T.Helper() - varargs := []any{ctx, conversationId} - for _, a := range reqEditors { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "RetrieveConversation", varargs...) - ret0, _ := ret[0].(*http.Response) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RetrieveConversation indicates an expected call of RetrieveConversation. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversation(ctx, conversationId any, reqEditors ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, conversationId}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversation), varargs...) -} - // RetrieveConversationModel mocks base method. func (m *MockAPIClientInterface) RetrieveConversationModel(ctx context.Context, modelId string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -1902,26 +1882,6 @@ func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationModelWithRespo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationModelWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationModelWithResponse), varargs...) } -// RetrieveConversationWithResponse mocks base method. -func (m *MockAPIClientInterface) RetrieveConversationWithResponse(ctx context.Context, conversationId string, reqEditors ...api.RequestEditorFn) (*api.RetrieveConversationResponse, error) { - m.ctrl.T.Helper() - varargs := []any{ctx, conversationId} - for _, a := range reqEditors { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "RetrieveConversationWithResponse", varargs...) - ret0, _ := ret[0].(*api.RetrieveConversationResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RetrieveConversationWithResponse indicates an expected call of RetrieveConversationWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) RetrieveConversationWithResponse(ctx, conversationId any, reqEditors ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, conversationId}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetrieveConversationWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).RetrieveConversationWithResponse), varargs...) -} - // RetrieveMetrics mocks base method. func (m *MockAPIClientInterface) RetrieveMetrics(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -2242,26 +2202,6 @@ func (mr *MockAPIClientInterfaceMockRecorder) UpdateCollectionWithResponse(ctx, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateCollectionWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateCollectionWithResponse), varargs...) } -// UpdateConversation mocks base method. -func (m *MockAPIClientInterface) UpdateConversation(ctx context.Context, conversationId string, body api.UpdateConversationJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { - m.ctrl.T.Helper() - varargs := []any{ctx, conversationId, body} - for _, a := range reqEditors { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "UpdateConversation", varargs...) - ret0, _ := ret[0].(*http.Response) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdateConversation indicates an expected call of UpdateConversation. -func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversation(ctx, conversationId, body any, reqEditors ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, conversationId, body}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversation", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversation), varargs...) -} - // UpdateConversationModel mocks base method. func (m *MockAPIClientInterface) UpdateConversationModel(ctx context.Context, modelId string, body api.UpdateConversationModelJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -2342,66 +2282,6 @@ func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationModelWithRespons return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationModelWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationModelWithResponse), varargs...) } -// UpdateConversationWithBody mocks base method. -func (m *MockAPIClientInterface) UpdateConversationWithBody(ctx context.Context, conversationId, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { - m.ctrl.T.Helper() - varargs := []any{ctx, conversationId, contentType, body} - for _, a := range reqEditors { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "UpdateConversationWithBody", varargs...) - ret0, _ := ret[0].(*http.Response) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdateConversationWithBody indicates an expected call of UpdateConversationWithBody. -func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationWithBody(ctx, conversationId, contentType, body any, reqEditors ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, conversationId, contentType, body}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationWithBody", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationWithBody), varargs...) -} - -// UpdateConversationWithBodyWithResponse mocks base method. -func (m *MockAPIClientInterface) UpdateConversationWithBodyWithResponse(ctx context.Context, conversationId, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*api.UpdateConversationResponse, error) { - m.ctrl.T.Helper() - varargs := []any{ctx, conversationId, contentType, body} - for _, a := range reqEditors { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "UpdateConversationWithBodyWithResponse", varargs...) - ret0, _ := ret[0].(*api.UpdateConversationResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdateConversationWithBodyWithResponse indicates an expected call of UpdateConversationWithBodyWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationWithBodyWithResponse(ctx, conversationId, contentType, body any, reqEditors ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, conversationId, contentType, body}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationWithBodyWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationWithBodyWithResponse), varargs...) -} - -// UpdateConversationWithResponse mocks base method. -func (m *MockAPIClientInterface) UpdateConversationWithResponse(ctx context.Context, conversationId string, body api.UpdateConversationJSONRequestBody, reqEditors ...api.RequestEditorFn) (*api.UpdateConversationResponse, error) { - m.ctrl.T.Helper() - varargs := []any{ctx, conversationId, body} - for _, a := range reqEditors { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "UpdateConversationWithResponse", varargs...) - ret0, _ := ret[0].(*api.UpdateConversationResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdateConversationWithResponse indicates an expected call of UpdateConversationWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationWithResponse(ctx, conversationId, body any, reqEditors ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, conversationId, body}, reqEditors...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConversationWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateConversationWithResponse), varargs...) -} - // UpdateDocument mocks base method. func (m *MockAPIClientInterface) UpdateDocument(ctx context.Context, collectionName, documentId string, body api.UpdateDocumentJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() diff --git a/typesense/multi_search_test.go b/typesense/multi_search_test.go index da019e6..3cc27ee 100644 --- a/typesense/multi_search_test.go +++ b/typesense/multi_search_test.go @@ -293,3 +293,54 @@ func TestMultiSearchOnApiClientError(t *testing.T) { _, err := client.MultiSearch.Perform(context.Background(), params, newMultiSearchBodyParams()) assert.NotNil(t, err) } + +func TestMultiSearchRAG(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/multi_search?q=can+you+suggest&conversation=true&conversation_model_id=conv-1&conversation_id=123", http.MethodPost) + w.Header().Set("Content-Type", "application/json") + w.Write([]byte(` + { + "conversation": { + "answer": "Based on the context provided,...", + "conversation_history": [ + { + "user": "can you suggest an action series" + }, + { + "assistant": "Based on the context provided,..." + } + ], + "conversation_id": "abc", + "query": "can you suggest" + }, + "results": [] + }`)) + }) + defer server.Close() + + res, err := client.MultiSearch.Perform(context.Background(), &api.MultiSearchParams{ + Q: pointer.String("can you suggest"), + Conversation: pointer.True(), + ConversationModelId: pointer.String("conv-1"), + ConversationId: pointer.String("123"), + }, api.MultiSearchSearchesParameter{ + Searches: newMultiSearchBodyParams().Searches, + }) + + assert.NotNil(t, err) + assert.Equal(t, &api.MultiSearchResult{ + Conversation: &api.SearchResultConversation{ + Answer: "Based on the context provided,...", + ConversationHistory: []map[string]interface{}{ + { + "user": "can you suggest an action series", + }, + { + "assistant": "Based on the context provided,...", + }, + }, + ConversationId: "abc", + Query: "can you suggest", + }, + }, res) +} From 7967cf543b49c3ebb7a9250eaf40d7827c42f59f Mon Sep 17 00:00:00 2001 From: Hayden Date: Tue, 17 Sep 2024 20:12:44 +0700 Subject: [PATCH 11/19] fix: conversation API tests --- typesense/conversation_models_test.go | 1 - typesense/documents_test.go | 4 ++-- typesense/multi_search_test.go | 7 +++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/typesense/conversation_models_test.go b/typesense/conversation_models_test.go index 0852759..41f9236 100644 --- a/typesense/conversation_models_test.go +++ b/typesense/conversation_models_test.go @@ -79,7 +79,6 @@ func TestConversationModelsCreate(t *testing.T) { data := jsonEncode(t, expectedData) w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusCreated) w.Write(data) }) defer server.Close() diff --git a/typesense/documents_test.go b/typesense/documents_test.go index 49f2424..e6a7075 100644 --- a/typesense/documents_test.go +++ b/typesense/documents_test.go @@ -341,7 +341,7 @@ func TestDocumentsExportOnHttpStatusErrorCodeReturnsError(t *testing.T) { func TestSingleCollectionSearchRAG(t *testing.T) { server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - validateRequestMetadata(t, r, "/collections/test/documents/search?q=can+you+suggest&conversation=true&conversation_model_id=conv-1&conversation_id=123", http.MethodPost) + validateRequestMetadata(t, r, "/collections/test/documents/search?conversation=true&conversation_id=123&conversation_model_id=conv-1&q=can+you+suggest", http.MethodGet) w.Header().Set("Content-Type", "application/json") w.Write([]byte(` { @@ -369,7 +369,7 @@ func TestSingleCollectionSearchRAG(t *testing.T) { ConversationId: pointer.String("123"), }) - assert.NotNil(t, err) + assert.NoError(t, err) assert.Equal(t, &api.SearchResult{ Conversation: &api.SearchResultConversation{ Answer: "Based on the context provided,...", diff --git a/typesense/multi_search_test.go b/typesense/multi_search_test.go index 3cc27ee..08a7afc 100644 --- a/typesense/multi_search_test.go +++ b/typesense/multi_search_test.go @@ -296,7 +296,7 @@ func TestMultiSearchOnApiClientError(t *testing.T) { func TestMultiSearchRAG(t *testing.T) { server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { - validateRequestMetadata(t, r, "/multi_search?q=can+you+suggest&conversation=true&conversation_model_id=conv-1&conversation_id=123", http.MethodPost) + validateRequestMetadata(t, r, "/multi_search?conversation=true&conversation_id=123&conversation_model_id=conv-1&q=can+you+suggest", http.MethodPost) w.Header().Set("Content-Type", "application/json") w.Write([]byte(` { @@ -312,8 +312,7 @@ func TestMultiSearchRAG(t *testing.T) { ], "conversation_id": "abc", "query": "can you suggest" - }, - "results": [] + } }`)) }) defer server.Close() @@ -327,7 +326,7 @@ func TestMultiSearchRAG(t *testing.T) { Searches: newMultiSearchBodyParams().Searches, }) - assert.NotNil(t, err) + assert.NoError(t, err) assert.Equal(t, &api.MultiSearchResult{ Conversation: &api.SearchResultConversation{ Answer: "Based on the context provided,...", From dd791ffee2b505be057eb50724b2b740fa5121a3 Mon Sep 17 00:00:00 2001 From: Hayden Date: Tue, 17 Sep 2024 21:57:49 +0700 Subject: [PATCH 12/19] feat: analytics --- typesense/analytics.go | 23 ++++++ typesense/analytics_events.go | 26 +++++++ typesense/analytics_events_test.go | 55 ++++++++++++++ typesense/analytics_rule.go | 39 ++++++++++ typesense/analytics_rule_test.go | 75 +++++++++++++++++++ typesense/analytics_rules.go | 39 ++++++++++ typesense/analytics_rules_test.go | 98 +++++++++++++++++++++++++ typesense/client.go | 4 + typesense/test/analytics_events_test.go | 31 ++++++++ typesense/test/analytics_rule_test.go | 33 +++++++++ typesense/test/analytics_rules_test.go | 47 ++++++++++++ typesense/test/dbhelpers_test.go | 72 +++++++++++++++--- 12 files changed, 532 insertions(+), 10 deletions(-) create mode 100644 typesense/analytics.go create mode 100644 typesense/analytics_events.go create mode 100644 typesense/analytics_events_test.go create mode 100644 typesense/analytics_rule.go create mode 100644 typesense/analytics_rule_test.go create mode 100644 typesense/analytics_rules.go create mode 100644 typesense/analytics_rules_test.go create mode 100644 typesense/test/analytics_events_test.go create mode 100644 typesense/test/analytics_rule_test.go create mode 100644 typesense/test/analytics_rules_test.go diff --git a/typesense/analytics.go b/typesense/analytics.go new file mode 100644 index 0000000..21fe01c --- /dev/null +++ b/typesense/analytics.go @@ -0,0 +1,23 @@ +package typesense + +type AnalyticsInterface interface { + Events() AnalyticsEventsInterface + Rules() AnalyticsRulesInterface + Rule(ruleName string) AnalyticsRuleInterface +} + +type analytics struct { + apiClient APIClientInterface +} + +func (a *analytics) Events() AnalyticsEventsInterface { + return &analyticsEvents{apiClient: a.apiClient} +} + +func (a *analytics) Rules() AnalyticsRulesInterface { + return &analyticsRules{apiClient: a.apiClient} +} + +func (a *analytics) Rule(ruleName string) AnalyticsRuleInterface { + return &analyticsRule{apiClient: a.apiClient, ruleName: ruleName} +} diff --git a/typesense/analytics_events.go b/typesense/analytics_events.go new file mode 100644 index 0000000..34f2386 --- /dev/null +++ b/typesense/analytics_events.go @@ -0,0 +1,26 @@ +package typesense + +import ( + "context" + + "github.com/typesense/typesense-go/v2/typesense/api" +) + +type AnalyticsEventsInterface interface { + Create(ctx context.Context, eventSchema *api.AnalyticsEventCreateSchema) (*api.AnalyticsEventCreateResponse, error) +} + +type analyticsEvents struct { + apiClient APIClientInterface +} + +func (a *analyticsEvents) Create(ctx context.Context, eventSchema *api.AnalyticsEventCreateSchema) (*api.AnalyticsEventCreateResponse, error) { + response, err := a.apiClient.CreateAnalyticsEventWithResponse(ctx, api.CreateAnalyticsEventJSONRequestBody(*eventSchema)) + if err != nil { + return nil, err + } + if response.JSON201 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON201, nil +} diff --git a/typesense/analytics_events_test.go b/typesense/analytics_events_test.go new file mode 100644 index 0000000..f1ef194 --- /dev/null +++ b/typesense/analytics_events_test.go @@ -0,0 +1,55 @@ +package typesense + +import ( + "context" + "encoding/json" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/typesense/typesense-go/v2/typesense/api" +) + +func TestAnalyticsEventsCreate(t *testing.T) { + expectedData := &api.AnalyticsEventCreateSchema{ + Name: "products_click_event", + Type: "click", + Data: map[string]interface{}{ + "hello": "hi", + }, + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/analytics/events", http.MethodPost) + + var reqBody api.AnalyticsEventCreateSchema + err := json.NewDecoder(r.Body).Decode(&reqBody) + + assert.NoError(t, err) + assert.Equal(t, *expectedData, reqBody) + + data := jsonEncode(t, api.AnalyticsEventCreateResponse{ + Ok: true, + }) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + w.Write(data) + }) + defer server.Close() + + res, err := client.Analytics().Events().Create(context.Background(), expectedData) + assert.NoError(t, err) + assert.True(t, res.Ok) +} + +func TestAnalyticsEventsCreateOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/analytics/events", http.MethodPost) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Analytics().Events().Create(context.Background(), &api.AnalyticsEventCreateSchema{}) + assert.ErrorContains(t, err, "status: 409") +} diff --git a/typesense/analytics_rule.go b/typesense/analytics_rule.go new file mode 100644 index 0000000..6a66313 --- /dev/null +++ b/typesense/analytics_rule.go @@ -0,0 +1,39 @@ +package typesense + +import ( + "context" + + "github.com/typesense/typesense-go/v2/typesense/api" +) + +type AnalyticsRuleInterface interface { + Delete(ctx context.Context) (*api.AnalyticsRuleDeleteResponse, error) + Retrieve(ctx context.Context) (*api.AnalyticsRuleSchema, error) +} + +type analyticsRule struct { + apiClient APIClientInterface + ruleName string +} + +func (a *analyticsRule) Delete(ctx context.Context) (*api.AnalyticsRuleDeleteResponse, error) { + response, err := a.apiClient.DeleteAnalyticsRuleWithResponse(ctx, a.ruleName) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON200, nil +} + +func (a *analyticsRule) Retrieve(ctx context.Context) (*api.AnalyticsRuleSchema, error) { + response, err := a.apiClient.RetrieveAnalyticsRuleWithResponse(ctx, a.ruleName) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON200, nil +} diff --git a/typesense/analytics_rule_test.go b/typesense/analytics_rule_test.go new file mode 100644 index 0000000..0a41738 --- /dev/null +++ b/typesense/analytics_rule_test.go @@ -0,0 +1,75 @@ +package typesense + +import ( + "context" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/typesense/typesense-go/v2/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api/pointer" +) + +func TestAnalyticsRuleRetrieve(t *testing.T) { + expectedData := &api.AnalyticsRuleSchema{ + Name: "test_rule", + Type: "test_type", + Params: api.AnalyticsRuleParameters{ + Limit: pointer.Int(10), + }, + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/analytics/rules/test_rule", http.MethodGet) + data := jsonEncode(t, expectedData) + + w.Header().Set("Content-Type", "application/json") + w.Write(data) + }) + defer server.Close() + + res, err := client.Analytics().Rule(expectedData.Name).Retrieve(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestAnalyticsRuleRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/analytics/rules/test_rule", http.MethodGet) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Analytics().Rule("test_rule").Retrieve(context.Background()) + assert.ErrorContains(t, err, "status: 409") +} + +func TestAnalyticsRuleDelete(t *testing.T) { + expectedData := &api.AnalyticsRuleDeleteResponse{ + Name: "test_rule", + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/analytics/rules/test_rule", http.MethodDelete) + data := jsonEncode(t, expectedData) + + w.Header().Set("Content-Type", "application/json") + w.Write(data) + }) + defer server.Close() + + res, err := client.Analytics().Rule("test_rule").Delete(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestAnalyticsRuleUpsertOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/analytics/rules/test_rule", http.MethodDelete) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Analytics().Rule("test_rule").Delete(context.Background()) + assert.ErrorContains(t, err, "status: 409") +} diff --git a/typesense/analytics_rules.go b/typesense/analytics_rules.go new file mode 100644 index 0000000..58c3d76 --- /dev/null +++ b/typesense/analytics_rules.go @@ -0,0 +1,39 @@ +package typesense + +import ( + "context" + + "github.com/typesense/typesense-go/v2/typesense/api" +) + +type AnalyticsRulesInterface interface { + Upsert(ctx context.Context, ruleName string, ruleSchema *api.AnalyticsRuleUpsertSchema) (*api.AnalyticsRuleSchema, error) + Retrieve(ctx context.Context) ([]*api.AnalyticsRuleSchema, error) +} + +type analyticsRules struct { + apiClient APIClientInterface +} + +func (a *analyticsRules) Upsert(ctx context.Context, ruleName string, ruleSchema *api.AnalyticsRuleUpsertSchema) (*api.AnalyticsRuleSchema, error) { + response, err := a.apiClient.UpsertAnalyticsRuleWithResponse(ctx, + ruleName, api.UpsertAnalyticsRuleJSONRequestBody(*ruleSchema)) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return response.JSON200, nil +} + +func (a *analyticsRules) Retrieve(ctx context.Context) ([]*api.AnalyticsRuleSchema, error) { + response, err := a.apiClient.RetrieveAnalyticsRulesWithResponse(ctx) + if err != nil { + return nil, err + } + if response.JSON200 == nil { + return nil, &HTTPError{Status: response.StatusCode(), Body: response.Body} + } + return *response.JSON200.Rules, nil +} diff --git a/typesense/analytics_rules_test.go b/typesense/analytics_rules_test.go new file mode 100644 index 0000000..28f7b96 --- /dev/null +++ b/typesense/analytics_rules_test.go @@ -0,0 +1,98 @@ +package typesense + +import ( + "context" + "encoding/json" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/typesense/typesense-go/v2/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api/pointer" +) + +func TestAnalyticsRulesRetrieve(t *testing.T) { + expectedData := []*api.AnalyticsRuleSchema{ + { + Name: "test_name", + Type: "test_type", + Params: api.AnalyticsRuleParameters{ + Limit: pointer.Int(10), + }, + }, + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/analytics/rules", http.MethodGet) + data := jsonEncode(t, api.AnalyticsRulesRetrieveSchema{ + Rules: &expectedData, + }) + w.Header().Set("Content-Type", "application/json") + w.Write(data) + }) + defer server.Close() + + res, err := client.Analytics().Rules().Retrieve(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestAnalyticsRulesRetrieveOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/analytics/rules", http.MethodGet) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Analytics().Rules().Retrieve(context.Background()) + assert.ErrorContains(t, err, "status: 409") +} + +func TestAnalyticsRulesUpsert(t *testing.T) { + upsertData := &api.AnalyticsRuleUpsertSchema{ + Type: api.AnalyticsRuleUpsertSchemaTypeCounter, + Params: api.AnalyticsRuleParameters{ + Limit: pointer.Int(100), + }, + } + expectedData := &api.AnalyticsRuleSchema{ + Name: "test-rule", + Type: api.AnalyticsRuleSchemaType(upsertData.Type), + Params: upsertData.Params, + } + + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/analytics/rules/test-rule", http.MethodPut) + + var reqBody api.AnalyticsRuleUpsertSchema + err := json.NewDecoder(r.Body).Decode(&reqBody) + + assert.NoError(t, err) + assert.Equal(t, *upsertData, reqBody) + + data := jsonEncode(t, api.AnalyticsRuleSchema{ + Name: expectedData.Name, + Type: api.AnalyticsRuleSchemaType(upsertData.Type), + Params: upsertData.Params, + }) + + w.Header().Set("Content-Type", "application/json") + w.Write(data) + }) + defer server.Close() + + res, err := client.Analytics().Rules().Upsert(context.Background(), expectedData.Name, upsertData) + assert.NoError(t, err) + assert.Equal(t, expectedData, res) +} + +func TestAnalyticsRulesUpsertOnHttpStatusErrorCodeReturnsError(t *testing.T) { + server, client := newTestServerAndClient(func(w http.ResponseWriter, r *http.Request) { + validateRequestMetadata(t, r, "/analytics/rules/test-rule", http.MethodPut) + w.WriteHeader(http.StatusConflict) + }) + defer server.Close() + + _, err := client.Analytics().Rules().Upsert(context.Background(), "test-rule", &api.AnalyticsRuleUpsertSchema{}) + assert.ErrorContains(t, err, "status: 409") +} diff --git a/typesense/client.go b/typesense/client.go index 2cf897a..9b35eff 100644 --- a/typesense/client.go +++ b/typesense/client.go @@ -44,6 +44,10 @@ func (c *Client) Alias(aliasName string) AliasInterface { return &alias{apiClient: c.apiClient, name: aliasName} } +func (c *Client) Analytics() AnalyticsInterface { + return &analytics{apiClient: c.apiClient} +} + func (c *Client) Conversations() ConversationsInterface { return &conversations{apiClient: c.apiClient} } diff --git a/typesense/test/analytics_events_test.go b/typesense/test/analytics_events_test.go new file mode 100644 index 0000000..2757338 --- /dev/null +++ b/typesense/test/analytics_events_test.go @@ -0,0 +1,31 @@ +//go:build integration +// +build integration + +package test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "github.com/typesense/typesense-go/v2/typesense/api" +) + +func TestAnalyticsEventsCreate(t *testing.T) { + eventName := newUUIDName("event") + collectionName := createNewCollection(t, "analytics-rules-collection") + createNewAnalyticsRule(t, collectionName, eventName) + + result, err := typesenseClient.Analytics().Events().Create(context.Background(), &api.AnalyticsEventCreateSchema{ + Type: "click", + Name: eventName, + Data: map[string]interface{}{ + "q": "nike shoes", + "doc_id": "1024", + "user_id": "111112", + }, + }) + + require.NoError(t, err) + require.True(t, result.Ok) +} diff --git a/typesense/test/analytics_rule_test.go b/typesense/test/analytics_rule_test.go new file mode 100644 index 0000000..b948012 --- /dev/null +++ b/typesense/test/analytics_rule_test.go @@ -0,0 +1,33 @@ +//go:build integration +// +build integration + +package test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestAnalyticsRuleRetrieve(t *testing.T) { + eventName := newUUIDName("event") + collectionName := createNewCollection(t, "analytics-rules-collection") + expectedRule := createNewAnalyticsRule(t, collectionName, eventName) + + result, err := typesenseClient.Analytics().Rule(expectedRule.Name).Retrieve(context.Background()) + + require.NoError(t, err) + require.Equal(t, expectedRule, result) +} + +func TestAnalyticsRuleDelete(t *testing.T) { + eventName := newUUIDName("event") + collectionName := createNewCollection(t, "analytics-rules-collection") + expectedRule := createNewAnalyticsRule(t, collectionName, eventName) + + result, err := typesenseClient.Analytics().Rule(expectedRule.Name).Delete(context.Background()) + + require.NoError(t, err) + require.Equal(t, expectedRule.Name, result.Name) +} diff --git a/typesense/test/analytics_rules_test.go b/typesense/test/analytics_rules_test.go new file mode 100644 index 0000000..6606b8d --- /dev/null +++ b/typesense/test/analytics_rules_test.go @@ -0,0 +1,47 @@ +//go:build integration +// +build integration + +package test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "github.com/typesense/typesense-go/v2/typesense/api" +) + +func TestAnalyticsRulesUpsert(t *testing.T) { + collectionName := createNewCollection(t, "analytics-rules-collection") + eventName := newUUIDName("event") + ruleSchema := newAnalyticsRuleUpsertSchema(collectionName, eventName) + ruleName := newUUIDName("test-rule") + expectedData := newAnalyticsRule(ruleName, collectionName, eventName) + + result, err := typesenseClient.Analytics().Rules().Upsert(context.Background(), ruleName, ruleSchema) + + require.NoError(t, err) + require.Equal(t, expectedData, result) +} + +func TestAnalyticsRulesRetrieve(t *testing.T) { + collectionName := createNewCollection(t, "analytics-rules-collection") + eventName := newUUIDName("event") + expectedRule := createNewAnalyticsRule(t, collectionName, eventName) + + results, err := typesenseClient.Analytics().Rules().Retrieve(context.Background()) + + require.NoError(t, err) + require.True(t, len(results) >= 1, "number of rules is invalid") + + var result *api.AnalyticsRuleSchema + for _, rule := range results { + if rule.Name == expectedRule.Name { + result = rule + break + } + } + + require.NotNil(t, result, "rule not found") + require.Equal(t, expectedRule, result) +} diff --git a/typesense/test/dbhelpers_test.go b/typesense/test/dbhelpers_test.go index 8fea813..ff695ee 100644 --- a/typesense/test/dbhelpers_test.go +++ b/typesense/test/dbhelpers_test.go @@ -187,17 +187,11 @@ func newKey() *api.ApiKey { type newSearchOverrideSchemaOption func(*api.SearchOverrideSchema) -func withOverrideRuleMatch(match api.SearchOverrideRuleMatch) newSearchOverrideSchemaOption { - return func(o *api.SearchOverrideSchema) { - o.Rule.Match = match - } -} - func newSearchOverrideSchema() *api.SearchOverrideSchema { schema := &api.SearchOverrideSchema{ Rule: api.SearchOverrideRule{ - Query: "apple", - Match: "exact", + Query: pointer.String("apple"), + Match: (*api.SearchOverrideRuleMatch)(pointer.String("exact")), }, Includes: &[]api.SearchOverrideInclude{ { @@ -224,8 +218,8 @@ func newSearchOverride(overrideID string) *api.SearchOverride { return &api.SearchOverride{ Id: pointer.String(overrideID), Rule: api.SearchOverrideRule{ - Query: "apple", - Match: "exact", + Query: pointer.String("apple"), + Match: (*api.SearchOverrideRuleMatch)(pointer.String("exact")), }, Includes: &[]api.SearchOverrideInclude{ { @@ -322,6 +316,53 @@ func newPresetFromMultiSearchSearchesParameter(presetName string) *api.PresetSch return preset } +func newAnalyticsRuleUpsertSchema(collectionName string, eventName string) *api.AnalyticsRuleUpsertSchema { + return &api.AnalyticsRuleUpsertSchema{ + Type: "counter", + Params: api.AnalyticsRuleParameters{ + Source: api.AnalyticsRuleParametersSource{ + Collections: []string{"products"}, + Events: &[]struct { + Name string "json:\"name\"" + Type string "json:\"type\"" + Weight float32 "json:\"weight\"" + }{ + {Type: "click", Weight: 1, Name: eventName}, + }, + }, + Destination: api.AnalyticsRuleParametersDestination{ + Collection: collectionName, + CounterField: pointer.String("num_employees"), + }, + Limit: pointer.Int(9999), + }, + } +} + +func newAnalyticsRule(ruleName string, collectionName string, eventName string) *api.AnalyticsRuleSchema { + return &api.AnalyticsRuleSchema{ + Name: ruleName, + Type: "counter", + Params: api.AnalyticsRuleParameters{ + Source: api.AnalyticsRuleParametersSource{ + Collections: []string{"products"}, + Events: &[]struct { + Name string "json:\"name\"" + Type string "json:\"type\"" + Weight float32 "json:\"weight\"" + }{ + {Type: "click", Weight: 1, Name: eventName}, + }, + }, + Destination: api.AnalyticsRuleParametersDestination{ + Collection: collectionName, + CounterField: pointer.String("num_employees"), + }, + Limit: pointer.Int(9999), + }, + } +} + func createNewCollection(t *testing.T, namePrefix string) string { t.Helper() collectionName := newUUIDName(namePrefix) @@ -363,6 +404,17 @@ func createNewPreset(t *testing.T, presetValueIsFromSearchParameters ...bool) (s return presetName, result } +func createNewAnalyticsRule(t *testing.T, collectionName string, eventName string) *api.AnalyticsRuleSchema { + t.Helper() + ruleSchema := newAnalyticsRuleUpsertSchema(collectionName, eventName) + ruleName := newUUIDName("test-rule") + + result, err := typesenseClient.Analytics().Rules().Upsert(context.Background(), ruleName, ruleSchema) + + require.NoError(t, err) + return result +} + func retrieveDocuments(t *testing.T, collectionName string, docIDs ...string) []map[string]interface{} { results := make([]map[string]interface{}, len(docIDs)) for i, docID := range docIDs { From ab589e85a3e85c145081995510f45388760ad6e1 Mon Sep 17 00:00:00 2001 From: Hayden Date: Thu, 26 Sep 2024 21:49:51 +0700 Subject: [PATCH 13/19] feat: allow configuration of dirty values behavior and export options [BREAKING CHANGE]: documents `Export` function signature - Added a new method: documents `Index` to avoid breaking changes in `Create` & `Upsert` function signatures --- typesense/api/client_gen.go | 8 +-- typesense/api/generator/generator.yml | 60 +++++++++------------- typesense/api/generator/openapi.yml | 56 ++++++++------------ typesense/api/pointer/pointer.go | 3 ++ typesense/api/types_gen.go | 74 ++++++++++----------------- typesense/documents.go | 21 ++++---- typesense/documents_test.go | 12 ++--- typesense/import_test.go | 40 +++++++-------- typesense/test/documents_test.go | 2 +- typesense/test/import_test.go | 4 +- typesense/test/multi_search_test.go | 8 +-- typesense/test/search_test.go | 10 ++-- 12 files changed, 130 insertions(+), 168 deletions(-) diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index 55a2c3d..76e46f7 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -2089,9 +2089,9 @@ func NewImportDocumentsRequestWithBody(server string, collectionName string, par } - if params.BatchSize != nil { + if params.DirtyValues != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "batch_size", runtime.ParamLocationQuery, *params.BatchSize); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "dirty_values", runtime.ParamLocationQuery, *params.DirtyValues); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -2105,9 +2105,9 @@ func NewImportDocumentsRequestWithBody(server string, collectionName string, par } - if params.DirtyValues != nil { + if params.BatchSize != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "dirty_values", runtime.ParamLocationQuery, *params.DirtyValues); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "batch_size", runtime.ParamLocationQuery, *params.BatchSize); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index 5a8e3c4..43da119 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -387,22 +387,17 @@ components: description: URL of vLLM service type: string type: object + DirtyValues: + enum: + - coerce_or_reject + - coerce_or_drop + - drop + - reject + type: string DocumentIndexParameters: properties: - action: - enum: - - create - - update - - upsert - - emplace - type: string dirty_values: - enum: - - coerce_or_reject - - coerce_or_drop - - drop - - reject - type: string + $ref: '#/components/schemas/DirtyValues' type: object ErrorResponse: properties: @@ -523,6 +518,13 @@ components: required: - ok type: object + IndexAction: + enum: + - create + - update + - upsert + - emplace + type: string MultiSearchCollectionParameters: allOf: - $ref: '#/components/schemas/MultiSearchParameters' @@ -1237,6 +1239,8 @@ components: found: description: The number of documents found type: integer + found_docs: + type: integer grouped_hits: items: $ref: '#/components/schemas/SearchGroupedHit' @@ -1965,20 +1969,14 @@ paths: in: query name: action schema: - enum: - - upsert + $ref: '#/components/schemas/IndexAction' example: upsert type: string - description: Dealing with Dirty Data in: query name: dirty_values schema: - enum: - - coerce_or_reject - - coerce_or_drop - - drop - - reject - type: string + $ref: '#/components/schemas/DirtyValues' requestBody: content: application/json: @@ -2171,25 +2169,15 @@ paths: - in: query name: action schema: - enum: - - create - - update - - upsert - - emplace - type: string + $ref: '#/components/schemas/IndexAction' - in: query - name: batch_size + name: dirty_values schema: - type: integer + $ref: '#/components/schemas/DirtyValues' - in: query - name: dirty_values + name: batch_size schema: - enum: - - coerce_or_reject - - coerce_or_drop - - drop - - reject - type: string + type: integer - in: query name: remote_embedding_batch_size schema: diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index aa92458..327632b 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -228,18 +228,12 @@ paths: schema: type: string example: upsert - enum: - - upsert + $ref: "#/components/schemas/IndexAction" - name: dirty_values in: query description: Dealing with Dirty Data schema: - type: string - enum: - - coerce_or_reject - - coerce_or_drop - - drop - - reject + $ref: "#/components/schemas/DirtyValues" requestBody: description: The document object to be indexed content: @@ -732,18 +726,12 @@ paths: required: true schema: type: string + # Do not change the index position of this param - name: importDocumentsParameters in: query schema: type: object properties: - action: - type: string - enum: - - create - - update - - upsert - - emplace batch_size: type: integer return_id: @@ -752,17 +740,18 @@ paths: Returning the id of the imported documents. If you want the import response to return the ingested document's id in the response, you can use the return_id parameter. - dirty_values: - type: string - enum: - - coerce_or_reject - - coerce_or_drop - - drop - - reject remote_embedding_batch_size: type: integer return_doc: type: boolean + - name: action + in: query + schema: + $ref: "#/components/schemas/IndexAction" + - name: dirty_values + in: query + schema: + $ref: "#/components/schemas/DirtyValues" requestBody: description: The json array of documents or the JSONL file to import content: @@ -1974,6 +1963,8 @@ components: found: type: integer description: The number of documents found + found_docs: + type: integer search_time_ms: type: integer description: The number of milliseconds the search took @@ -3385,23 +3376,18 @@ components: properties: name: type: string + # client libraries already have .create, .upsert,... methods so we omit the `action` param DocumentIndexParameters: type: object properties: - action: - type: string - enum: - - create - - update - - upsert - - emplace dirty_values: - type: string - enum: - - coerce_or_reject - - coerce_or_drop - - drop - - reject + $ref: "#/components/schemas/DirtyValues" + DirtyValues: + type: string + enum: [coerce_or_reject, coerce_or_drop, drop, reject] + IndexAction: + type: string + enum: [create, update, upsert, emplace] ConversationModelCreateSchema: required: - model_name diff --git a/typesense/api/pointer/pointer.go b/typesense/api/pointer/pointer.go index b53887c..54195a0 100644 --- a/typesense/api/pointer/pointer.go +++ b/typesense/api/pointer/pointer.go @@ -33,3 +33,6 @@ func Interface(v interface{}) *interface{} { func String(v string) *string { return &v } +func Any[T any](v T) *T { + return &v +} diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index 5d5c603..6d44e8a 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -27,39 +27,26 @@ const ( AnalyticsRuleUpsertSchemaTypePopularQueries AnalyticsRuleUpsertSchemaType = "popular_queries" ) -// Defines values for SearchOverrideRuleMatch. -const ( - Contains SearchOverrideRuleMatch = "contains" - Exact SearchOverrideRuleMatch = "exact" -) - -// Defines values for IndexDocumentParamsAction. -const ( - IndexDocumentParamsActionUpsert IndexDocumentParamsAction = "upsert" -) - -// Defines values for IndexDocumentParamsDirtyValues. +// Defines values for DirtyValues. const ( - IndexDocumentParamsDirtyValuesCoerceOrDrop IndexDocumentParamsDirtyValues = "coerce_or_drop" - IndexDocumentParamsDirtyValuesCoerceOrReject IndexDocumentParamsDirtyValues = "coerce_or_reject" - IndexDocumentParamsDirtyValuesDrop IndexDocumentParamsDirtyValues = "drop" - IndexDocumentParamsDirtyValuesReject IndexDocumentParamsDirtyValues = "reject" + CoerceOrDrop DirtyValues = "coerce_or_drop" + CoerceOrReject DirtyValues = "coerce_or_reject" + Drop DirtyValues = "drop" + Reject DirtyValues = "reject" ) -// Defines values for ImportDocumentsParamsAction. +// Defines values for IndexAction. const ( - ImportDocumentsParamsActionCreate ImportDocumentsParamsAction = "create" - ImportDocumentsParamsActionEmplace ImportDocumentsParamsAction = "emplace" - ImportDocumentsParamsActionUpdate ImportDocumentsParamsAction = "update" - ImportDocumentsParamsActionUpsert ImportDocumentsParamsAction = "upsert" + Create IndexAction = "create" + Emplace IndexAction = "emplace" + Update IndexAction = "update" + Upsert IndexAction = "upsert" ) -// Defines values for ImportDocumentsParamsDirtyValues. +// Defines values for SearchOverrideRuleMatch. const ( - ImportDocumentsParamsDirtyValuesCoerceOrDrop ImportDocumentsParamsDirtyValues = "coerce_or_drop" - ImportDocumentsParamsDirtyValuesCoerceOrReject ImportDocumentsParamsDirtyValues = "coerce_or_reject" - ImportDocumentsParamsDirtyValuesDrop ImportDocumentsParamsDirtyValues = "drop" - ImportDocumentsParamsDirtyValuesReject ImportDocumentsParamsDirtyValues = "reject" + Contains SearchOverrideRuleMatch = "contains" + Exact SearchOverrideRuleMatch = "exact" ) // APIStatsResponse defines model for APIStatsResponse. @@ -344,6 +331,9 @@ type ConversationModelUpdateSchema struct { VllmUrl *string `json:"vllm_url,omitempty"` } +// DirtyValues defines model for DirtyValues. +type DirtyValues string + // FacetCounts defines model for FacetCounts. type FacetCounts struct { Counts *[]struct { @@ -396,6 +386,9 @@ type HealthStatus struct { Ok bool `json:"ok"` } +// IndexAction defines model for IndexAction. +type IndexAction string + // MultiSearchCollectionParameters defines model for MultiSearchCollectionParameters. type MultiSearchCollectionParameters struct { // CacheTtl The duration (in seconds) that determines how long the search query is cached. This value can be set on a per-query basis. Default: 60. @@ -1131,6 +1124,7 @@ type SearchResult struct { // Found The number of documents found Found *int `json:"found,omitempty"` + FoundDocs *int `json:"found_docs,omitempty"` GroupedHits *[]SearchGroupedHit `json:"grouped_hits,omitempty"` // Hits The documents that matched the search query @@ -1275,18 +1269,12 @@ type IndexDocumentJSONBody = interface{} // IndexDocumentParams defines parameters for IndexDocument. type IndexDocumentParams struct { // Action Additional action to perform - Action *IndexDocumentParamsAction `form:"action,omitempty" json:"action,omitempty"` + Action *IndexAction `form:"action,omitempty" json:"action,omitempty"` // DirtyValues Dealing with Dirty Data - DirtyValues *IndexDocumentParamsDirtyValues `form:"dirty_values,omitempty" json:"dirty_values,omitempty"` + DirtyValues *DirtyValues `form:"dirty_values,omitempty" json:"dirty_values,omitempty"` } -// IndexDocumentParamsAction defines parameters for IndexDocument. -type IndexDocumentParamsAction string - -// IndexDocumentParamsDirtyValues defines parameters for IndexDocument. -type IndexDocumentParamsDirtyValues string - // ExportDocumentsParams defines parameters for ExportDocuments. type ExportDocumentsParams struct { ExcludeFields *string `form:"exclude_fields,omitempty" json:"exclude_fields,omitempty"` @@ -1296,20 +1284,14 @@ type ExportDocumentsParams struct { // ImportDocumentsParams defines parameters for ImportDocuments. type ImportDocumentsParams struct { - Action *ImportDocumentsParamsAction `form:"action,omitempty" json:"action,omitempty"` - BatchSize *int `form:"batch_size,omitempty" json:"batch_size,omitempty"` - DirtyValues *ImportDocumentsParamsDirtyValues `form:"dirty_values,omitempty" json:"dirty_values,omitempty"` - RemoteEmbeddingBatchSize *int `form:"remote_embedding_batch_size,omitempty" json:"remote_embedding_batch_size,omitempty"` - ReturnDoc *bool `form:"return_doc,omitempty" json:"return_doc,omitempty"` - ReturnId *bool `form:"return_id,omitempty" json:"return_id,omitempty"` + Action *IndexAction `form:"action,omitempty" json:"action,omitempty"` + DirtyValues *DirtyValues `form:"dirty_values,omitempty" json:"dirty_values,omitempty"` + BatchSize *int `form:"batch_size,omitempty" json:"batch_size,omitempty"` + RemoteEmbeddingBatchSize *int `form:"remote_embedding_batch_size,omitempty" json:"remote_embedding_batch_size,omitempty"` + ReturnDoc *bool `form:"return_doc,omitempty" json:"return_doc,omitempty"` + ReturnId *bool `form:"return_id,omitempty" json:"return_id,omitempty"` } -// ImportDocumentsParamsAction defines parameters for ImportDocuments. -type ImportDocumentsParamsAction string - -// ImportDocumentsParamsDirtyValues defines parameters for ImportDocuments. -type ImportDocumentsParamsDirtyValues string - // SearchCollectionParams defines parameters for SearchCollection. type SearchCollectionParams struct { CacheTtl *int `form:"cache_ttl,omitempty" json:"cache_ttl,omitempty"` diff --git a/typesense/documents.go b/typesense/documents.go index 9d8134e..3e057be 100644 --- a/typesense/documents.go +++ b/typesense/documents.go @@ -9,13 +9,11 @@ import ( "net/http" "github.com/typesense/typesense-go/v2/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api/pointer" ) -var upsertAction api.IndexDocumentParamsAction = "upsert" - const ( defaultImportBatchSize = 40 - defaultImportAction = "create" ) // DocumentsInterface is a type for Documents API operations @@ -31,7 +29,7 @@ type DocumentsInterface interface { // Search performs document search in collection Search(ctx context.Context, params *api.SearchCollectionParams) (*api.SearchResult, error) // Export returns all documents from index in jsonl format - Export(ctx context.Context) (io.ReadCloser, error) + Export(ctx context.Context, params *api.ExportDocumentsParams) (io.ReadCloser, error) // Import returns json array. Each item of the response indicates // the result of each document present in the request body (in the same order). Import(ctx context.Context, documents []interface{}, params *api.ImportDocumentsParams) ([]*api.ImportDocumentResponse, error) @@ -39,6 +37,8 @@ type DocumentsInterface interface { // response indicates the result of each document present in the // request body (in the same order). ImportJsonl(ctx context.Context, body io.Reader, params *api.ImportDocumentsParams) (io.ReadCloser, error) + // Index returns indexed document, this method allow configuration of dirty values behavior and action mode. Default action: create + Index(ctx context.Context, document interface{}, params *api.IndexDocumentParams) (map[string]interface{}, error) } // documents is internal implementation of DocumentsInterface @@ -59,6 +59,10 @@ func (d *documents) indexDocument(ctx context.Context, document interface{}, par return *response.JSON201, nil } +func (d *documents) Index(ctx context.Context, document interface{}, params *api.IndexDocumentParams) (map[string]interface{}, error) { + return d.indexDocument(ctx, document, params) +} + func (d *documents) Create(ctx context.Context, document interface{}) (map[string]interface{}, error) { return d.indexDocument(ctx, document, &api.IndexDocumentParams{}) } @@ -76,7 +80,7 @@ func (d *documents) Update(ctx context.Context, updateFields interface{}, params } func (d *documents) Upsert(ctx context.Context, document interface{}) (map[string]interface{}, error) { - return d.indexDocument(ctx, document, &api.IndexDocumentParams{Action: &upsertAction}) + return d.indexDocument(ctx, document, &api.IndexDocumentParams{Action: pointer.Any(api.Upsert)}) } func (d *documents) Delete(ctx context.Context, filter *api.DeleteDocumentsParams) (int, error) { @@ -103,8 +107,8 @@ func (d *documents) Search(ctx context.Context, params *api.SearchCollectionPara return response.JSON200, nil } -func (d *documents) Export(ctx context.Context) (io.ReadCloser, error) { - response, err := d.apiClient.ExportDocuments(ctx, d.collectionName, &api.ExportDocumentsParams{}) +func (d *documents) Export(ctx context.Context, params *api.ExportDocumentsParams) (io.ReadCloser, error) { + response, err := d.apiClient.ExportDocuments(ctx, d.collectionName, params) if err != nil { return nil, err } @@ -122,8 +126,7 @@ func initImportParams(params *api.ImportDocumentsParams) { *params.BatchSize = defaultImportBatchSize } if params.Action == nil { - params.Action = new(string) - *params.Action = defaultImportAction + params.Action = pointer.Any(api.Create) } } diff --git a/typesense/documents_test.go b/typesense/documents_test.go index e6a7075..08fc0a8 100644 --- a/typesense/documents_test.go +++ b/typesense/documents_test.go @@ -123,7 +123,7 @@ func TestDocumentUpsert(t *testing.T) { mockedResult := createNewDocumentResponse() notNill := gomock.Not(gomock.Nil()) - indexParams := &api.IndexDocumentParams{Action: &upsertAction} + indexParams := &api.IndexDocumentParams{Action: pointer.Any(api.Upsert)} mockAPIClient.EXPECT(). IndexDocumentWithResponse(notNill, "companies", indexParams, newDocument). Return(&api.IndexDocumentResponse{ @@ -146,7 +146,7 @@ func TestDocumentUpsertOnApiClientErrorReturnsError(t *testing.T) { mockAPIClient := mocks.NewMockAPIClientInterface(ctrl) notNill := gomock.Not(gomock.Nil()) - indexParams := &api.IndexDocumentParams{Action: &upsertAction} + indexParams := &api.IndexDocumentParams{Action: pointer.Any(api.Upsert)} mockAPIClient.EXPECT(). IndexDocumentWithResponse(notNill, "companies", indexParams, newDocument). Return(nil, errors.New("failed request")). @@ -165,7 +165,7 @@ func TestDocumentUpsertOnHttpStatusErrorCodeReturnsError(t *testing.T) { mockAPIClient := mocks.NewMockAPIClientInterface(ctrl) notNill := gomock.Not(gomock.Nil()) - indexParams := &api.IndexDocumentParams{Action: &upsertAction} + indexParams := &api.IndexDocumentParams{Action: pointer.Any(api.Upsert)} mockAPIClient.EXPECT(). IndexDocumentWithResponse(notNill, "companies", indexParams, newDocument). Return(&api.IndexDocumentResponse{ @@ -298,7 +298,7 @@ func TestDocumentsExport(t *testing.T) { Times(1) client := NewClient(WithAPIClient(mockAPIClient)) - result, err := client.Collection("companies").Documents().Export(context.Background()) + result, err := client.Collection("companies").Documents().Export(context.Background(), &api.ExportDocumentsParams{}) assert.Nil(t, err) resultBytes, err := ioutil.ReadAll(result) @@ -317,7 +317,7 @@ func TestDocumentsExportOnApiClientErrorReturnsError(t *testing.T) { Times(1) client := NewClient(WithAPIClient(mockAPIClient)) - _, err := client.Collection("companies").Documents().Export(context.Background()) + _, err := client.Collection("companies").Documents().Export(context.Background(), &api.ExportDocumentsParams{}) assert.NotNil(t, err) } @@ -335,7 +335,7 @@ func TestDocumentsExportOnHttpStatusErrorCodeReturnsError(t *testing.T) { Times(1) client := NewClient(WithAPIClient(mockAPIClient)) - _, err := client.Collection("companies").Documents().Export(context.Background()) + _, err := client.Collection("companies").Documents().Export(context.Background(), &api.ExportDocumentsParams{}) assert.NotNil(t, err) } diff --git a/typesense/import_test.go b/typesense/import_test.go index 0aaf30a..726011d 100644 --- a/typesense/import_test.go +++ b/typesense/import_test.go @@ -48,7 +48,7 @@ func (m *eqReaderMatcher) String() string { func TestDocumentsImportWithOneDocument(t *testing.T) { expectedParams := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } expectedBody := strings.NewReader(`{"id":"123","companyName":"Stark Industries","numEmployees":5215,"country":"USA"}` + "\n") @@ -75,7 +75,7 @@ func TestDocumentsImportWithOneDocument(t *testing.T) { createNewDocument(), } params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } result, err := client.Collection("companies").Documents().Import(context.Background(), documents, params) @@ -91,7 +91,7 @@ func TestDocumentsImportWithEmptyListReturnsError(t *testing.T) { client := NewClient(WithAPIClient(mockAPIClient)) params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } documents := []interface{}{} @@ -101,7 +101,7 @@ func TestDocumentsImportWithEmptyListReturnsError(t *testing.T) { func TestDocumentsImportWithOneDocumentAndInvalidResultJsonReturnsError(t *testing.T) { expectedParams := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } expectedBody := strings.NewReader(`{"id":"123","companyName":"Stark Industries","numEmployees":5215,"country":"USA"}` + "\n") @@ -125,7 +125,7 @@ func TestDocumentsImportWithOneDocumentAndInvalidResultJsonReturnsError(t *testi createNewDocument(), } params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } _, err := client.Collection("companies").Documents().Import(context.Background(), documents, params) @@ -139,7 +139,7 @@ func TestDocumentsImportWithInvalidInputDataReturnsError(t *testing.T) { client := NewClient(WithAPIClient(mockAPIClient)) params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } documents := []interface{}{ @@ -162,7 +162,7 @@ func TestDocumentsImportOnApiClientErrorReturnsError(t *testing.T) { client := NewClient(WithAPIClient(mockAPIClient)) params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } documents := []interface{}{ @@ -188,7 +188,7 @@ func TestDocumentsImportOnHttpStatusErrorCodeReturnsError(t *testing.T) { client := NewClient(WithAPIClient(mockAPIClient)) params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } documents := []interface{}{ @@ -200,7 +200,7 @@ func TestDocumentsImportOnHttpStatusErrorCodeReturnsError(t *testing.T) { func TestDocumentsImportWithTwoDocuments(t *testing.T) { expectedParams := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } expectedBody := strings.NewReader(`{"id":"123","companyName":"Stark Industries","numEmployees":5215,"country":"USA"}` + @@ -230,7 +230,7 @@ func TestDocumentsImportWithTwoDocuments(t *testing.T) { createNewDocument("125"), } params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } result, err := client.Collection("companies").Documents().Import(context.Background(), documents, params) @@ -241,7 +241,7 @@ func TestDocumentsImportWithTwoDocuments(t *testing.T) { func TestDocumentsImportWithActionOnly(t *testing.T) { expectedParams := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(defaultImportBatchSize), } @@ -263,7 +263,7 @@ func TestDocumentsImportWithActionOnly(t *testing.T) { createNewDocument(), } params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), } _, err := client.Collection("companies").Documents().Import(context.Background(), documents, params) assert.Nil(t, err) @@ -271,7 +271,7 @@ func TestDocumentsImportWithActionOnly(t *testing.T) { func TestDocumentsImportWithBatchSizeOnly(t *testing.T) { expectedParams := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(10), } @@ -302,7 +302,7 @@ func TestDocumentsImportWithBatchSizeOnly(t *testing.T) { func TestDocumentsImportJsonl(t *testing.T) { expectedBytes := []byte(`{"success": true}`) expectedParams := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } expectedBody := createDocumentStream() @@ -322,7 +322,7 @@ func TestDocumentsImportJsonl(t *testing.T) { client := NewClient(WithAPIClient(mockAPIClient)) params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } importBody := createDocumentStream() @@ -347,7 +347,7 @@ func TestDocumentsImportJsonlOnApiClientErrorReturnsError(t *testing.T) { client := NewClient(WithAPIClient(mockAPIClient)) params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } importBody := createDocumentStream() @@ -371,7 +371,7 @@ func TestDocumentsImportJsonlOnHttpStatusErrorCodeReturnsError(t *testing.T) { client := NewClient(WithAPIClient(mockAPIClient)) params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(40), } importBody := createDocumentStream() @@ -381,7 +381,7 @@ func TestDocumentsImportJsonlOnHttpStatusErrorCodeReturnsError(t *testing.T) { func TestDocumentsImportJsonlWithActionOnly(t *testing.T) { expectedParams := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(defaultImportBatchSize), } @@ -400,7 +400,7 @@ func TestDocumentsImportJsonlWithActionOnly(t *testing.T) { client := NewClient(WithAPIClient(mockAPIClient)) params := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), } importBody := createDocumentStream() _, err := client.Collection("companies").Documents().ImportJsonl(context.Background(), importBody, params) @@ -409,7 +409,7 @@ func TestDocumentsImportJsonlWithActionOnly(t *testing.T) { func TestDocumentsImportJsonlWithBatchSizeOnly(t *testing.T) { expectedParams := &api.ImportDocumentsParams{ - Action: pointer.String("create"), + Action: pointer.Any(api.Create), BatchSize: pointer.Int(10), } diff --git a/typesense/test/documents_test.go b/typesense/test/documents_test.go index f13769a..611f844 100644 --- a/typesense/test/documents_test.go +++ b/typesense/test/documents_test.go @@ -106,7 +106,7 @@ func TestDocumentsExport(t *testing.T) { createDocument(t, collectionName, newDocument("125", withCompanyName("Company2"))) createDocument(t, collectionName, newDocument("127", withCompanyName("Company3"))) - body, err := typesenseClient.Collection(collectionName).Documents().Export(context.Background()) + body, err := typesenseClient.Collection(collectionName).Documents().Export(context.Background(), &api.ExportDocumentsParams{}) require.NoError(t, err) defer body.Close() diff --git a/typesense/test/import_test.go b/typesense/test/import_test.go index 6ba8fe5..c30a21a 100644 --- a/typesense/test/import_test.go +++ b/typesense/test/import_test.go @@ -29,7 +29,7 @@ func TestDocumentsImport(t *testing.T) { newDocument("127", withCompanyName("Company3")), } - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} responses, err := typesenseClient.Collection(collectionName).Documents().Import(context.Background(), documents, params) require.NoError(t, err) @@ -58,7 +58,7 @@ func TestDocumentsImportJsonl(t *testing.T) { require.NoError(t, buffer.WriteByte('\n')) require.NoError(t, je.Encode(newDocument("127", withCompanyName("Company3")))) - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} responses, err := typesenseClient.Collection(collectionName).Documents().ImportJsonl(context.Background(), &buffer, params) require.NoError(t, err) diff --git a/typesense/test/multi_search_test.go b/typesense/test/multi_search_test.go index bfda00f..5daa4d7 100644 --- a/typesense/test/multi_search_test.go +++ b/typesense/test/multi_search_test.go @@ -23,7 +23,7 @@ func TestMultiSearch(t *testing.T) { newDocument("131", withCompanyName("Stark Industries 5"), withNumEmployees(1000)), } - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} _, err := typesenseClient.Collection(collectionName1).Documents().Import(context.Background(), documents, params) require.NoError(t, err) @@ -95,7 +95,7 @@ func TestMultiSearchGroupBy(t *testing.T) { newDocument("3", withCompanyName("Company 4"), withNumEmployees(500), withCountry("England")), } - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} _, err := typesenseClient.Collection(collectionName1).Documents().Import(context.Background(), documents, params) require.NoError(t, err) @@ -207,7 +207,7 @@ func TestMultiSearchWithPreset(t *testing.T) { newDocument("131", withCompanyName("Stark Industries 5"), withNumEmployees(1000)), } - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} _, err := typesenseClient.Collection(collectionName1).Documents().Import(context.Background(), documents, params) require.NoError(t, err) @@ -288,7 +288,7 @@ func TestMultiSearchWithStopwords(t *testing.T) { newDocument("129", withCompanyName("Stark Industries 4"), withNumEmployees(1500)), } - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} _, err := typesenseClient.Collection(collectionName1).Documents().Import(context.Background(), documents, params) require.NoError(t, err) diff --git a/typesense/test/search_test.go b/typesense/test/search_test.go index 4578105..1c13d33 100644 --- a/typesense/test/search_test.go +++ b/typesense/test/search_test.go @@ -22,7 +22,7 @@ func TestCollectionSearch(t *testing.T) { newDocument("131", withCompanyName("Stark Industries 5"), withNumEmployees(1000)), } - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} _, err := typesenseClient.Collection(collectionName).Documents().Import(context.Background(), documents, params) require.NoError(t, err) @@ -67,7 +67,7 @@ func TestCollectionSearchRange(t *testing.T) { newDocument("129", withCompanyName("Stark Industries 4"), withNumEmployees(500)), } - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} _, err := typesenseClient.Collection(collectionName).Documents().Import(context.Background(), documents, params) require.NoError(t, err) @@ -131,7 +131,7 @@ func TestCollectionGroupByStringArray(t *testing.T) { }, } - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} _, err = typesenseClient.Collection(collectionName).Documents().Import(context.Background(), documents, params) require.NoError(t, err) @@ -160,7 +160,7 @@ func TestCollectionSearchWithPreset(t *testing.T) { newDocument("131", withCompanyName("Stark Industries 5"), withNumEmployees(1000)), } - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} _, err := typesenseClient.Collection(collectionName).Documents().Import(context.Background(), documents, params) require.NoError(t, err) @@ -214,7 +214,7 @@ func TestCollectionSearchWithStopwords(t *testing.T) { newDocument("129", withCompanyName("Stark Industries 4"), withNumEmployees(2000)), } - params := &api.ImportDocumentsParams{Action: pointer.String("create")} + params := &api.ImportDocumentsParams{Action: pointer.Any(api.Create)} _, err := typesenseClient.Collection(collectionName).Documents().Import(context.Background(), documents, params) require.NoError(t, err) From 412393ee16bb6c88b3846c182f84bb5831e2447f Mon Sep 17 00:00:00 2001 From: Hayden Date: Sun, 29 Sep 2024 20:16:46 +0700 Subject: [PATCH 14/19] use typesense v27.0 & update integration test --- .github/workflows/tests.yml | 2 +- typesense/api/pointer/pointer.go | 1 + typesense/overrides_test.go | 4 ++-- typesense/test/dbhelpers_test.go | 11 +++++++++-- typesense/test/overrides_test.go | 7 ++++--- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 460f0e7..b8847b1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest services: typesense: - image: typesense/typesense:26.0 + image: typesense/typesense:27.0 ports: - 8108:8108/tcp volumes: diff --git a/typesense/api/pointer/pointer.go b/typesense/api/pointer/pointer.go index 54195a0..d6feb14 100644 --- a/typesense/api/pointer/pointer.go +++ b/typesense/api/pointer/pointer.go @@ -33,6 +33,7 @@ func Interface(v interface{}) *interface{} { func String(v string) *string { return &v } + func Any[T any](v T) *T { return &v } diff --git a/typesense/overrides_test.go b/typesense/overrides_test.go index 3278fb1..14318a0 100644 --- a/typesense/overrides_test.go +++ b/typesense/overrides_test.go @@ -18,8 +18,8 @@ import ( func createNewSearchOverrideSchema() *api.SearchOverrideSchema { return &api.SearchOverrideSchema{ Rule: api.SearchOverrideRule{ - Query: "apple", - Match: "exact", + Query: pointer.String("apple"), + Match: pointer.Any(api.Exact), }, Includes: &[]api.SearchOverrideInclude{ { diff --git a/typesense/test/dbhelpers_test.go b/typesense/test/dbhelpers_test.go index ff695ee..e59b3f5 100644 --- a/typesense/test/dbhelpers_test.go +++ b/typesense/test/dbhelpers_test.go @@ -56,6 +56,7 @@ func expectedNewCollection(name string) *api.CollectionResponse { Locale: pointer.String(""), Sort: pointer.False(), Drop: nil, + Store: pointer.True(), }, { Name: "num_employees", @@ -67,6 +68,7 @@ func expectedNewCollection(name string) *api.CollectionResponse { Locale: pointer.String(""), Sort: pointer.True(), Drop: nil, + Store: pointer.True(), }, { Name: "country", @@ -78,6 +80,7 @@ func expectedNewCollection(name string) *api.CollectionResponse { Locale: pointer.String(""), Sort: pointer.False(), Drop: nil, + Store: pointer.True(), }, }, EnableNestedFields: pointer.False(), @@ -191,7 +194,7 @@ func newSearchOverrideSchema() *api.SearchOverrideSchema { schema := &api.SearchOverrideSchema{ Rule: api.SearchOverrideRule{ Query: pointer.String("apple"), - Match: (*api.SearchOverrideRuleMatch)(pointer.String("exact")), + Match: pointer.Any(api.Exact), }, Includes: &[]api.SearchOverrideInclude{ { @@ -209,6 +212,8 @@ func newSearchOverrideSchema() *api.SearchOverrideSchema { }, }, RemoveMatchedTokens: pointer.True(), + FilterCuratedHits: pointer.False(), + StopProcessing: pointer.True(), } return schema @@ -219,7 +224,7 @@ func newSearchOverride(overrideID string) *api.SearchOverride { Id: pointer.String(overrideID), Rule: api.SearchOverrideRule{ Query: pointer.String("apple"), - Match: (*api.SearchOverrideRuleMatch)(pointer.String("exact")), + Match: pointer.Any(api.Exact), }, Includes: &[]api.SearchOverrideInclude{ { @@ -237,6 +242,8 @@ func newSearchOverride(overrideID string) *api.SearchOverride { }, }, RemoveMatchedTokens: pointer.True(), + FilterCuratedHits: pointer.False(), + StopProcessing: pointer.True(), } } diff --git a/typesense/test/overrides_test.go b/typesense/test/overrides_test.go index 14e6abf..54cb7a0 100644 --- a/typesense/test/overrides_test.go +++ b/typesense/test/overrides_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/typesense/typesense-go/v2/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api/pointer" ) func TestSearchOverrideUpsertNewOverride(t *testing.T) { @@ -33,14 +34,14 @@ func TestSearchOverrideUpsertExistingOverride(t *testing.T) { collectionName := createNewCollection(t, "companies") overrideID := newUUIDName("customize-apple") expectedResult := newSearchOverride(overrideID) - expectedResult.Rule.Match = "contains" + expectedResult.Rule.Match = pointer.Any(api.Contains) body := newSearchOverrideSchema() - body.Rule.Match = "exact" + body.Rule.Match = pointer.Any(api.Exact) _, err := typesenseClient.Collection(collectionName).Overrides().Upsert(context.Background(), overrideID, body) require.NoError(t, err) - body.Rule.Match = "contains" + body.Rule.Match = pointer.Any(api.Contains) result, err := typesenseClient.Collection(collectionName).Overrides().Upsert(context.Background(), overrideID, body) From d9cc0653ee246fe10d6324ca77b1979c27a1b5d0 Mon Sep 17 00:00:00 2001 From: Hayden Date: Mon, 30 Sep 2024 20:52:15 +0700 Subject: [PATCH 15/19] pull openapi changes --- typesense/api/client_gen.go | 192 ++++++++++++++ typesense/api/generator/generator.yml | 117 ++++++++- typesense/api/generator/main.go | 25 +- typesense/api/generator/openapi.yml | 71 +++++- typesense/api/types_gen.go | 343 ++++++++++++++++---------- 5 files changed, 608 insertions(+), 140 deletions(-) diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index 76e46f7..ac57a69 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -2275,6 +2275,22 @@ func NewSearchCollectionRequest(server string, collectionName string, params *Se } + if params.DropTokensMode != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "drop_tokens_mode", runtime.ParamLocationQuery, *params.DropTokensMode); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.DropTokensThreshold != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "drop_tokens_threshold", runtime.ParamLocationQuery, *params.DropTokensThreshold); err != nil { @@ -2323,6 +2339,38 @@ func NewSearchCollectionRequest(server string, collectionName string, params *Se } + if params.EnableSynonyms != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "enable_synonyms", runtime.ParamLocationQuery, *params.EnableSynonyms); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.EnableTyposForAlphaNumericalTokens != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "enable_typos_for_alpha_numerical_tokens", runtime.ParamLocationQuery, *params.EnableTyposForAlphaNumericalTokens); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.EnableTyposForNumericalTokens != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "enable_typos_for_numerical_tokens", runtime.ParamLocationQuery, *params.EnableTyposForNumericalTokens); err != nil { @@ -2451,6 +2499,22 @@ func NewSearchCollectionRequest(server string, collectionName string, params *Se } + if params.FilterCuratedHits != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "filter_curated_hits", runtime.ParamLocationQuery, *params.FilterCuratedHits); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.GroupBy != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "group_by", runtime.ParamLocationQuery, *params.GroupBy); err != nil { @@ -3091,6 +3155,38 @@ func NewSearchCollectionRequest(server string, collectionName string, params *Se } + if params.SynonymNumTypos != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "synonym_num_typos", runtime.ParamLocationQuery, *params.SynonymNumTypos); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.SynonymPrefix != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "synonym_prefix", runtime.ParamLocationQuery, *params.SynonymPrefix); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.TextMatchType != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "text_match_type", runtime.ParamLocationQuery, *params.TextMatchType); err != nil { @@ -4153,6 +4249,22 @@ func NewMultiSearchRequestWithBody(server string, params *MultiSearchParams, con } + if params.DropTokensMode != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "drop_tokens_mode", runtime.ParamLocationQuery, *params.DropTokensMode); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.DropTokensThreshold != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "drop_tokens_threshold", runtime.ParamLocationQuery, *params.DropTokensThreshold); err != nil { @@ -4201,6 +4313,38 @@ func NewMultiSearchRequestWithBody(server string, params *MultiSearchParams, con } + if params.EnableSynonyms != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "enable_synonyms", runtime.ParamLocationQuery, *params.EnableSynonyms); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.EnableTyposForAlphaNumericalTokens != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "enable_typos_for_alpha_numerical_tokens", runtime.ParamLocationQuery, *params.EnableTyposForAlphaNumericalTokens); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.EnableTyposForNumericalTokens != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "enable_typos_for_numerical_tokens", runtime.ParamLocationQuery, *params.EnableTyposForNumericalTokens); err != nil { @@ -4329,6 +4473,22 @@ func NewMultiSearchRequestWithBody(server string, params *MultiSearchParams, con } + if params.FilterCuratedHits != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "filter_curated_hits", runtime.ParamLocationQuery, *params.FilterCuratedHits); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.GroupBy != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "group_by", runtime.ParamLocationQuery, *params.GroupBy); err != nil { @@ -4969,6 +5129,38 @@ func NewMultiSearchRequestWithBody(server string, params *MultiSearchParams, con } + if params.SynonymNumTypos != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "synonym_num_typos", runtime.ParamLocationQuery, *params.SynonymNumTypos); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.SynonymPrefix != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "synonym_prefix", runtime.ParamLocationQuery, *params.SynonymPrefix); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.TextMatchType != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "text_match_type", runtime.ParamLocationQuery, *params.TextMatchType); err != nil { diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index 43da119..72feaf2 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -399,6 +399,14 @@ components: dirty_values: $ref: '#/components/schemas/DirtyValues' type: object + DropTokensMode: + description: | + Dictates the direction in which the words in the query must be dropped when the original words in the query do not appear in any document. Values: right_to_left (default), left_to_right, both_sides:3 A note on both_sides:3 - for queries upto 3 tokens (words) in length, this mode will drop tokens from both sides and exhaustively rank all matching results. If query length is greater than 3 words, Typesense will just fallback to default behavior of right_to_left + enum: + - right_to_left + - left_to_right + - both_sides:3 + type: string ErrorResponse: properties: message: @@ -494,19 +502,32 @@ components: optional: example: true type: boolean + range_index: + description: | + Enables an index optimized for range filtering on numerical fields (e.g. rating:>3.5). Default: false. + type: boolean reference: - example: string + description: | + Name of a field in another collection that should be linked to this collection so that it can be joined during query. type: string sort: example: true type: boolean + stem: + description: | + Values are stemmed before indexing in-memory. Default: false. + type: boolean store: description: | - Whether to store the image on disk. + When set to false, the field value will not be stored on disk. Default: true. type: boolean type: example: string type: string + vec_dist: + description: | + The distance metric to be used for vector search. Default: `cosine`. You can also use `ip` for inner product. + type: string required: - name - type @@ -556,6 +577,8 @@ components: description: | The Id of Conversation Model to be used. type: string + drop_tokens_mode: + $ref: '#/components/schemas/DropTokensMode' drop_tokens_threshold: description: | If the number of results found for a specific query is less than this number, Typesense will attempt to drop the tokens in the query until enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 @@ -565,6 +588,14 @@ components: description: | If you have some overrides defined but want to disable all of them during query time, you can do that by setting this parameter to false type: boolean + enable_synonyms: + description: | + If you have some synonyms defined but want to disable all of them for a particular search query, set enable_synonyms to false. Default: true + type: boolean + enable_typos_for_alpha_numerical_tokens: + description: | + Set this parameter to false to disable typos on alphanumerical query tokens. Default: true. + type: boolean enable_typos_for_numerical_tokens: default: true description: | @@ -595,6 +626,10 @@ components: description: Filter conditions for refining youropen api validator search results. Separate multiple conditions with &&. example: 'num_employees:>100 && country: [USA, UK]' type: string + filter_curated_hits: + description: | + Whether the filter_by condition of the search query should be applicable to curated results (override definitions, pinned hits, hidden hits, etc.). Default: false + type: boolean group_by: description: You can aggregate search results into groups or buckets by specify one or more `group_by` fields. Separate multiple fields with a comma. To group on a particular field, it must be a faceted field. type: string @@ -738,6 +773,14 @@ components: description: | Name of the stopwords set to apply for this search, the keywords present in the set will be removed from the search query. type: string + synonym_num_typos: + description: | + Allow synonym resolution on typo-corrected words in the query. Default: 0 + type: integer + synonym_prefix: + description: | + Allow synonym resolution on word prefixes in the query. Default: false + type: boolean text_match_type: description: In a multi-field matching context, this parameter determines how the representative text match score of a record is calculated. Possible values are max_score (default) or max_weight. type: string @@ -1010,6 +1053,8 @@ components: description: | The Id of Conversation Model to be used. type: string + drop_tokens_mode: + $ref: '#/components/schemas/DropTokensMode' drop_tokens_threshold: description: | If the number of results found for a specific query is less than this number, Typesense will attempt to drop the tokens in the query until enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 @@ -1024,6 +1069,14 @@ components: description: | If you have some overrides defined but want to disable all of them during query time, you can do that by setting this parameter to false type: boolean + enable_synonyms: + description: | + If you have some synonyms defined but want to disable all of them for a particular search query, set enable_synonyms to false. Default: true + type: boolean + enable_typos_for_alpha_numerical_tokens: + description: | + Set this parameter to false to disable typos on alphanumerical query tokens. Default: true. + type: boolean enable_typos_for_numerical_tokens: default: true description: | @@ -1054,6 +1107,10 @@ components: description: Filter conditions for refining youropen api validator search results. Separate multiple conditions with &&. example: 'num_employees:>100 && country: [USA, UK]' type: string + filter_curated_hits: + description: | + Whether the filter_by condition of the search query should be applicable to curated results (override definitions, pinned hits, hidden hits, etc.). Default: false + type: boolean group_by: description: You can aggregate search results into groups or buckets by specify one or more `group_by` fields. Separate multiple fields with a comma. To group on a particular field, it must be a faceted field. type: string @@ -1205,6 +1262,14 @@ components: description: | Name of the stopwords set to apply for this search, the keywords present in the set will be removed from the search query. type: string + synonym_num_typos: + description: | + Allow synonym resolution on typo-corrected words in the query. Default: 0 + type: integer + synonym_prefix: + description: | + Allow synonym resolution on word prefixes in the query. Default: false + type: boolean text_match_type: description: In a multi-field matching context, this parameter determines how the representative text match score of a record is calculated. Possible values are max_score (default) or max_weight. type: string @@ -2250,6 +2315,10 @@ paths: name: conversation_model_id schema: type: string + - in: query + name: drop_tokens_mode + schema: + $ref: '#/components/schemas/DropTokensMode' - in: query name: drop_tokens_threshold schema: @@ -2262,6 +2331,14 @@ paths: name: enable_overrides schema: type: boolean + - in: query + name: enable_synonyms + schema: + type: boolean + - in: query + name: enable_typos_for_alpha_numerical_tokens + schema: + type: boolean - in: query name: enable_typos_for_numerical_tokens schema: @@ -2294,6 +2371,10 @@ paths: name: filter_by schema: type: string + - in: query + name: filter_curated_hits + schema: + type: boolean - in: query name: group_by schema: @@ -2454,6 +2535,14 @@ paths: name: stopwords schema: type: string + - in: query + name: synonym_num_typos + schema: + type: integer + - in: query + name: synonym_prefix + schema: + type: boolean - in: query name: text_match_type schema: @@ -3024,6 +3113,10 @@ paths: name: conversation_model_id schema: type: string + - in: query + name: drop_tokens_mode + schema: + $ref: '#/components/schemas/DropTokensMode' - in: query name: drop_tokens_threshold schema: @@ -3036,6 +3129,14 @@ paths: name: enable_overrides schema: type: boolean + - in: query + name: enable_synonyms + schema: + type: boolean + - in: query + name: enable_typos_for_alpha_numerical_tokens + schema: + type: boolean - in: query name: enable_typos_for_numerical_tokens schema: @@ -3068,6 +3169,10 @@ paths: name: filter_by schema: type: string + - in: query + name: filter_curated_hits + schema: + type: boolean - in: query name: group_by schema: @@ -3228,6 +3333,14 @@ paths: name: stopwords schema: type: string + - in: query + name: synonym_num_typos + schema: + type: integer + - in: query + name: synonym_prefix + schema: + type: boolean - in: query name: text_match_type schema: diff --git a/typesense/api/generator/main.go b/typesense/api/generator/main.go index d932b09..26e856b 100644 --- a/typesense/api/generator/main.go +++ b/typesense/api/generator/main.go @@ -215,11 +215,16 @@ func unwrapSearchParameters(m *yml) { newMap["in"] = query newMap["schema"] = make(yml) if obj.Value.(yml)["oneOf"] == nil { - if obj.Value.(yml)["type"].(string) == array { - newMap["schema"].(yml)["type"] = array - newMap["schema"].(yml)["items"] = obj.Value.(yml)["items"] + // if the param is referencing a schema + if obj.Value.(yml)["type"] == nil { + newMap["schema"].(yml)["$ref"] = obj.Value.(yml)["$ref"].(string) } else { - newMap["schema"].(yml)["type"] = obj.Value.(yml)["type"].(string) + if obj.Value.(yml)["type"].(string) == array { + newMap["schema"].(yml)["type"] = array + newMap["schema"].(yml)["items"] = obj.Value.(yml)["items"] + } else { + newMap["schema"].(yml)["type"] = obj.Value.(yml)["type"].(string) + } } } else { newMap["schema"].(yml)["oneOf"] = obj.Value.(yml)["oneOf"] @@ -241,11 +246,15 @@ func unwrapMultiSearchParameters(m *yml) { newMap["in"] = query newMap["schema"] = make(yml) if obj.Value.(yml)["oneOf"] == nil { - if obj.Value.(yml)["type"].(string) == array { - newMap["schema"].(yml)["type"] = array - newMap["schema"].(yml)["items"] = obj.Value.(yml)["items"] + if obj.Value.(yml)["type"] == nil { + newMap["schema"].(yml)["$ref"] = obj.Value.(yml)["$ref"].(string) } else { - newMap["schema"].(yml)["type"] = obj.Value.(yml)["type"].(string) + if obj.Value.(yml)["type"].(string) == array { + newMap["schema"].(yml)["type"] = array + newMap["schema"].(yml)["items"] = obj.Value.(yml)["items"] + } else { + newMap["schema"].(yml)["type"] = obj.Value.(yml)["type"].(string) + } } } else { newMap["schema"].(yml)["oneOf"] = obj.Value.(yml)["oneOf"] diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index 327632b..622fa7c 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -1875,7 +1875,8 @@ components: default: false reference: type: string - example: string + description: > + Name of a field in another collection that should be linked to this collection so that it can be joined during query. num_dim: type: integer example: 256 @@ -1886,7 +1887,19 @@ components: store: type: boolean description: > - Whether to store the image on disk. + When set to false, the field value will not be stored on disk. Default: true. + vec_dist: + type: string + description: > + The distance metric to be used for vector search. Default: `cosine`. You can also use `ip` for inner product. + range_index: + type: boolean + description: > + Enables an index optimized for range filtering on numerical fields (e.g. rating:>3.5). Default: false. + stem: + type: boolean + description: > + Values are stemmed before indexing in-memory. Default: false. embed: type: object required: @@ -2574,12 +2587,35 @@ components: enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 type: integer + drop_tokens_mode: + $ref: "#/components/schemas/DropTokensMode" typo_tokens_threshold: description: > If the number of results found for a specific query is less than this number, Typesense will attempt to look for tokens with more typos until enough results are found. Default: 100 type: integer + enable_typos_for_alpha_numerical_tokens: + type: boolean + description: > + Set this parameter to false to disable typos on alphanumerical query tokens. Default: true. + + filter_curated_hits: + type: boolean + description: > + Whether the filter_by condition of the search query should be applicable to curated results (override definitions, pinned hits, hidden hits, etc.). Default: false + enable_synonyms: + type: boolean + description: > + If you have some synonyms defined but want to disable all of them for a particular search query, set enable_synonyms to false. Default: true + synonym_prefix: + type: boolean + description: > + Allow synonym resolution on word prefixes in the query. Default: false + synonym_num_typos: + type: integer + description: > + Allow synonym resolution on typo-corrected words in the query. Default: 0 pinned_hits: description: > @@ -2928,12 +2964,35 @@ components: enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 type: integer + drop_tokens_mode: + $ref: "#/components/schemas/DropTokensMode" typo_tokens_threshold: description: > If the number of results found for a specific query is less than this number, Typesense will attempt to look for tokens with more typos until enough results are found. Default: 100 type: integer + enable_typos_for_alpha_numerical_tokens: + type: boolean + description: > + Set this parameter to false to disable typos on alphanumerical query tokens. Default: true. + + filter_curated_hits: + type: boolean + description: > + Whether the filter_by condition of the search query should be applicable to curated results (override definitions, pinned hits, hidden hits, etc.). Default: false + enable_synonyms: + type: boolean + description: > + If you have some synonyms defined but want to disable all of them for a particular search query, set enable_synonyms to false. Default: true + synonym_prefix: + type: boolean + description: > + Allow synonym resolution on word prefixes in the query. Default: false + synonym_num_typos: + type: integer + description: > + Allow synonym resolution on typo-corrected words in the query. Default: 0 pinned_hits: description: > @@ -3388,6 +3447,14 @@ components: IndexAction: type: string enum: [create, update, upsert, emplace] + DropTokensMode: + type: string + enum: [right_to_left, left_to_right, both_sides:3] + description: > + Dictates the direction in which the words in the query must be dropped when the original words in the query do not appear in any document. + Values: right_to_left (default), left_to_right, both_sides:3 + A note on both_sides:3 - for queries upto 3 tokens (words) in length, this mode will drop tokens from both sides and exhaustively rank all matching results. + If query length is greater than 3 words, Typesense will just fallback to default behavior of right_to_left ConversationModelCreateSchema: required: - model_name diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index 6d44e8a..e9a8da1 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -35,6 +35,13 @@ const ( Reject DirtyValues = "reject" ) +// Defines values for DropTokensMode. +const ( + BothSides3 DropTokensMode = "both_sides:3" + LeftToRight DropTokensMode = "left_to_right" + RightToLeft DropTokensMode = "right_to_left" +) + // Defines values for IndexAction. const ( Create IndexAction = "create" @@ -334,6 +341,9 @@ type ConversationModelUpdateSchema struct { // DirtyValues defines model for DirtyValues. type DirtyValues string +// DropTokensMode Dictates the direction in which the words in the query must be dropped when the original words in the query do not appear in any document. Values: right_to_left (default), left_to_right, both_sides:3 A note on both_sides:3 - for queries upto 3 tokens (words) in length, this mode will drop tokens from both sides and exhaustively rank all matching results. If query length is greater than 3 words, Typesense will just fallback to default behavior of right_to_left +type DropTokensMode string + // FacetCounts defines model for FacetCounts. type FacetCounts struct { Counts *[]struct { @@ -366,19 +376,30 @@ type Field struct { ProjectId *string `json:"project_id,omitempty"` } `json:"model_config"` } `json:"embed,omitempty"` - Facet *bool `json:"facet,omitempty"` - Index *bool `json:"index,omitempty"` - Infix *bool `json:"infix,omitempty"` - Locale *string `json:"locale,omitempty"` - Name string `json:"name"` - NumDim *int `json:"num_dim,omitempty"` - Optional *bool `json:"optional,omitempty"` + Facet *bool `json:"facet,omitempty"` + Index *bool `json:"index,omitempty"` + Infix *bool `json:"infix,omitempty"` + Locale *string `json:"locale,omitempty"` + Name string `json:"name"` + NumDim *int `json:"num_dim,omitempty"` + Optional *bool `json:"optional,omitempty"` + + // RangeIndex Enables an index optimized for range filtering on numerical fields (e.g. rating:>3.5). Default: false. + RangeIndex *bool `json:"range_index,omitempty"` + + // Reference Name of a field in another collection that should be linked to this collection so that it can be joined during query. Reference *string `json:"reference,omitempty"` Sort *bool `json:"sort,omitempty"` - // Store Whether to store the image on disk. + // Stem Values are stemmed before indexing in-memory. Default: false. + Stem *bool `json:"stem,omitempty"` + + // Store When set to false, the field value will not be stored on disk. Default: true. Store *bool `json:"store,omitempty"` Type string `json:"type"` + + // VecDist The distance metric to be used for vector search. Default: `cosine`. You can also use `ip` for inner product. + VecDist *string `json:"vec_dist,omitempty"` } // HealthStatus defines model for HealthStatus. @@ -406,12 +427,21 @@ type MultiSearchCollectionParameters struct { // ConversationModelId The Id of Conversation Model to be used. ConversationModelId *string `json:"conversation_model_id,omitempty"` + // DropTokensMode Dictates the direction in which the words in the query must be dropped when the original words in the query do not appear in any document. Values: right_to_left (default), left_to_right, both_sides:3 A note on both_sides:3 - for queries upto 3 tokens (words) in length, this mode will drop tokens from both sides and exhaustively rank all matching results. If query length is greater than 3 words, Typesense will just fallback to default behavior of right_to_left + DropTokensMode *DropTokensMode `json:"drop_tokens_mode,omitempty"` + // DropTokensThreshold If the number of results found for a specific query is less than this number, Typesense will attempt to drop the tokens in the query until enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 DropTokensThreshold *int `json:"drop_tokens_threshold,omitempty"` // EnableOverrides If you have some overrides defined but want to disable all of them during query time, you can do that by setting this parameter to false EnableOverrides *bool `json:"enable_overrides,omitempty"` + // EnableSynonyms If you have some synonyms defined but want to disable all of them for a particular search query, set enable_synonyms to false. Default: true + EnableSynonyms *bool `json:"enable_synonyms,omitempty"` + + // EnableTyposForAlphaNumericalTokens Set this parameter to false to disable typos on alphanumerical query tokens. Default: true. + EnableTyposForAlphaNumericalTokens *bool `json:"enable_typos_for_alpha_numerical_tokens,omitempty"` + // EnableTyposForNumericalTokens Make Typesense disable typos for numerical tokens. EnableTyposForNumericalTokens *bool `json:"enable_typos_for_numerical_tokens,omitempty"` @@ -436,6 +466,9 @@ type MultiSearchCollectionParameters struct { // FilterBy Filter conditions for refining youropen api validator search results. Separate multiple conditions with &&. FilterBy *string `json:"filter_by,omitempty"` + // FilterCuratedHits Whether the filter_by condition of the search query should be applicable to curated results (override definitions, pinned hits, hidden hits, etc.). Default: false + FilterCuratedHits *bool `json:"filter_curated_hits,omitempty"` + // GroupBy You can aggregate search results into groups or buckets by specify one or more `group_by` fields. Separate multiple fields with a comma. To group on a particular field, it must be a faceted field. GroupBy *string `json:"group_by,omitempty"` @@ -553,6 +586,12 @@ type MultiSearchCollectionParameters struct { // Stopwords Name of the stopwords set to apply for this search, the keywords present in the set will be removed from the search query. Stopwords *string `json:"stopwords,omitempty"` + // SynonymNumTypos Allow synonym resolution on typo-corrected words in the query. Default: 0 + SynonymNumTypos *int `json:"synonym_num_typos,omitempty"` + + // SynonymPrefix Allow synonym resolution on word prefixes in the query. Default: false + SynonymPrefix *bool `json:"synonym_prefix,omitempty"` + // TextMatchType In a multi-field matching context, this parameter determines how the representative text match score of a record is calculated. Possible values are max_score (default) or max_weight. TextMatchType *string `json:"text_match_type,omitempty"` @@ -583,12 +622,21 @@ type MultiSearchParameters struct { // ConversationModelId The Id of Conversation Model to be used. ConversationModelId *string `json:"conversation_model_id,omitempty"` + // DropTokensMode Dictates the direction in which the words in the query must be dropped when the original words in the query do not appear in any document. Values: right_to_left (default), left_to_right, both_sides:3 A note on both_sides:3 - for queries upto 3 tokens (words) in length, this mode will drop tokens from both sides and exhaustively rank all matching results. If query length is greater than 3 words, Typesense will just fallback to default behavior of right_to_left + DropTokensMode *DropTokensMode `json:"drop_tokens_mode,omitempty"` + // DropTokensThreshold If the number of results found for a specific query is less than this number, Typesense will attempt to drop the tokens in the query until enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 DropTokensThreshold *int `json:"drop_tokens_threshold,omitempty"` // EnableOverrides If you have some overrides defined but want to disable all of them during query time, you can do that by setting this parameter to false EnableOverrides *bool `json:"enable_overrides,omitempty"` + // EnableSynonyms If you have some synonyms defined but want to disable all of them for a particular search query, set enable_synonyms to false. Default: true + EnableSynonyms *bool `json:"enable_synonyms,omitempty"` + + // EnableTyposForAlphaNumericalTokens Set this parameter to false to disable typos on alphanumerical query tokens. Default: true. + EnableTyposForAlphaNumericalTokens *bool `json:"enable_typos_for_alpha_numerical_tokens,omitempty"` + // EnableTyposForNumericalTokens Make Typesense disable typos for numerical tokens. EnableTyposForNumericalTokens *bool `json:"enable_typos_for_numerical_tokens,omitempty"` @@ -613,6 +661,9 @@ type MultiSearchParameters struct { // FilterBy Filter conditions for refining youropen api validator search results. Separate multiple conditions with &&. FilterBy *string `json:"filter_by,omitempty"` + // FilterCuratedHits Whether the filter_by condition of the search query should be applicable to curated results (override definitions, pinned hits, hidden hits, etc.). Default: false + FilterCuratedHits *bool `json:"filter_curated_hits,omitempty"` + // GroupBy You can aggregate search results into groups or buckets by specify one or more `group_by` fields. Separate multiple fields with a comma. To group on a particular field, it must be a faceted field. GroupBy *string `json:"group_by,omitempty"` @@ -730,6 +781,12 @@ type MultiSearchParameters struct { // Stopwords Name of the stopwords set to apply for this search, the keywords present in the set will be removed from the search query. Stopwords *string `json:"stopwords,omitempty"` + // SynonymNumTypos Allow synonym resolution on typo-corrected words in the query. Default: 0 + SynonymNumTypos *int `json:"synonym_num_typos,omitempty"` + + // SynonymPrefix Allow synonym resolution on word prefixes in the query. Default: false + SynonymPrefix *bool `json:"synonym_prefix,omitempty"` + // TextMatchType In a multi-field matching context, this parameter determines how the representative text match score of a record is calculated. Possible values are max_score (default) or max_weight. TextMatchType *string `json:"text_match_type,omitempty"` @@ -945,6 +1002,9 @@ type SearchParameters struct { // ConversationModelId The Id of Conversation Model to be used. ConversationModelId *string `json:"conversation_model_id,omitempty"` + // DropTokensMode Dictates the direction in which the words in the query must be dropped when the original words in the query do not appear in any document. Values: right_to_left (default), left_to_right, both_sides:3 A note on both_sides:3 - for queries upto 3 tokens (words) in length, this mode will drop tokens from both sides and exhaustively rank all matching results. If query length is greater than 3 words, Typesense will just fallback to default behavior of right_to_left + DropTokensMode *DropTokensMode `json:"drop_tokens_mode,omitempty"` + // DropTokensThreshold If the number of results found for a specific query is less than this number, Typesense will attempt to drop the tokens in the query until enough results are found. Tokens that have the least individual hits are dropped first. Set to 0 to disable. Default: 10 DropTokensThreshold *int `json:"drop_tokens_threshold,omitempty"` @@ -954,6 +1014,12 @@ type SearchParameters struct { // EnableOverrides If you have some overrides defined but want to disable all of them during query time, you can do that by setting this parameter to false EnableOverrides *bool `json:"enable_overrides,omitempty"` + // EnableSynonyms If you have some synonyms defined but want to disable all of them for a particular search query, set enable_synonyms to false. Default: true + EnableSynonyms *bool `json:"enable_synonyms,omitempty"` + + // EnableTyposForAlphaNumericalTokens Set this parameter to false to disable typos on alphanumerical query tokens. Default: true. + EnableTyposForAlphaNumericalTokens *bool `json:"enable_typos_for_alpha_numerical_tokens,omitempty"` + // EnableTyposForNumericalTokens Make Typesense disable typos for numerical tokens. EnableTyposForNumericalTokens *bool `json:"enable_typos_for_numerical_tokens,omitempty"` @@ -978,6 +1044,9 @@ type SearchParameters struct { // FilterBy Filter conditions for refining youropen api validator search results. Separate multiple conditions with &&. FilterBy *string `json:"filter_by,omitempty"` + // FilterCuratedHits Whether the filter_by condition of the search query should be applicable to curated results (override definitions, pinned hits, hidden hits, etc.). Default: false + FilterCuratedHits *bool `json:"filter_curated_hits,omitempty"` + // GroupBy You can aggregate search results into groups or buckets by specify one or more `group_by` fields. Separate multiple fields with a comma. To group on a particular field, it must be a faceted field. GroupBy *string `json:"group_by,omitempty"` @@ -1101,6 +1170,12 @@ type SearchParameters struct { // Stopwords Name of the stopwords set to apply for this search, the keywords present in the set will be removed from the search query. Stopwords *string `json:"stopwords,omitempty"` + // SynonymNumTypos Allow synonym resolution on typo-corrected words in the query. Default: 0 + SynonymNumTypos *int `json:"synonym_num_typos,omitempty"` + + // SynonymPrefix Allow synonym resolution on word prefixes in the query. Default: false + SynonymPrefix *bool `json:"synonym_prefix,omitempty"` + // TextMatchType In a multi-field matching context, this parameter determines how the representative text match score of a record is calculated. Possible values are max_score (default) or max_weight. TextMatchType *string `json:"text_match_type,omitempty"` @@ -1294,66 +1369,72 @@ type ImportDocumentsParams struct { // SearchCollectionParams defines parameters for SearchCollection. type SearchCollectionParams struct { - CacheTtl *int `form:"cache_ttl,omitempty" json:"cache_ttl,omitempty"` - Conversation *bool `form:"conversation,omitempty" json:"conversation,omitempty"` - ConversationId *string `form:"conversation_id,omitempty" json:"conversation_id,omitempty"` - ConversationModelId *string `form:"conversation_model_id,omitempty" json:"conversation_model_id,omitempty"` - DropTokensThreshold *int `form:"drop_tokens_threshold,omitempty" json:"drop_tokens_threshold,omitempty"` - EnableHighlightV1 *bool `form:"enable_highlight_v1,omitempty" json:"enable_highlight_v1,omitempty"` - EnableOverrides *bool `form:"enable_overrides,omitempty" json:"enable_overrides,omitempty"` - EnableTyposForNumericalTokens *bool `form:"enable_typos_for_numerical_tokens,omitempty" json:"enable_typos_for_numerical_tokens,omitempty"` - ExcludeFields *string `form:"exclude_fields,omitempty" json:"exclude_fields,omitempty"` - ExhaustiveSearch *bool `form:"exhaustive_search,omitempty" json:"exhaustive_search,omitempty"` - FacetBy *string `form:"facet_by,omitempty" json:"facet_by,omitempty"` - FacetQuery *string `form:"facet_query,omitempty" json:"facet_query,omitempty"` - FacetReturnParent *string `form:"facet_return_parent,omitempty" json:"facet_return_parent,omitempty"` - FacetStrategy *string `form:"facet_strategy,omitempty" json:"facet_strategy,omitempty"` - FilterBy *string `form:"filter_by,omitempty" json:"filter_by,omitempty"` - GroupBy *string `form:"group_by,omitempty" json:"group_by,omitempty"` - GroupLimit *int `form:"group_limit,omitempty" json:"group_limit,omitempty"` - GroupMissingValues *bool `form:"group_missing_values,omitempty" json:"group_missing_values,omitempty"` - HiddenHits *string `form:"hidden_hits,omitempty" json:"hidden_hits,omitempty"` - HighlightAffixNumTokens *int `form:"highlight_affix_num_tokens,omitempty" json:"highlight_affix_num_tokens,omitempty"` - HighlightEndTag *string `form:"highlight_end_tag,omitempty" json:"highlight_end_tag,omitempty"` - HighlightFields *string `form:"highlight_fields,omitempty" json:"highlight_fields,omitempty"` - HighlightFullFields *string `form:"highlight_full_fields,omitempty" json:"highlight_full_fields,omitempty"` - HighlightStartTag *string `form:"highlight_start_tag,omitempty" json:"highlight_start_tag,omitempty"` - IncludeFields *string `form:"include_fields,omitempty" json:"include_fields,omitempty"` - Infix *string `form:"infix,omitempty" json:"infix,omitempty"` - Limit *int `form:"limit,omitempty" json:"limit,omitempty"` - MaxCandidates *int `form:"max_candidates,omitempty" json:"max_candidates,omitempty"` - MaxExtraPrefix *int `form:"max_extra_prefix,omitempty" json:"max_extra_prefix,omitempty"` - MaxExtraSuffix *int `form:"max_extra_suffix,omitempty" json:"max_extra_suffix,omitempty"` - MaxFacetValues *int `form:"max_facet_values,omitempty" json:"max_facet_values,omitempty"` - MinLen1typo *int `form:"min_len_1typo,omitempty" json:"min_len_1typo,omitempty"` - MinLen2typo *int `form:"min_len_2typo,omitempty" json:"min_len_2typo,omitempty"` - NumTypos *string `form:"num_typos,omitempty" json:"num_typos,omitempty"` - Offset *int `form:"offset,omitempty" json:"offset,omitempty"` - OverrideTags *string `form:"override_tags,omitempty" json:"override_tags,omitempty"` - Page *int `form:"page,omitempty" json:"page,omitempty"` - PerPage *int `form:"per_page,omitempty" json:"per_page,omitempty"` - PinnedHits *string `form:"pinned_hits,omitempty" json:"pinned_hits,omitempty"` - PreSegmentedQuery *bool `form:"pre_segmented_query,omitempty" json:"pre_segmented_query,omitempty"` - Prefix *string `form:"prefix,omitempty" json:"prefix,omitempty"` - Preset *string `form:"preset,omitempty" json:"preset,omitempty"` - PrioritizeExactMatch *bool `form:"prioritize_exact_match,omitempty" json:"prioritize_exact_match,omitempty"` - PrioritizeNumMatchingFields *bool `form:"prioritize_num_matching_fields,omitempty" json:"prioritize_num_matching_fields,omitempty"` - PrioritizeTokenPosition *bool `form:"prioritize_token_position,omitempty" json:"prioritize_token_position,omitempty"` - Q *string `form:"q,omitempty" json:"q,omitempty"` - QueryBy *string `form:"query_by,omitempty" json:"query_by,omitempty"` - QueryByWeights *string `form:"query_by_weights,omitempty" json:"query_by_weights,omitempty"` - RemoteEmbeddingNumTries *int `form:"remote_embedding_num_tries,omitempty" json:"remote_embedding_num_tries,omitempty"` - RemoteEmbeddingTimeoutMs *int `form:"remote_embedding_timeout_ms,omitempty" json:"remote_embedding_timeout_ms,omitempty"` - SearchCutoffMs *int `form:"search_cutoff_ms,omitempty" json:"search_cutoff_ms,omitempty"` - SnippetThreshold *int `form:"snippet_threshold,omitempty" json:"snippet_threshold,omitempty"` - SortBy *string `form:"sort_by,omitempty" json:"sort_by,omitempty"` - SplitJoinTokens *string `form:"split_join_tokens,omitempty" json:"split_join_tokens,omitempty"` - Stopwords *string `form:"stopwords,omitempty" json:"stopwords,omitempty"` - TextMatchType *string `form:"text_match_type,omitempty" json:"text_match_type,omitempty"` - TypoTokensThreshold *int `form:"typo_tokens_threshold,omitempty" json:"typo_tokens_threshold,omitempty"` - UseCache *bool `form:"use_cache,omitempty" json:"use_cache,omitempty"` - VectorQuery *string `form:"vector_query,omitempty" json:"vector_query,omitempty"` - VoiceQuery *string `form:"voice_query,omitempty" json:"voice_query,omitempty"` + CacheTtl *int `form:"cache_ttl,omitempty" json:"cache_ttl,omitempty"` + Conversation *bool `form:"conversation,omitempty" json:"conversation,omitempty"` + ConversationId *string `form:"conversation_id,omitempty" json:"conversation_id,omitempty"` + ConversationModelId *string `form:"conversation_model_id,omitempty" json:"conversation_model_id,omitempty"` + DropTokensMode *DropTokensMode `form:"drop_tokens_mode,omitempty" json:"drop_tokens_mode,omitempty"` + DropTokensThreshold *int `form:"drop_tokens_threshold,omitempty" json:"drop_tokens_threshold,omitempty"` + EnableHighlightV1 *bool `form:"enable_highlight_v1,omitempty" json:"enable_highlight_v1,omitempty"` + EnableOverrides *bool `form:"enable_overrides,omitempty" json:"enable_overrides,omitempty"` + EnableSynonyms *bool `form:"enable_synonyms,omitempty" json:"enable_synonyms,omitempty"` + EnableTyposForAlphaNumericalTokens *bool `form:"enable_typos_for_alpha_numerical_tokens,omitempty" json:"enable_typos_for_alpha_numerical_tokens,omitempty"` + EnableTyposForNumericalTokens *bool `form:"enable_typos_for_numerical_tokens,omitempty" json:"enable_typos_for_numerical_tokens,omitempty"` + ExcludeFields *string `form:"exclude_fields,omitempty" json:"exclude_fields,omitempty"` + ExhaustiveSearch *bool `form:"exhaustive_search,omitempty" json:"exhaustive_search,omitempty"` + FacetBy *string `form:"facet_by,omitempty" json:"facet_by,omitempty"` + FacetQuery *string `form:"facet_query,omitempty" json:"facet_query,omitempty"` + FacetReturnParent *string `form:"facet_return_parent,omitempty" json:"facet_return_parent,omitempty"` + FacetStrategy *string `form:"facet_strategy,omitempty" json:"facet_strategy,omitempty"` + FilterBy *string `form:"filter_by,omitempty" json:"filter_by,omitempty"` + FilterCuratedHits *bool `form:"filter_curated_hits,omitempty" json:"filter_curated_hits,omitempty"` + GroupBy *string `form:"group_by,omitempty" json:"group_by,omitempty"` + GroupLimit *int `form:"group_limit,omitempty" json:"group_limit,omitempty"` + GroupMissingValues *bool `form:"group_missing_values,omitempty" json:"group_missing_values,omitempty"` + HiddenHits *string `form:"hidden_hits,omitempty" json:"hidden_hits,omitempty"` + HighlightAffixNumTokens *int `form:"highlight_affix_num_tokens,omitempty" json:"highlight_affix_num_tokens,omitempty"` + HighlightEndTag *string `form:"highlight_end_tag,omitempty" json:"highlight_end_tag,omitempty"` + HighlightFields *string `form:"highlight_fields,omitempty" json:"highlight_fields,omitempty"` + HighlightFullFields *string `form:"highlight_full_fields,omitempty" json:"highlight_full_fields,omitempty"` + HighlightStartTag *string `form:"highlight_start_tag,omitempty" json:"highlight_start_tag,omitempty"` + IncludeFields *string `form:"include_fields,omitempty" json:"include_fields,omitempty"` + Infix *string `form:"infix,omitempty" json:"infix,omitempty"` + Limit *int `form:"limit,omitempty" json:"limit,omitempty"` + MaxCandidates *int `form:"max_candidates,omitempty" json:"max_candidates,omitempty"` + MaxExtraPrefix *int `form:"max_extra_prefix,omitempty" json:"max_extra_prefix,omitempty"` + MaxExtraSuffix *int `form:"max_extra_suffix,omitempty" json:"max_extra_suffix,omitempty"` + MaxFacetValues *int `form:"max_facet_values,omitempty" json:"max_facet_values,omitempty"` + MinLen1typo *int `form:"min_len_1typo,omitempty" json:"min_len_1typo,omitempty"` + MinLen2typo *int `form:"min_len_2typo,omitempty" json:"min_len_2typo,omitempty"` + NumTypos *string `form:"num_typos,omitempty" json:"num_typos,omitempty"` + Offset *int `form:"offset,omitempty" json:"offset,omitempty"` + OverrideTags *string `form:"override_tags,omitempty" json:"override_tags,omitempty"` + Page *int `form:"page,omitempty" json:"page,omitempty"` + PerPage *int `form:"per_page,omitempty" json:"per_page,omitempty"` + PinnedHits *string `form:"pinned_hits,omitempty" json:"pinned_hits,omitempty"` + PreSegmentedQuery *bool `form:"pre_segmented_query,omitempty" json:"pre_segmented_query,omitempty"` + Prefix *string `form:"prefix,omitempty" json:"prefix,omitempty"` + Preset *string `form:"preset,omitempty" json:"preset,omitempty"` + PrioritizeExactMatch *bool `form:"prioritize_exact_match,omitempty" json:"prioritize_exact_match,omitempty"` + PrioritizeNumMatchingFields *bool `form:"prioritize_num_matching_fields,omitempty" json:"prioritize_num_matching_fields,omitempty"` + PrioritizeTokenPosition *bool `form:"prioritize_token_position,omitempty" json:"prioritize_token_position,omitempty"` + Q *string `form:"q,omitempty" json:"q,omitempty"` + QueryBy *string `form:"query_by,omitempty" json:"query_by,omitempty"` + QueryByWeights *string `form:"query_by_weights,omitempty" json:"query_by_weights,omitempty"` + RemoteEmbeddingNumTries *int `form:"remote_embedding_num_tries,omitempty" json:"remote_embedding_num_tries,omitempty"` + RemoteEmbeddingTimeoutMs *int `form:"remote_embedding_timeout_ms,omitempty" json:"remote_embedding_timeout_ms,omitempty"` + SearchCutoffMs *int `form:"search_cutoff_ms,omitempty" json:"search_cutoff_ms,omitempty"` + SnippetThreshold *int `form:"snippet_threshold,omitempty" json:"snippet_threshold,omitempty"` + SortBy *string `form:"sort_by,omitempty" json:"sort_by,omitempty"` + SplitJoinTokens *string `form:"split_join_tokens,omitempty" json:"split_join_tokens,omitempty"` + Stopwords *string `form:"stopwords,omitempty" json:"stopwords,omitempty"` + SynonymNumTypos *int `form:"synonym_num_typos,omitempty" json:"synonym_num_typos,omitempty"` + SynonymPrefix *bool `form:"synonym_prefix,omitempty" json:"synonym_prefix,omitempty"` + TextMatchType *string `form:"text_match_type,omitempty" json:"text_match_type,omitempty"` + TypoTokensThreshold *int `form:"typo_tokens_threshold,omitempty" json:"typo_tokens_threshold,omitempty"` + UseCache *bool `form:"use_cache,omitempty" json:"use_cache,omitempty"` + VectorQuery *string `form:"vector_query,omitempty" json:"vector_query,omitempty"` + VoiceQuery *string `form:"voice_query,omitempty" json:"voice_query,omitempty"` } // UpdateDocumentJSONBody defines parameters for UpdateDocument. @@ -1361,66 +1442,72 @@ type UpdateDocumentJSONBody = interface{} // MultiSearchParams defines parameters for MultiSearch. type MultiSearchParams struct { - CacheTtl *int `form:"cache_ttl,omitempty" json:"cache_ttl,omitempty"` - Conversation *bool `form:"conversation,omitempty" json:"conversation,omitempty"` - ConversationId *string `form:"conversation_id,omitempty" json:"conversation_id,omitempty"` - ConversationModelId *string `form:"conversation_model_id,omitempty" json:"conversation_model_id,omitempty"` - DropTokensThreshold *int `form:"drop_tokens_threshold,omitempty" json:"drop_tokens_threshold,omitempty"` - EnableHighlightV1 *bool `form:"enable_highlight_v1,omitempty" json:"enable_highlight_v1,omitempty"` - EnableOverrides *bool `form:"enable_overrides,omitempty" json:"enable_overrides,omitempty"` - EnableTyposForNumericalTokens *bool `form:"enable_typos_for_numerical_tokens,omitempty" json:"enable_typos_for_numerical_tokens,omitempty"` - ExcludeFields *string `form:"exclude_fields,omitempty" json:"exclude_fields,omitempty"` - ExhaustiveSearch *bool `form:"exhaustive_search,omitempty" json:"exhaustive_search,omitempty"` - FacetBy *string `form:"facet_by,omitempty" json:"facet_by,omitempty"` - FacetQuery *string `form:"facet_query,omitempty" json:"facet_query,omitempty"` - FacetReturnParent *string `form:"facet_return_parent,omitempty" json:"facet_return_parent,omitempty"` - FacetStrategy *string `form:"facet_strategy,omitempty" json:"facet_strategy,omitempty"` - FilterBy *string `form:"filter_by,omitempty" json:"filter_by,omitempty"` - GroupBy *string `form:"group_by,omitempty" json:"group_by,omitempty"` - GroupLimit *int `form:"group_limit,omitempty" json:"group_limit,omitempty"` - GroupMissingValues *bool `form:"group_missing_values,omitempty" json:"group_missing_values,omitempty"` - HiddenHits *string `form:"hidden_hits,omitempty" json:"hidden_hits,omitempty"` - HighlightAffixNumTokens *int `form:"highlight_affix_num_tokens,omitempty" json:"highlight_affix_num_tokens,omitempty"` - HighlightEndTag *string `form:"highlight_end_tag,omitempty" json:"highlight_end_tag,omitempty"` - HighlightFields *string `form:"highlight_fields,omitempty" json:"highlight_fields,omitempty"` - HighlightFullFields *string `form:"highlight_full_fields,omitempty" json:"highlight_full_fields,omitempty"` - HighlightStartTag *string `form:"highlight_start_tag,omitempty" json:"highlight_start_tag,omitempty"` - IncludeFields *string `form:"include_fields,omitempty" json:"include_fields,omitempty"` - Infix *string `form:"infix,omitempty" json:"infix,omitempty"` - Limit *int `form:"limit,omitempty" json:"limit,omitempty"` - MaxCandidates *int `form:"max_candidates,omitempty" json:"max_candidates,omitempty"` - MaxExtraPrefix *int `form:"max_extra_prefix,omitempty" json:"max_extra_prefix,omitempty"` - MaxExtraSuffix *int `form:"max_extra_suffix,omitempty" json:"max_extra_suffix,omitempty"` - MaxFacetValues *int `form:"max_facet_values,omitempty" json:"max_facet_values,omitempty"` - MinLen1typo *int `form:"min_len_1typo,omitempty" json:"min_len_1typo,omitempty"` - MinLen2typo *int `form:"min_len_2typo,omitempty" json:"min_len_2typo,omitempty"` - NumTypos *string `form:"num_typos,omitempty" json:"num_typos,omitempty"` - Offset *int `form:"offset,omitempty" json:"offset,omitempty"` - OverrideTags *string `form:"override_tags,omitempty" json:"override_tags,omitempty"` - Page *int `form:"page,omitempty" json:"page,omitempty"` - PerPage *int `form:"per_page,omitempty" json:"per_page,omitempty"` - PinnedHits *string `form:"pinned_hits,omitempty" json:"pinned_hits,omitempty"` - PreSegmentedQuery *bool `form:"pre_segmented_query,omitempty" json:"pre_segmented_query,omitempty"` - Prefix *string `form:"prefix,omitempty" json:"prefix,omitempty"` - Preset *string `form:"preset,omitempty" json:"preset,omitempty"` - PrioritizeExactMatch *bool `form:"prioritize_exact_match,omitempty" json:"prioritize_exact_match,omitempty"` - PrioritizeNumMatchingFields *bool `form:"prioritize_num_matching_fields,omitempty" json:"prioritize_num_matching_fields,omitempty"` - PrioritizeTokenPosition *bool `form:"prioritize_token_position,omitempty" json:"prioritize_token_position,omitempty"` - Q *string `form:"q,omitempty" json:"q,omitempty"` - QueryBy *string `form:"query_by,omitempty" json:"query_by,omitempty"` - QueryByWeights *string `form:"query_by_weights,omitempty" json:"query_by_weights,omitempty"` - RemoteEmbeddingNumTries *int `form:"remote_embedding_num_tries,omitempty" json:"remote_embedding_num_tries,omitempty"` - RemoteEmbeddingTimeoutMs *int `form:"remote_embedding_timeout_ms,omitempty" json:"remote_embedding_timeout_ms,omitempty"` - SearchCutoffMs *int `form:"search_cutoff_ms,omitempty" json:"search_cutoff_ms,omitempty"` - SnippetThreshold *int `form:"snippet_threshold,omitempty" json:"snippet_threshold,omitempty"` - SortBy *string `form:"sort_by,omitempty" json:"sort_by,omitempty"` - SplitJoinTokens *string `form:"split_join_tokens,omitempty" json:"split_join_tokens,omitempty"` - Stopwords *string `form:"stopwords,omitempty" json:"stopwords,omitempty"` - TextMatchType *string `form:"text_match_type,omitempty" json:"text_match_type,omitempty"` - TypoTokensThreshold *int `form:"typo_tokens_threshold,omitempty" json:"typo_tokens_threshold,omitempty"` - UseCache *bool `form:"use_cache,omitempty" json:"use_cache,omitempty"` - VectorQuery *string `form:"vector_query,omitempty" json:"vector_query,omitempty"` - VoiceQuery *string `form:"voice_query,omitempty" json:"voice_query,omitempty"` + CacheTtl *int `form:"cache_ttl,omitempty" json:"cache_ttl,omitempty"` + Conversation *bool `form:"conversation,omitempty" json:"conversation,omitempty"` + ConversationId *string `form:"conversation_id,omitempty" json:"conversation_id,omitempty"` + ConversationModelId *string `form:"conversation_model_id,omitempty" json:"conversation_model_id,omitempty"` + DropTokensMode *DropTokensMode `form:"drop_tokens_mode,omitempty" json:"drop_tokens_mode,omitempty"` + DropTokensThreshold *int `form:"drop_tokens_threshold,omitempty" json:"drop_tokens_threshold,omitempty"` + EnableHighlightV1 *bool `form:"enable_highlight_v1,omitempty" json:"enable_highlight_v1,omitempty"` + EnableOverrides *bool `form:"enable_overrides,omitempty" json:"enable_overrides,omitempty"` + EnableSynonyms *bool `form:"enable_synonyms,omitempty" json:"enable_synonyms,omitempty"` + EnableTyposForAlphaNumericalTokens *bool `form:"enable_typos_for_alpha_numerical_tokens,omitempty" json:"enable_typos_for_alpha_numerical_tokens,omitempty"` + EnableTyposForNumericalTokens *bool `form:"enable_typos_for_numerical_tokens,omitempty" json:"enable_typos_for_numerical_tokens,omitempty"` + ExcludeFields *string `form:"exclude_fields,omitempty" json:"exclude_fields,omitempty"` + ExhaustiveSearch *bool `form:"exhaustive_search,omitempty" json:"exhaustive_search,omitempty"` + FacetBy *string `form:"facet_by,omitempty" json:"facet_by,omitempty"` + FacetQuery *string `form:"facet_query,omitempty" json:"facet_query,omitempty"` + FacetReturnParent *string `form:"facet_return_parent,omitempty" json:"facet_return_parent,omitempty"` + FacetStrategy *string `form:"facet_strategy,omitempty" json:"facet_strategy,omitempty"` + FilterBy *string `form:"filter_by,omitempty" json:"filter_by,omitempty"` + FilterCuratedHits *bool `form:"filter_curated_hits,omitempty" json:"filter_curated_hits,omitempty"` + GroupBy *string `form:"group_by,omitempty" json:"group_by,omitempty"` + GroupLimit *int `form:"group_limit,omitempty" json:"group_limit,omitempty"` + GroupMissingValues *bool `form:"group_missing_values,omitempty" json:"group_missing_values,omitempty"` + HiddenHits *string `form:"hidden_hits,omitempty" json:"hidden_hits,omitempty"` + HighlightAffixNumTokens *int `form:"highlight_affix_num_tokens,omitempty" json:"highlight_affix_num_tokens,omitempty"` + HighlightEndTag *string `form:"highlight_end_tag,omitempty" json:"highlight_end_tag,omitempty"` + HighlightFields *string `form:"highlight_fields,omitempty" json:"highlight_fields,omitempty"` + HighlightFullFields *string `form:"highlight_full_fields,omitempty" json:"highlight_full_fields,omitempty"` + HighlightStartTag *string `form:"highlight_start_tag,omitempty" json:"highlight_start_tag,omitempty"` + IncludeFields *string `form:"include_fields,omitempty" json:"include_fields,omitempty"` + Infix *string `form:"infix,omitempty" json:"infix,omitempty"` + Limit *int `form:"limit,omitempty" json:"limit,omitempty"` + MaxCandidates *int `form:"max_candidates,omitempty" json:"max_candidates,omitempty"` + MaxExtraPrefix *int `form:"max_extra_prefix,omitempty" json:"max_extra_prefix,omitempty"` + MaxExtraSuffix *int `form:"max_extra_suffix,omitempty" json:"max_extra_suffix,omitempty"` + MaxFacetValues *int `form:"max_facet_values,omitempty" json:"max_facet_values,omitempty"` + MinLen1typo *int `form:"min_len_1typo,omitempty" json:"min_len_1typo,omitempty"` + MinLen2typo *int `form:"min_len_2typo,omitempty" json:"min_len_2typo,omitempty"` + NumTypos *string `form:"num_typos,omitempty" json:"num_typos,omitempty"` + Offset *int `form:"offset,omitempty" json:"offset,omitempty"` + OverrideTags *string `form:"override_tags,omitempty" json:"override_tags,omitempty"` + Page *int `form:"page,omitempty" json:"page,omitempty"` + PerPage *int `form:"per_page,omitempty" json:"per_page,omitempty"` + PinnedHits *string `form:"pinned_hits,omitempty" json:"pinned_hits,omitempty"` + PreSegmentedQuery *bool `form:"pre_segmented_query,omitempty" json:"pre_segmented_query,omitempty"` + Prefix *string `form:"prefix,omitempty" json:"prefix,omitempty"` + Preset *string `form:"preset,omitempty" json:"preset,omitempty"` + PrioritizeExactMatch *bool `form:"prioritize_exact_match,omitempty" json:"prioritize_exact_match,omitempty"` + PrioritizeNumMatchingFields *bool `form:"prioritize_num_matching_fields,omitempty" json:"prioritize_num_matching_fields,omitempty"` + PrioritizeTokenPosition *bool `form:"prioritize_token_position,omitempty" json:"prioritize_token_position,omitempty"` + Q *string `form:"q,omitempty" json:"q,omitempty"` + QueryBy *string `form:"query_by,omitempty" json:"query_by,omitempty"` + QueryByWeights *string `form:"query_by_weights,omitempty" json:"query_by_weights,omitempty"` + RemoteEmbeddingNumTries *int `form:"remote_embedding_num_tries,omitempty" json:"remote_embedding_num_tries,omitempty"` + RemoteEmbeddingTimeoutMs *int `form:"remote_embedding_timeout_ms,omitempty" json:"remote_embedding_timeout_ms,omitempty"` + SearchCutoffMs *int `form:"search_cutoff_ms,omitempty" json:"search_cutoff_ms,omitempty"` + SnippetThreshold *int `form:"snippet_threshold,omitempty" json:"snippet_threshold,omitempty"` + SortBy *string `form:"sort_by,omitempty" json:"sort_by,omitempty"` + SplitJoinTokens *string `form:"split_join_tokens,omitempty" json:"split_join_tokens,omitempty"` + Stopwords *string `form:"stopwords,omitempty" json:"stopwords,omitempty"` + SynonymNumTypos *int `form:"synonym_num_typos,omitempty" json:"synonym_num_typos,omitempty"` + SynonymPrefix *bool `form:"synonym_prefix,omitempty" json:"synonym_prefix,omitempty"` + TextMatchType *string `form:"text_match_type,omitempty" json:"text_match_type,omitempty"` + TypoTokensThreshold *int `form:"typo_tokens_threshold,omitempty" json:"typo_tokens_threshold,omitempty"` + UseCache *bool `form:"use_cache,omitempty" json:"use_cache,omitempty"` + VectorQuery *string `form:"vector_query,omitempty" json:"vector_query,omitempty"` + VoiceQuery *string `form:"voice_query,omitempty" json:"voice_query,omitempty"` } // TakeSnapshotParams defines parameters for TakeSnapshot. From 60e15492d556b22ba33d45c7d48c9de2c7f25f94 Mon Sep 17 00:00:00 2001 From: Hayden Date: Mon, 30 Sep 2024 21:10:20 +0700 Subject: [PATCH 16/19] fix lint & update integration test --- typesense/api/generator/main.go | 31 +++++++++++++++---------------- typesense/test/dbhelpers_test.go | 3 +++ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/typesense/api/generator/main.go b/typesense/api/generator/main.go index 26e856b..ced3ccc 100644 --- a/typesense/api/generator/main.go +++ b/typesense/api/generator/main.go @@ -215,16 +215,15 @@ func unwrapSearchParameters(m *yml) { newMap["in"] = query newMap["schema"] = make(yml) if obj.Value.(yml)["oneOf"] == nil { + switch { // if the param is referencing a schema - if obj.Value.(yml)["type"] == nil { + case obj.Value.(yml)["type"] == nil: newMap["schema"].(yml)["$ref"] = obj.Value.(yml)["$ref"].(string) - } else { - if obj.Value.(yml)["type"].(string) == array { - newMap["schema"].(yml)["type"] = array - newMap["schema"].(yml)["items"] = obj.Value.(yml)["items"] - } else { - newMap["schema"].(yml)["type"] = obj.Value.(yml)["type"].(string) - } + case obj.Value.(yml)["type"].(string) == array: + newMap["schema"].(yml)["type"] = array + newMap["schema"].(yml)["items"] = obj.Value.(yml)["items"] + default: + newMap["schema"].(yml)["type"] = obj.Value.(yml)["type"].(string) } } else { newMap["schema"].(yml)["oneOf"] = obj.Value.(yml)["oneOf"] @@ -246,15 +245,15 @@ func unwrapMultiSearchParameters(m *yml) { newMap["in"] = query newMap["schema"] = make(yml) if obj.Value.(yml)["oneOf"] == nil { - if obj.Value.(yml)["type"] == nil { + switch { + // if the param is referencing a schema + case obj.Value.(yml)["type"] == nil: newMap["schema"].(yml)["$ref"] = obj.Value.(yml)["$ref"].(string) - } else { - if obj.Value.(yml)["type"].(string) == array { - newMap["schema"].(yml)["type"] = array - newMap["schema"].(yml)["items"] = obj.Value.(yml)["items"] - } else { - newMap["schema"].(yml)["type"] = obj.Value.(yml)["type"].(string) - } + case obj.Value.(yml)["type"].(string) == array: + newMap["schema"].(yml)["type"] = array + newMap["schema"].(yml)["items"] = obj.Value.(yml)["items"] + default: + newMap["schema"].(yml)["type"] = obj.Value.(yml)["type"].(string) } } else { newMap["schema"].(yml)["oneOf"] = obj.Value.(yml)["oneOf"] diff --git a/typesense/test/dbhelpers_test.go b/typesense/test/dbhelpers_test.go index e59b3f5..21c6972 100644 --- a/typesense/test/dbhelpers_test.go +++ b/typesense/test/dbhelpers_test.go @@ -57,6 +57,7 @@ func expectedNewCollection(name string) *api.CollectionResponse { Sort: pointer.False(), Drop: nil, Store: pointer.True(), + Stem: pointer.False(), }, { Name: "num_employees", @@ -69,6 +70,7 @@ func expectedNewCollection(name string) *api.CollectionResponse { Sort: pointer.True(), Drop: nil, Store: pointer.True(), + Stem: pointer.False(), }, { Name: "country", @@ -81,6 +83,7 @@ func expectedNewCollection(name string) *api.CollectionResponse { Sort: pointer.False(), Drop: nil, Store: pointer.True(), + Stem: pointer.False(), }, }, EnableNestedFields: pointer.False(), From 0a701e119608d321d9ed7704cb4c82fe55823b7d Mon Sep 17 00:00:00 2001 From: Hayden Date: Mon, 30 Sep 2024 21:29:31 +0700 Subject: [PATCH 17/19] ci: bump golangci-lint version to v1.60 --- .github/workflows/golangci-lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 9783f4d..f6213bf 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -30,4 +30,4 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v6 with: - version: v1.59 + version: v1.60 From 90638ca1fe1ce5fed6f11e0806969b5aea5b30b1 Mon Sep 17 00:00:00 2001 From: Hayden Date: Mon, 30 Sep 2024 21:35:30 +0700 Subject: [PATCH 18/19] ci: replace deprecated "io/ioutil" package --- typesense/documents_test.go | 9 ++++----- typesense/import_test.go | 27 +++++++++++++-------------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/typesense/documents_test.go b/typesense/documents_test.go index 08fc0a8..2dc8d97 100644 --- a/typesense/documents_test.go +++ b/typesense/documents_test.go @@ -4,7 +4,6 @@ import ( "context" "errors" "io" - "io/ioutil" "net/http" "strings" "testing" @@ -277,11 +276,11 @@ func TestDocumentsDeleteOnHttpStatusErrorCodeReturnsError(t *testing.T) { } func createDocumentStream() io.ReadCloser { - return ioutil.NopCloser(strings.NewReader(`{"id": "125","company_name":"Future Technology","num_employees":1232,"country":"UK"}`)) + return io.NopCloser(strings.NewReader(`{"id": "125","company_name":"Future Technology","num_employees":1232,"country":"UK"}`)) } func TestDocumentsExport(t *testing.T) { - expectedBytes, err := ioutil.ReadAll(createDocumentStream()) + expectedBytes, err := io.ReadAll(createDocumentStream()) assert.Nil(t, err) ctrl := gomock.NewController(t) @@ -301,7 +300,7 @@ func TestDocumentsExport(t *testing.T) { result, err := client.Collection("companies").Documents().Export(context.Background(), &api.ExportDocumentsParams{}) assert.Nil(t, err) - resultBytes, err := ioutil.ReadAll(result) + resultBytes, err := io.ReadAll(result) assert.Nil(t, err) assert.Equal(t, string(expectedBytes), string(resultBytes)) } @@ -330,7 +329,7 @@ func TestDocumentsExportOnHttpStatusErrorCodeReturnsError(t *testing.T) { ExportDocuments(gomock.Not(gomock.Nil()), "companies", &api.ExportDocumentsParams{}). Return(&http.Response{ StatusCode: http.StatusInternalServerError, - Body: ioutil.NopCloser(strings.NewReader("Internal server error")), + Body: io.NopCloser(strings.NewReader("Internal server error")), }, nil). Times(1) diff --git a/typesense/import_test.go b/typesense/import_test.go index 726011d..4459f2a 100644 --- a/typesense/import_test.go +++ b/typesense/import_test.go @@ -5,7 +5,6 @@ import ( "context" "errors" "io" - "io/ioutil" "net/http" "reflect" "strings" @@ -23,7 +22,7 @@ type eqReaderMatcher struct { } func eqReader(r io.Reader) gomock.Matcher { - allBytes, err := ioutil.ReadAll(r) + allBytes, err := io.ReadAll(r) if err != nil { panic(err) } @@ -35,7 +34,7 @@ func (m *eqReaderMatcher) Matches(x interface{}) bool { return false } r := x.(io.Reader) - allBytes, err := ioutil.ReadAll(r) + allBytes, err := io.ReadAll(r) if err != nil { panic(err) } @@ -66,7 +65,7 @@ func TestDocumentsImportWithOneDocument(t *testing.T) { "companies", expectedParams, "application/octet-stream", eqReader(expectedBody)). Return(&http.Response{ StatusCode: http.StatusOK, - Body: ioutil.NopCloser(strings.NewReader(expectedResultString)), + Body: io.NopCloser(strings.NewReader(expectedResultString)), }, nil). Times(1) @@ -116,7 +115,7 @@ func TestDocumentsImportWithOneDocumentAndInvalidResultJsonReturnsError(t *testi "companies", expectedParams, "application/octet-stream", eqReader(expectedBody)). Return(&http.Response{ StatusCode: http.StatusOK, - Body: ioutil.NopCloser(strings.NewReader(expectedResultString)), + Body: io.NopCloser(strings.NewReader(expectedResultString)), }, nil). Times(1) @@ -182,7 +181,7 @@ func TestDocumentsImportOnHttpStatusErrorCodeReturnsError(t *testing.T) { "companies", gomock.Any(), "application/octet-stream", gomock.Any()). Return(&http.Response{ StatusCode: http.StatusInternalServerError, - Body: ioutil.NopCloser(strings.NewReader("Internal server error")), + Body: io.NopCloser(strings.NewReader("Internal server error")), }, nil). Times(1) @@ -220,7 +219,7 @@ func TestDocumentsImportWithTwoDocuments(t *testing.T) { "companies", expectedParams, "application/octet-stream", eqReader(expectedBody)). Return(&http.Response{ StatusCode: http.StatusOK, - Body: ioutil.NopCloser(strings.NewReader(expectedResultString)), + Body: io.NopCloser(strings.NewReader(expectedResultString)), }, nil). Times(1) @@ -254,7 +253,7 @@ func TestDocumentsImportWithActionOnly(t *testing.T) { "companies", expectedParams, "application/octet-stream", gomock.Any()). Return(&http.Response{ StatusCode: http.StatusOK, - Body: ioutil.NopCloser(strings.NewReader(`{"success": true}`)), + Body: io.NopCloser(strings.NewReader(`{"success": true}`)), }, nil). Times(1) @@ -284,7 +283,7 @@ func TestDocumentsImportWithBatchSizeOnly(t *testing.T) { "companies", expectedParams, "application/octet-stream", gomock.Any()). Return(&http.Response{ StatusCode: http.StatusOK, - Body: ioutil.NopCloser(strings.NewReader(`{"success": true}`)), + Body: io.NopCloser(strings.NewReader(`{"success": true}`)), }, nil). Times(1) @@ -316,7 +315,7 @@ func TestDocumentsImportJsonl(t *testing.T) { "companies", expectedParams, "application/octet-stream", eqReader(expectedBody)). Return(&http.Response{ StatusCode: http.StatusOK, - Body: ioutil.NopCloser(bytes.NewBuffer(expectedBytes)), + Body: io.NopCloser(bytes.NewBuffer(expectedBytes)), }, nil). Times(1) @@ -329,7 +328,7 @@ func TestDocumentsImportJsonl(t *testing.T) { result, err := client.Collection("companies").Documents().ImportJsonl(context.Background(), importBody, params) assert.Nil(t, err) - resultBytes, err := ioutil.ReadAll(result) + resultBytes, err := io.ReadAll(result) assert.Nil(t, err) assert.Equal(t, string(expectedBytes), string(resultBytes)) } @@ -365,7 +364,7 @@ func TestDocumentsImportJsonlOnHttpStatusErrorCodeReturnsError(t *testing.T) { gomock.Any(), gomock.Any(), "application/octet-stream", gomock.Any()). Return(&http.Response{ StatusCode: http.StatusInternalServerError, - Body: ioutil.NopCloser(strings.NewReader("Internal server error")), + Body: io.NopCloser(strings.NewReader("Internal server error")), }, nil). Times(1) @@ -394,7 +393,7 @@ func TestDocumentsImportJsonlWithActionOnly(t *testing.T) { "companies", expectedParams, "application/octet-stream", gomock.Any()). Return(&http.Response{ StatusCode: http.StatusOK, - Body: ioutil.NopCloser(strings.NewReader(`{"success": true}`)), + Body: io.NopCloser(strings.NewReader(`{"success": true}`)), }, nil). Times(1) @@ -422,7 +421,7 @@ func TestDocumentsImportJsonlWithBatchSizeOnly(t *testing.T) { "companies", expectedParams, "application/octet-stream", gomock.Any()). Return(&http.Response{ StatusCode: http.StatusOK, - Body: ioutil.NopCloser(strings.NewReader(`{"success": true}`)), + Body: io.NopCloser(strings.NewReader(`{"success": true}`)), }, nil). Times(1) From 77722d7593dc578957a7cad4d53f760a56244c79 Mon Sep 17 00:00:00 2001 From: Hayden Date: Thu, 3 Oct 2024 22:17:06 +0700 Subject: [PATCH 19/19] feat: add dirty values parameter for single document indexing - add `dirty_values` parameter for .Create, .Upsert and .Update methods - pull latest oapi-spec changes --- typesense/api/client.go | 6 ++++ typesense/api/client_gen.go | 52 +++++++++++++++++++-------- typesense/api/generator/generator.yml | 17 ++++++--- typesense/api/generator/openapi.yml | 41 ++++++++++++--------- typesense/api/types_gen.go | 7 ++++ typesense/document.go | 8 +++-- typesense/document_test.go | 14 ++++---- typesense/documents.go | 18 ++++------ typesense/documents_test.go | 16 ++++----- typesense/mocks/mock_client.go | 32 ++++++++--------- typesense/test/dbhelpers_test.go | 2 +- typesense/test/document_test.go | 3 +- typesense/test/documents_test.go | 12 +++---- typesense/test/multi_search_test.go | 2 +- 14 files changed, 139 insertions(+), 91 deletions(-) diff --git a/typesense/api/client.go b/typesense/api/client.go index ce03473..8ae0dfa 100644 --- a/typesense/api/client.go +++ b/typesense/api/client.go @@ -16,3 +16,9 @@ func WithAPIKey(apiKey string) ClientOption { return nil } } + +// Manually defining this unreferenced schema here instead of disabling oapi-codegen schema pruning + +type DocumentIndexParameters struct { + DirtyValues *DirtyValues `json:"dirty_values,omitempty"` +} diff --git a/typesense/api/client_gen.go b/typesense/api/client_gen.go index ac57a69..2695586 100644 --- a/typesense/api/client_gen.go +++ b/typesense/api/client_gen.go @@ -175,9 +175,9 @@ type ClientInterface interface { GetDocument(ctx context.Context, collectionName string, documentId string, reqEditors ...RequestEditorFn) (*http.Response, error) // UpdateDocumentWithBody request with any body - UpdateDocumentWithBody(ctx context.Context, collectionName string, documentId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + UpdateDocumentWithBody(ctx context.Context, collectionName string, documentId string, params *UpdateDocumentParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - UpdateDocument(ctx context.Context, collectionName string, documentId string, body UpdateDocumentJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + UpdateDocument(ctx context.Context, collectionName string, documentId string, params *UpdateDocumentParams, body UpdateDocumentJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // GetSearchOverrides request GetSearchOverrides(ctx context.Context, collectionName string, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -664,8 +664,8 @@ func (c *Client) GetDocument(ctx context.Context, collectionName string, documen return c.Client.Do(req) } -func (c *Client) UpdateDocumentWithBody(ctx context.Context, collectionName string, documentId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateDocumentRequestWithBody(c.Server, collectionName, documentId, contentType, body) +func (c *Client) UpdateDocumentWithBody(ctx context.Context, collectionName string, documentId string, params *UpdateDocumentParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateDocumentRequestWithBody(c.Server, collectionName, documentId, params, contentType, body) if err != nil { return nil, err } @@ -676,8 +676,8 @@ func (c *Client) UpdateDocumentWithBody(ctx context.Context, collectionName stri return c.Client.Do(req) } -func (c *Client) UpdateDocument(ctx context.Context, collectionName string, documentId string, body UpdateDocumentJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateDocumentRequest(c.Server, collectionName, documentId, body) +func (c *Client) UpdateDocument(ctx context.Context, collectionName string, documentId string, params *UpdateDocumentParams, body UpdateDocumentJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateDocumentRequest(c.Server, collectionName, documentId, params, body) if err != nil { return nil, err } @@ -3361,18 +3361,18 @@ func NewGetDocumentRequest(server string, collectionName string, documentId stri } // NewUpdateDocumentRequest calls the generic UpdateDocument builder with application/json body -func NewUpdateDocumentRequest(server string, collectionName string, documentId string, body UpdateDocumentJSONRequestBody) (*http.Request, error) { +func NewUpdateDocumentRequest(server string, collectionName string, documentId string, params *UpdateDocumentParams, body UpdateDocumentJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewUpdateDocumentRequestWithBody(server, collectionName, documentId, "application/json", bodyReader) + return NewUpdateDocumentRequestWithBody(server, collectionName, documentId, params, "application/json", bodyReader) } // NewUpdateDocumentRequestWithBody generates requests for UpdateDocument with any type of body -func NewUpdateDocumentRequestWithBody(server string, collectionName string, documentId string, contentType string, body io.Reader) (*http.Request, error) { +func NewUpdateDocumentRequestWithBody(server string, collectionName string, documentId string, params *UpdateDocumentParams, contentType string, body io.Reader) (*http.Request, error) { var err error var pathParam0 string @@ -3404,6 +3404,28 @@ func NewUpdateDocumentRequestWithBody(server string, collectionName string, docu return nil, err } + if params != nil { + queryValues := queryURL.Query() + + if params.DirtyValues != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "dirty_values", runtime.ParamLocationQuery, *params.DirtyValues); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + queryURL.RawQuery = queryValues.Encode() + } + req, err := http.NewRequest("PATCH", queryURL.String(), body) if err != nil { return nil, err @@ -5766,9 +5788,9 @@ type ClientWithResponsesInterface interface { GetDocumentWithResponse(ctx context.Context, collectionName string, documentId string, reqEditors ...RequestEditorFn) (*GetDocumentResponse, error) // UpdateDocumentWithBodyWithResponse request with any body - UpdateDocumentWithBodyWithResponse(ctx context.Context, collectionName string, documentId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateDocumentResponse, error) + UpdateDocumentWithBodyWithResponse(ctx context.Context, collectionName string, documentId string, params *UpdateDocumentParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateDocumentResponse, error) - UpdateDocumentWithResponse(ctx context.Context, collectionName string, documentId string, body UpdateDocumentJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateDocumentResponse, error) + UpdateDocumentWithResponse(ctx context.Context, collectionName string, documentId string, params *UpdateDocumentParams, body UpdateDocumentJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateDocumentResponse, error) // GetSearchOverridesWithResponse request GetSearchOverridesWithResponse(ctx context.Context, collectionName string, reqEditors ...RequestEditorFn) (*GetSearchOverridesResponse, error) @@ -7440,16 +7462,16 @@ func (c *ClientWithResponses) GetDocumentWithResponse(ctx context.Context, colle } // UpdateDocumentWithBodyWithResponse request with arbitrary body returning *UpdateDocumentResponse -func (c *ClientWithResponses) UpdateDocumentWithBodyWithResponse(ctx context.Context, collectionName string, documentId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateDocumentResponse, error) { - rsp, err := c.UpdateDocumentWithBody(ctx, collectionName, documentId, contentType, body, reqEditors...) +func (c *ClientWithResponses) UpdateDocumentWithBodyWithResponse(ctx context.Context, collectionName string, documentId string, params *UpdateDocumentParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateDocumentResponse, error) { + rsp, err := c.UpdateDocumentWithBody(ctx, collectionName, documentId, params, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseUpdateDocumentResponse(rsp) } -func (c *ClientWithResponses) UpdateDocumentWithResponse(ctx context.Context, collectionName string, documentId string, body UpdateDocumentJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateDocumentResponse, error) { - rsp, err := c.UpdateDocument(ctx, collectionName, documentId, body, reqEditors...) +func (c *ClientWithResponses) UpdateDocumentWithResponse(ctx context.Context, collectionName string, documentId string, params *UpdateDocumentParams, body UpdateDocumentJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateDocumentResponse, error) { + rsp, err := c.UpdateDocument(ctx, collectionName, documentId, params, body, reqEditors...) if err != nil { return nil, err } diff --git a/typesense/api/generator/generator.yml b/typesense/api/generator/generator.yml index 72feaf2..804f2cf 100644 --- a/typesense/api/generator/generator.yml +++ b/typesense/api/generator/generator.yml @@ -472,6 +472,8 @@ components: type: string project_id: type: string + url: + type: string required: - model_name type: object @@ -2151,6 +2153,11 @@ paths: required: true schema: type: string + - description: Dealing with Dirty Data + in: query + name: dirty_values + schema: + $ref: '#/components/schemas/DirtyValues' requestBody: content: application/json: @@ -2605,7 +2612,7 @@ paths: summary: List all collection overrides tags: - documents - - promote + - curation /collections/{collectionName}/overrides/{overrideId}: delete: operationId: deleteSearchOverride @@ -2638,7 +2645,7 @@ paths: summary: Delete an override associated with a collection tags: - documents - - promote + - curation get: description: Retrieve the details of a search override, given its id. operationId: getSearchOverride @@ -2705,7 +2712,7 @@ paths: summary: Create or update an override to promote certain documents over others tags: - documents - - promote + - curation /collections/{collectionName}/synonyms: get: operationId: getSearchSynonyms @@ -3657,11 +3664,11 @@ tags: description: Find out more url: https://typesense.org/api/#index-document name: documents - - description: Promote certain documents over others + - description: Hand-curate search results based on conditional business rules externalDocs: description: Find out more url: https://typesense.org/docs/0.23.0/api/#curation - name: promote + name: curation - description: Typesense can aggregate search queries for both analytics purposes and for query suggestions. externalDocs: description: Find out more diff --git a/typesense/api/generator/openapi.yml b/typesense/api/generator/openapi.yml index 622fa7c..296c508 100644 --- a/typesense/api/generator/openapi.yml +++ b/typesense/api/generator/openapi.yml @@ -19,8 +19,8 @@ tags: externalDocs: description: Find out more url: https://typesense.org/api/#index-document - - name: promote - description: Promote certain documents over others + - name: curation + description: Hand-curate search results based on conditional business rules externalDocs: description: Find out more url: https://typesense.org/docs/0.23.0/api/#curation @@ -412,7 +412,7 @@ paths: get: tags: - documents - - promote + - curation summary: List all collection overrides operationId: getSearchOverrides parameters: @@ -460,7 +460,7 @@ paths: put: tags: - documents - - promote + - curation summary: Create or update an override to promote certain documents over others description: Create or update an override to promote certain documents over others. @@ -502,7 +502,7 @@ paths: delete: tags: - documents - - promote + - curation summary: Delete an override associated with a collection operationId: deleteSearchOverride parameters: @@ -842,6 +842,11 @@ paths: required: true schema: type: string + - name: dirty_values + in: query + description: Dealing with Dirty Data + schema: + $ref: "#/components/schemas/DirtyValues" requestBody: description: The document object with fields to be updated content: @@ -1784,12 +1789,12 @@ components: maxLength: 1 default: [] enable_nested_fields: - type: boolean - description: - Enables experimental support at a collection level for nested object or object array fields. - This field is only available if the Typesense server is version `0.24.0.rcn34` or later. - default: false - example: true + type: boolean + description: + Enables experimental support at a collection level for nested object or object array fields. + This field is only available if the Typesense server is version `0.24.0.rcn34` or later. + default: false + example: true symbols_to_index: type: array description: > @@ -1919,6 +1924,8 @@ components: type: string api_key: type: string + url: + type: string access_token: type: string client_id: @@ -2436,8 +2443,8 @@ components: If infix index is enabled for this field, infix searching can be done on a per-field basis by sending a comma separated string parameter called infix to the search query. This parameter can have 3 values; `off` infix search is disabled, which is default - `always` infix search is performed along with regular search - `fallback` infix search is performed if regular search does not produce results + `always` infix search is performed along with regular search + `fallback` infix search is performed if regular search does not produce results type: string max_extra_prefix: @@ -2773,7 +2780,7 @@ components: type: boolean conversation_model_id: description: > - The Id of Conversation Model to be used. + The Id of Conversation Model to be used. type: string conversation_id: description: > @@ -2821,8 +2828,8 @@ components: If infix index is enabled for this field, infix searching can be done on a per-field basis by sending a comma separated string parameter called infix to the search query. This parameter can have 3 values; `off` infix search is disabled, which is default - `always` infix search is performed along with regular search - `fallback` infix search is performed if regular search does not produce results + `always` infix search is performed along with regular search + `fallback` infix search is performed if regular search does not produce results type: string max_extra_prefix: @@ -3143,7 +3150,7 @@ components: type: boolean conversation_model_id: description: > - The Id of Conversation Model to be used. + The Id of Conversation Model to be used. type: string conversation_id: description: > diff --git a/typesense/api/types_gen.go b/typesense/api/types_gen.go index e9a8da1..b425961 100644 --- a/typesense/api/types_gen.go +++ b/typesense/api/types_gen.go @@ -374,6 +374,7 @@ type Field struct { ClientSecret *string `json:"client_secret,omitempty"` ModelName string `json:"model_name"` ProjectId *string `json:"project_id,omitempty"` + Url *string `json:"url,omitempty"` } `json:"model_config"` } `json:"embed,omitempty"` Facet *bool `json:"facet,omitempty"` @@ -1440,6 +1441,12 @@ type SearchCollectionParams struct { // UpdateDocumentJSONBody defines parameters for UpdateDocument. type UpdateDocumentJSONBody = interface{} +// UpdateDocumentParams defines parameters for UpdateDocument. +type UpdateDocumentParams struct { + // DirtyValues Dealing with Dirty Data + DirtyValues *DirtyValues `form:"dirty_values,omitempty" json:"dirty_values,omitempty"` +} + // MultiSearchParams defines parameters for MultiSearch. type MultiSearchParams struct { CacheTtl *int `form:"cache_ttl,omitempty" json:"cache_ttl,omitempty"` diff --git a/typesense/document.go b/typesense/document.go index 360f3de..e244d0f 100644 --- a/typesense/document.go +++ b/typesense/document.go @@ -5,11 +5,13 @@ import ( "encoding/json" "io" "strings" + + "github.com/typesense/typesense-go/v2/typesense/api" ) type DocumentInterface[T any] interface { Retrieve(ctx context.Context) (T, error) - Update(ctx context.Context, document any) (T, error) + Update(ctx context.Context, document any, params *api.DocumentIndexParameters) (T, error) Delete(ctx context.Context) (T, error) } @@ -39,9 +41,9 @@ func (d *document[T]) Retrieve(ctx context.Context) (resp T, err error) { return resp, nil } -func (d *document[T]) Update(ctx context.Context, document any) (resp T, err error) { +func (d *document[T]) Update(ctx context.Context, document any, params *api.DocumentIndexParameters) (resp T, err error) { response, err := d.apiClient.UpdateDocument(ctx, - d.collectionName, d.documentID, document) + d.collectionName, d.documentID, &api.UpdateDocumentParams{DirtyValues: params.DirtyValues}, document) if err != nil { return resp, err } diff --git a/typesense/document_test.go b/typesense/document_test.go index 6ee38bf..c968fb3 100644 --- a/typesense/document_test.go +++ b/typesense/document_test.go @@ -6,6 +6,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/typesense/typesense-go/v2/typesense/api" + "github.com/typesense/typesense-go/v2/typesense/api/pointer" "github.com/typesense/typesense-go/v2/typesense/mocks" "go.uber.org/mock/gomock" ) @@ -71,13 +73,13 @@ func TestDocumentUpdate(t *testing.T) { notNill := gomock.Not(gomock.Nil()) mockAPIClient.EXPECT(). - UpdateDocument(notNill, "companies", "123", expectedDocument). + UpdateDocument(notNill, "companies", "123", &api.UpdateDocumentParams{DirtyValues: pointer.Any(api.CoerceOrDrop)}, expectedDocument). Return(createResponse(200, "", mockedResult), nil). Times(1) client := NewClient(WithAPIClient(mockAPIClient)) document := createNewDocument() - result, err := client.Collection("companies").Document("123").Update(context.Background(), document) + result, err := client.Collection("companies").Document("123").Update(context.Background(), document, &api.DocumentIndexParameters{DirtyValues: pointer.Any(api.CoerceOrDrop)}) assert.Nil(t, err) assert.Equal(t, expectedResult, result) @@ -92,13 +94,13 @@ func TestDocumentUpdateOnApiClientErrorReturnsError(t *testing.T) { notNill := gomock.Not(gomock.Nil()) mockAPIClient.EXPECT(). - UpdateDocument(notNill, "companies", "123", expectedDocument). + UpdateDocument(notNill, "companies", "123", &api.UpdateDocumentParams{}, expectedDocument). Return(nil, errors.New("failed request")). Times(1) client := NewClient(WithAPIClient(mockAPIClient)) document := createNewDocument() - _, err := client.Collection("companies").Document("123").Update(context.Background(), document) + _, err := client.Collection("companies").Document("123").Update(context.Background(), document, &api.DocumentIndexParameters{}) assert.NotNil(t, err) } @@ -111,13 +113,13 @@ func TestDocumentUpdateOnHttpStatusErrorCodeReturnsError(t *testing.T) { notNill := gomock.Not(gomock.Nil()) mockAPIClient.EXPECT(). - UpdateDocument(notNill, "companies", "123", expectedDocument). + UpdateDocument(notNill, "companies", "123", &api.UpdateDocumentParams{}, expectedDocument). Return(createResponse(500, "Internal server error", nil), nil). Times(1) client := NewClient(WithAPIClient(mockAPIClient)) document := createNewDocument() - _, err := client.Collection("companies").Document("123").Update(context.Background(), document) + _, err := client.Collection("companies").Document("123").Update(context.Background(), document, &api.DocumentIndexParameters{}) assert.NotNil(t, err) } diff --git a/typesense/documents.go b/typesense/documents.go index 3e057be..8bfd56c 100644 --- a/typesense/documents.go +++ b/typesense/documents.go @@ -19,11 +19,11 @@ const ( // DocumentsInterface is a type for Documents API operations type DocumentsInterface interface { // Create returns indexed document - Create(ctx context.Context, document interface{}) (map[string]interface{}, error) + Create(ctx context.Context, document interface{}, params *api.DocumentIndexParameters) (map[string]interface{}, error) // Update updates documents matching the filter_by condition Update(ctx context.Context, updateFields interface{}, params *api.UpdateDocumentsParams) (int, error) // Upsert returns indexed/updated document - Upsert(context.Context, interface{}) (map[string]interface{}, error) + Upsert(ctx context.Context, document interface{}, params *api.DocumentIndexParameters) (map[string]interface{}, error) // Delete returns number of deleted documents Delete(ctx context.Context, filter *api.DeleteDocumentsParams) (int, error) // Search performs document search in collection @@ -37,8 +37,6 @@ type DocumentsInterface interface { // response indicates the result of each document present in the // request body (in the same order). ImportJsonl(ctx context.Context, body io.Reader, params *api.ImportDocumentsParams) (io.ReadCloser, error) - // Index returns indexed document, this method allow configuration of dirty values behavior and action mode. Default action: create - Index(ctx context.Context, document interface{}, params *api.IndexDocumentParams) (map[string]interface{}, error) } // documents is internal implementation of DocumentsInterface @@ -59,12 +57,8 @@ func (d *documents) indexDocument(ctx context.Context, document interface{}, par return *response.JSON201, nil } -func (d *documents) Index(ctx context.Context, document interface{}, params *api.IndexDocumentParams) (map[string]interface{}, error) { - return d.indexDocument(ctx, document, params) -} - -func (d *documents) Create(ctx context.Context, document interface{}) (map[string]interface{}, error) { - return d.indexDocument(ctx, document, &api.IndexDocumentParams{}) +func (d *documents) Create(ctx context.Context, document interface{}, params *api.DocumentIndexParameters) (map[string]interface{}, error) { + return d.indexDocument(ctx, document, &api.IndexDocumentParams{DirtyValues: params.DirtyValues}) } func (d *documents) Update(ctx context.Context, updateFields interface{}, params *api.UpdateDocumentsParams) (int, error) { @@ -79,8 +73,8 @@ func (d *documents) Update(ctx context.Context, updateFields interface{}, params return response.JSON200.NumUpdated, nil } -func (d *documents) Upsert(ctx context.Context, document interface{}) (map[string]interface{}, error) { - return d.indexDocument(ctx, document, &api.IndexDocumentParams{Action: pointer.Any(api.Upsert)}) +func (d *documents) Upsert(ctx context.Context, document interface{}, params *api.DocumentIndexParameters) (map[string]interface{}, error) { + return d.indexDocument(ctx, document, &api.IndexDocumentParams{Action: pointer.Any(api.Upsert), DirtyValues: params.DirtyValues}) } func (d *documents) Delete(ctx context.Context, filter *api.DeleteDocumentsParams) (int, error) { diff --git a/typesense/documents_test.go b/typesense/documents_test.go index 2dc8d97..dbd6150 100644 --- a/typesense/documents_test.go +++ b/typesense/documents_test.go @@ -53,7 +53,7 @@ func TestDocumentCreate(t *testing.T) { mockedResult := createNewDocumentResponse() notNill := gomock.Not(gomock.Nil()) - indexParams := &api.IndexDocumentParams{} + indexParams := &api.IndexDocumentParams{DirtyValues: pointer.Any(api.CoerceOrDrop)} mockAPIClient.EXPECT(). IndexDocumentWithResponse(notNill, "companies", indexParams, expectedDocument). Return(&api.IndexDocumentResponse{ @@ -63,7 +63,7 @@ func TestDocumentCreate(t *testing.T) { client := NewClient(WithAPIClient(mockAPIClient)) document := createNewDocument() - result, err := client.Collection("companies").Documents().Create(context.Background(), document) + result, err := client.Collection("companies").Documents().Create(context.Background(), document, &api.DocumentIndexParameters{DirtyValues: pointer.Any(api.CoerceOrDrop)}) assert.Nil(t, err) assert.Equal(t, expectedResult, result) @@ -84,7 +84,7 @@ func TestDocumentCreateOnApiClientErrorReturnsError(t *testing.T) { Times(1) client := NewClient(WithAPIClient(mockAPIClient)) - _, err := client.Collection("companies").Documents().Create(context.Background(), newDocument) + _, err := client.Collection("companies").Documents().Create(context.Background(), newDocument, &api.DocumentIndexParameters{}) assert.NotNil(t, err) } @@ -108,7 +108,7 @@ func TestDocumentCreateOnHttpStatusErrorCodeReturnsError(t *testing.T) { Times(1) client := NewClient(WithAPIClient(mockAPIClient)) - _, err := client.Collection("companies").Documents().Create(context.Background(), newDocument) + _, err := client.Collection("companies").Documents().Create(context.Background(), newDocument, &api.DocumentIndexParameters{}) assert.NotNil(t, err) } @@ -122,7 +122,7 @@ func TestDocumentUpsert(t *testing.T) { mockedResult := createNewDocumentResponse() notNill := gomock.Not(gomock.Nil()) - indexParams := &api.IndexDocumentParams{Action: pointer.Any(api.Upsert)} + indexParams := &api.IndexDocumentParams{Action: pointer.Any(api.Upsert), DirtyValues: pointer.Any(api.CoerceOrDrop)} mockAPIClient.EXPECT(). IndexDocumentWithResponse(notNill, "companies", indexParams, newDocument). Return(&api.IndexDocumentResponse{ @@ -131,7 +131,7 @@ func TestDocumentUpsert(t *testing.T) { Times(1) client := NewClient(WithAPIClient(mockAPIClient)) - result, err := client.Collection("companies").Documents().Upsert(context.Background(), newDocument) + result, err := client.Collection("companies").Documents().Upsert(context.Background(), newDocument, &api.DocumentIndexParameters{DirtyValues: pointer.Any(api.CoerceOrDrop)}) assert.Nil(t, err) assert.Equal(t, expectedResult, result) @@ -152,7 +152,7 @@ func TestDocumentUpsertOnApiClientErrorReturnsError(t *testing.T) { Times(1) client := NewClient(WithAPIClient(mockAPIClient)) - _, err := client.Collection("companies").Documents().Upsert(context.Background(), newDocument) + _, err := client.Collection("companies").Documents().Upsert(context.Background(), newDocument, &api.DocumentIndexParameters{}) assert.NotNil(t, err) } @@ -176,7 +176,7 @@ func TestDocumentUpsertOnHttpStatusErrorCodeReturnsError(t *testing.T) { Times(1) client := NewClient(WithAPIClient(mockAPIClient)) - _, err := client.Collection("companies").Documents().Upsert(context.Background(), newDocument) + _, err := client.Collection("companies").Documents().Upsert(context.Background(), newDocument, &api.DocumentIndexParameters{}) assert.NotNil(t, err) } diff --git a/typesense/mocks/mock_client.go b/typesense/mocks/mock_client.go index 7092a9a..d24b223 100644 --- a/typesense/mocks/mock_client.go +++ b/typesense/mocks/mock_client.go @@ -2283,9 +2283,9 @@ func (mr *MockAPIClientInterfaceMockRecorder) UpdateConversationModelWithRespons } // UpdateDocument mocks base method. -func (m *MockAPIClientInterface) UpdateDocument(ctx context.Context, collectionName, documentId string, body api.UpdateDocumentJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +func (m *MockAPIClientInterface) UpdateDocument(ctx context.Context, collectionName, documentId string, params *api.UpdateDocumentParams, body api.UpdateDocumentJSONRequestBody, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() - varargs := []any{ctx, collectionName, documentId, body} + varargs := []any{ctx, collectionName, documentId, params, body} for _, a := range reqEditors { varargs = append(varargs, a) } @@ -2296,16 +2296,16 @@ func (m *MockAPIClientInterface) UpdateDocument(ctx context.Context, collectionN } // UpdateDocument indicates an expected call of UpdateDocument. -func (mr *MockAPIClientInterfaceMockRecorder) UpdateDocument(ctx, collectionName, documentId, body any, reqEditors ...any) *gomock.Call { +func (mr *MockAPIClientInterfaceMockRecorder) UpdateDocument(ctx, collectionName, documentId, params, body any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, collectionName, documentId, body}, reqEditors...) + varargs := append([]any{ctx, collectionName, documentId, params, body}, reqEditors...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDocument", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateDocument), varargs...) } // UpdateDocumentWithBody mocks base method. -func (m *MockAPIClientInterface) UpdateDocumentWithBody(ctx context.Context, collectionName, documentId, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +func (m *MockAPIClientInterface) UpdateDocumentWithBody(ctx context.Context, collectionName, documentId string, params *api.UpdateDocumentParams, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() - varargs := []any{ctx, collectionName, documentId, contentType, body} + varargs := []any{ctx, collectionName, documentId, params, contentType, body} for _, a := range reqEditors { varargs = append(varargs, a) } @@ -2316,16 +2316,16 @@ func (m *MockAPIClientInterface) UpdateDocumentWithBody(ctx context.Context, col } // UpdateDocumentWithBody indicates an expected call of UpdateDocumentWithBody. -func (mr *MockAPIClientInterfaceMockRecorder) UpdateDocumentWithBody(ctx, collectionName, documentId, contentType, body any, reqEditors ...any) *gomock.Call { +func (mr *MockAPIClientInterfaceMockRecorder) UpdateDocumentWithBody(ctx, collectionName, documentId, params, contentType, body any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, collectionName, documentId, contentType, body}, reqEditors...) + varargs := append([]any{ctx, collectionName, documentId, params, contentType, body}, reqEditors...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDocumentWithBody", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateDocumentWithBody), varargs...) } // UpdateDocumentWithBodyWithResponse mocks base method. -func (m *MockAPIClientInterface) UpdateDocumentWithBodyWithResponse(ctx context.Context, collectionName, documentId, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*api.UpdateDocumentResponse, error) { +func (m *MockAPIClientInterface) UpdateDocumentWithBodyWithResponse(ctx context.Context, collectionName, documentId string, params *api.UpdateDocumentParams, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*api.UpdateDocumentResponse, error) { m.ctrl.T.Helper() - varargs := []any{ctx, collectionName, documentId, contentType, body} + varargs := []any{ctx, collectionName, documentId, params, contentType, body} for _, a := range reqEditors { varargs = append(varargs, a) } @@ -2336,16 +2336,16 @@ func (m *MockAPIClientInterface) UpdateDocumentWithBodyWithResponse(ctx context. } // UpdateDocumentWithBodyWithResponse indicates an expected call of UpdateDocumentWithBodyWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) UpdateDocumentWithBodyWithResponse(ctx, collectionName, documentId, contentType, body any, reqEditors ...any) *gomock.Call { +func (mr *MockAPIClientInterfaceMockRecorder) UpdateDocumentWithBodyWithResponse(ctx, collectionName, documentId, params, contentType, body any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, collectionName, documentId, contentType, body}, reqEditors...) + varargs := append([]any{ctx, collectionName, documentId, params, contentType, body}, reqEditors...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDocumentWithBodyWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateDocumentWithBodyWithResponse), varargs...) } // UpdateDocumentWithResponse mocks base method. -func (m *MockAPIClientInterface) UpdateDocumentWithResponse(ctx context.Context, collectionName, documentId string, body api.UpdateDocumentJSONRequestBody, reqEditors ...api.RequestEditorFn) (*api.UpdateDocumentResponse, error) { +func (m *MockAPIClientInterface) UpdateDocumentWithResponse(ctx context.Context, collectionName, documentId string, params *api.UpdateDocumentParams, body api.UpdateDocumentJSONRequestBody, reqEditors ...api.RequestEditorFn) (*api.UpdateDocumentResponse, error) { m.ctrl.T.Helper() - varargs := []any{ctx, collectionName, documentId, body} + varargs := []any{ctx, collectionName, documentId, params, body} for _, a := range reqEditors { varargs = append(varargs, a) } @@ -2356,9 +2356,9 @@ func (m *MockAPIClientInterface) UpdateDocumentWithResponse(ctx context.Context, } // UpdateDocumentWithResponse indicates an expected call of UpdateDocumentWithResponse. -func (mr *MockAPIClientInterfaceMockRecorder) UpdateDocumentWithResponse(ctx, collectionName, documentId, body any, reqEditors ...any) *gomock.Call { +func (mr *MockAPIClientInterfaceMockRecorder) UpdateDocumentWithResponse(ctx, collectionName, documentId, params, body any, reqEditors ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, collectionName, documentId, body}, reqEditors...) + varargs := append([]any{ctx, collectionName, documentId, params, body}, reqEditors...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDocumentWithResponse", reflect.TypeOf((*MockAPIClientInterface)(nil).UpdateDocumentWithResponse), varargs...) } diff --git a/typesense/test/dbhelpers_test.go b/typesense/test/dbhelpers_test.go index 21c6972..dde658b 100644 --- a/typesense/test/dbhelpers_test.go +++ b/typesense/test/dbhelpers_test.go @@ -385,7 +385,7 @@ func createNewCollection(t *testing.T, namePrefix string) string { func createDocument(t *testing.T, collectionName string, document *testDocument) { t.Helper() - _, err := typesenseClient.Collection(collectionName).Documents().Create(context.Background(), document) + _, err := typesenseClient.Collection(collectionName).Documents().Create(context.Background(), document, &api.DocumentIndexParameters{}) require.NoError(t, err) } diff --git a/typesense/test/document_test.go b/typesense/test/document_test.go index ce21af1..77516b9 100644 --- a/typesense/test/document_test.go +++ b/typesense/test/document_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/typesense/typesense-go/v2/typesense" + "github.com/typesense/typesense-go/v2/typesense/api" ) func TestDocumentRetrieveGeneric(t *testing.T) { @@ -41,7 +42,7 @@ func TestDocumentUpdate(t *testing.T) { createDocument(t, collectionName, document) document.CompanyName = newCompanyName - typesenseClient.Collection(collectionName).Document("123").Update(context.Background(), document) + typesenseClient.Collection(collectionName).Document("123").Update(context.Background(), document, &api.DocumentIndexParameters{}) result, err := typesenseClient.Collection(collectionName).Document("123").Retrieve(context.Background()) diff --git a/typesense/test/documents_test.go b/typesense/test/documents_test.go index 611f844..53cb3e2 100644 --- a/typesense/test/documents_test.go +++ b/typesense/test/documents_test.go @@ -19,7 +19,7 @@ func TestDocumentCreate(t *testing.T) { expectedResult := newDocumentResponse("123") document := newDocument("123") - result, err := typesenseClient.Collection(collectionName).Documents().Create(context.Background(), document) + result, err := typesenseClient.Collection(collectionName).Documents().Create(context.Background(), document, &api.DocumentIndexParameters{}) require.NoError(t, err) require.Equal(t, expectedResult, result) @@ -35,7 +35,7 @@ func TestDocumentUpsertNewDocument(t *testing.T) { expectedResult := newDocumentResponse("123") document := newDocument("123") - result, err := typesenseClient.Collection(collectionName).Documents().Upsert(context.Background(), document) + result, err := typesenseClient.Collection(collectionName).Documents().Upsert(context.Background(), document, &api.DocumentIndexParameters{}) require.NoError(t, err) require.Equal(t, expectedResult, result) @@ -52,12 +52,12 @@ func TestDocumentUpsertExistingDocument(t *testing.T) { expectedResult := newDocumentResponse("123", withResponseCompanyName(newCompanyName)) document := newDocument("123") - _, err := typesenseClient.Collection(collectionName).Documents().Create(context.Background(), document) + _, err := typesenseClient.Collection(collectionName).Documents().Create(context.Background(), document, &api.DocumentIndexParameters{}) require.NoError(t, err) document.CompanyName = newCompanyName - result, err := typesenseClient.Collection(collectionName).Documents().Upsert(context.Background(), document) + result, err := typesenseClient.Collection(collectionName).Documents().Upsert(context.Background(), document, &api.DocumentIndexParameters{}) require.NoError(t, err) require.Equal(t, expectedResult, result) @@ -73,12 +73,12 @@ func TestDocumentsDelete(t *testing.T) { document := newDocument("123") document.NumEmployees = 5000 - _, err := typesenseClient.Collection(collectionName).Documents().Create(context.Background(), document) + _, err := typesenseClient.Collection(collectionName).Documents().Create(context.Background(), document, &api.DocumentIndexParameters{}) require.NoError(t, err) document = newDocument("124") document.NumEmployees = 7000 - _, err = typesenseClient.Collection(collectionName).Documents().Create(context.Background(), document) + _, err = typesenseClient.Collection(collectionName).Documents().Create(context.Background(), document, &api.DocumentIndexParameters{}) require.NoError(t, err) filter := &api.DeleteDocumentsParams{FilterBy: pointer.String("num_employees:>6500"), BatchSize: pointer.Int(100)} diff --git a/typesense/test/multi_search_test.go b/typesense/test/multi_search_test.go index 5daa4d7..de17e96 100644 --- a/typesense/test/multi_search_test.go +++ b/typesense/test/multi_search_test.go @@ -174,7 +174,7 @@ func TestMultiSearchVectorQuery(t *testing.T) { Vec: []float32{0.45, 0.222, 0.021, 0.1323}, } - _, err = typesenseClient.Collection("embeddings").Documents().Create(context.Background(), vecDoc) + _, err = typesenseClient.Collection("embeddings").Documents().Create(context.Background(), vecDoc, &api.DocumentIndexParameters{}) require.NoError(t, err) searchParams := &api.MultiSearchParams{}