feat: add StatelessMessage, StatelessRequest and GenerateStateless RPC

This commit is contained in:
Kaien 2026-05-07 13:00:55 +03:00
parent 1763962b7d
commit be5ac2dc40
3 changed files with 209 additions and 35 deletions

171
ai.pb.go
View File

@ -512,6 +512,112 @@ func (x *SessionStatusResponse) GetReasoningContent() string {
return ""
}
// StatelessMessage одно сообщение для stateless запроса (role + content)
type StatelessMessage struct {
state protoimpl.MessageState `protogen:"open.v1"`
Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"` // "system", "user", "assistant"
Content string `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` // Текст сообщения
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *StatelessMessage) Reset() {
*x = StatelessMessage{}
mi := &file_ai_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *StatelessMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StatelessMessage) ProtoMessage() {}
func (x *StatelessMessage) ProtoReflect() protoreflect.Message {
mi := &file_ai_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use StatelessMessage.ProtoReflect.Descriptor instead.
func (*StatelessMessage) Descriptor() ([]byte, []int) {
return file_ai_proto_rawDescGZIP(), []int{7}
}
func (x *StatelessMessage) GetRole() string {
if x != nil {
return x.Role
}
return ""
}
func (x *StatelessMessage) GetContent() string {
if x != nil {
return x.Content
}
return ""
}
// StatelessRequest для stateless генерации с полным контролем над messages
type StatelessRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Messages []*StatelessMessage `protobuf:"bytes,1,rep,name=messages,proto3" json:"messages,omitempty"` // Массив сообщений (system + history + user)
ModelName string `protobuf:"bytes,2,opt,name=model_name,json=modelName,proto3" json:"model_name,omitempty"` // Название модели (по умолчанию "venice-uncensored")
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *StatelessRequest) Reset() {
*x = StatelessRequest{}
mi := &file_ai_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *StatelessRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StatelessRequest) ProtoMessage() {}
func (x *StatelessRequest) ProtoReflect() protoreflect.Message {
mi := &file_ai_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use StatelessRequest.ProtoReflect.Descriptor instead.
func (*StatelessRequest) Descriptor() ([]byte, []int) {
return file_ai_proto_rawDescGZIP(), []int{8}
}
func (x *StatelessRequest) GetMessages() []*StatelessMessage {
if x != nil {
return x.Messages
}
return nil
}
func (x *StatelessRequest) GetModelName() string {
if x != nil {
return x.ModelName
}
return ""
}
// HealthCheckRequest для проверки здоровья сервиса
type HealthCheckRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
@ -521,7 +627,7 @@ type HealthCheckRequest struct {
func (x *HealthCheckRequest) Reset() {
*x = HealthCheckRequest{}
mi := &file_ai_proto_msgTypes[7]
mi := &file_ai_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -533,7 +639,7 @@ func (x *HealthCheckRequest) String() string {
func (*HealthCheckRequest) ProtoMessage() {}
func (x *HealthCheckRequest) ProtoReflect() protoreflect.Message {
mi := &file_ai_proto_msgTypes[7]
mi := &file_ai_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -546,7 +652,7 @@ func (x *HealthCheckRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use HealthCheckRequest.ProtoReflect.Descriptor instead.
func (*HealthCheckRequest) Descriptor() ([]byte, []int) {
return file_ai_proto_rawDescGZIP(), []int{7}
return file_ai_proto_rawDescGZIP(), []int{9}
}
// HealthCheckResponse для ответа на проверку здоровья
@ -560,7 +666,7 @@ type HealthCheckResponse struct {
func (x *HealthCheckResponse) Reset() {
*x = HealthCheckResponse{}
mi := &file_ai_proto_msgTypes[8]
mi := &file_ai_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -572,7 +678,7 @@ func (x *HealthCheckResponse) String() string {
func (*HealthCheckResponse) ProtoMessage() {}
func (x *HealthCheckResponse) ProtoReflect() protoreflect.Message {
mi := &file_ai_proto_msgTypes[8]
mi := &file_ai_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -585,7 +691,7 @@ func (x *HealthCheckResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use HealthCheckResponse.ProtoReflect.Descriptor instead.
func (*HealthCheckResponse) Descriptor() ([]byte, []int) {
return file_ai_proto_rawDescGZIP(), []int{8}
return file_ai_proto_rawDescGZIP(), []int{10}
}
func (x *HealthCheckResponse) GetServing() bool {
@ -651,13 +757,21 @@ const file_ai_proto_rawDesc = "" +
"\x05error\x18\x04 \x01(\tR\x05error\x12\x1f\n" +
"\vduration_ms\x18\x05 \x01(\x01R\n" +
"durationMs\x12+\n" +
"\x11reasoning_content\x18\x06 \x01(\tR\x10reasoningContent\"\x14\n" +
"\x11reasoning_content\x18\x06 \x01(\tR\x10reasoningContent\"@\n" +
"\x10StatelessMessage\x12\x12\n" +
"\x04role\x18\x01 \x01(\tR\x04role\x12\x18\n" +
"\acontent\x18\x02 \x01(\tR\acontent\"c\n" +
"\x10StatelessRequest\x120\n" +
"\bmessages\x18\x01 \x03(\v2\x14.ai.StatelessMessageR\bmessages\x12\x1d\n" +
"\n" +
"model_name\x18\x02 \x01(\tR\tmodelName\"\x14\n" +
"\x12HealthCheckRequest\"I\n" +
"\x13HealthCheckResponse\x12\x18\n" +
"\aserving\x18\x01 \x01(\bR\aserving\x12\x18\n" +
"\aversion\x18\x02 \x01(\tR\aversion2\x86\x02\n" +
"\aversion\x18\x02 \x01(\tR\aversion2\xc1\x02\n" +
"\tAIService\x12/\n" +
"\x0eGenerateAnswer\x12\r.ai.AIRequest\x1a\x0e.ai.AIResponse\x12>\n" +
"\x0eGenerateAnswer\x12\r.ai.AIRequest\x1a\x0e.ai.AIResponse\x129\n" +
"\x11GenerateStateless\x12\x14.ai.StatelessRequest\x1a\x0e.ai.AIResponse\x12>\n" +
"\vHealthCheck\x12\x16.ai.HealthCheckRequest\x1a\x17.ai.HealthCheckResponse\x12D\n" +
"\rCreateSession\x12\x18.ai.CreateSessionRequest\x1a\x19.ai.CreateSessionResponse\x12B\n" +
"\fAskInSession\x12\x17.ai.AskInSessionRequest\x1a\x19.ai.SessionStatusResponseB,Z*git.be.kaien.ru/l-ai/l-ai-core-proto/protob\x06proto3"
@ -674,7 +788,7 @@ func file_ai_proto_rawDescGZIP() []byte {
return file_ai_proto_rawDescData
}
var file_ai_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_ai_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_ai_proto_goTypes = []any{
(*AIRequest)(nil), // 0: ai.AIRequest
(*AnswerGenerationOptions)(nil), // 1: ai.AnswerGenerationOptions
@ -683,25 +797,30 @@ var file_ai_proto_goTypes = []any{
(*CreateSessionResponse)(nil), // 4: ai.CreateSessionResponse
(*AskInSessionRequest)(nil), // 5: ai.AskInSessionRequest
(*SessionStatusResponse)(nil), // 6: ai.SessionStatusResponse
(*HealthCheckRequest)(nil), // 7: ai.HealthCheckRequest
(*HealthCheckResponse)(nil), // 8: ai.HealthCheckResponse
(*StatelessMessage)(nil), // 7: ai.StatelessMessage
(*StatelessRequest)(nil), // 8: ai.StatelessRequest
(*HealthCheckRequest)(nil), // 9: ai.HealthCheckRequest
(*HealthCheckResponse)(nil), // 10: ai.HealthCheckResponse
}
var file_ai_proto_depIdxs = []int32{
1, // 0: ai.AIRequest.options:type_name -> ai.AnswerGenerationOptions
1, // 1: ai.AskInSessionRequest.options:type_name -> ai.AnswerGenerationOptions
0, // 2: ai.AIService.GenerateAnswer:input_type -> ai.AIRequest
7, // 3: ai.AIService.HealthCheck:input_type -> ai.HealthCheckRequest
3, // 4: ai.AIService.CreateSession:input_type -> ai.CreateSessionRequest
5, // 5: ai.AIService.AskInSession:input_type -> ai.AskInSessionRequest
2, // 6: ai.AIService.GenerateAnswer:output_type -> ai.AIResponse
8, // 7: ai.AIService.HealthCheck:output_type -> ai.HealthCheckResponse
4, // 8: ai.AIService.CreateSession:output_type -> ai.CreateSessionResponse
6, // 9: ai.AIService.AskInSession:output_type -> ai.SessionStatusResponse
6, // [6:10] is the sub-list for method output_type
2, // [2:6] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
7, // 2: ai.StatelessRequest.messages:type_name -> ai.StatelessMessage
0, // 3: ai.AIService.GenerateAnswer:input_type -> ai.AIRequest
8, // 4: ai.AIService.GenerateStateless:input_type -> ai.StatelessRequest
9, // 5: ai.AIService.HealthCheck:input_type -> ai.HealthCheckRequest
3, // 6: ai.AIService.CreateSession:input_type -> ai.CreateSessionRequest
5, // 7: ai.AIService.AskInSession:input_type -> ai.AskInSessionRequest
2, // 8: ai.AIService.GenerateAnswer:output_type -> ai.AIResponse
2, // 9: ai.AIService.GenerateStateless:output_type -> ai.AIResponse
10, // 10: ai.AIService.HealthCheck:output_type -> ai.HealthCheckResponse
4, // 11: ai.AIService.CreateSession:output_type -> ai.CreateSessionResponse
6, // 12: ai.AIService.AskInSession:output_type -> ai.SessionStatusResponse
8, // [8:13] is the sub-list for method output_type
3, // [3:8] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_ai_proto_init() }
@ -715,7 +834,7 @@ func file_ai_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ai_proto_rawDesc), len(file_ai_proto_rawDesc)),
NumEnums: 0,
NumMessages: 9,
NumMessages: 11,
NumExtensions: 0,
NumServices: 1,
},

View File

@ -61,6 +61,18 @@ message SessionStatusResponse {
string reasoning_content = 6; // Текст рассуждений (если включён режим reasoning)
}
// StatelessMessage одно сообщение для stateless запроса (role + content)
message StatelessMessage {
string role = 1; // "system", "user", "assistant"
string content = 2; // Текст сообщения
}
// StatelessRequest для stateless генерации с полным контролем над messages
message StatelessRequest {
repeated StatelessMessage messages = 1; // Массив сообщений (system + history + user)
string model_name = 2; // Название модели (по умолчанию "venice-uncensored")
}
// HealthCheckRequest для проверки здоровья сервиса
message HealthCheckRequest {}
@ -75,6 +87,9 @@ service AIService {
// GenerateAnswer генерирует ответ на запрос
rpc GenerateAnswer(AIRequest) returns (AIResponse);
// GenerateStateless генерирует ответ из массива messages (system+history+user)
rpc GenerateStateless(StatelessRequest) returns (AIResponse);
// HealthCheck проверяет здоровье сервиса
rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse);

View File

@ -20,6 +20,7 @@ const _ = grpc.SupportPackageIsVersion9
const (
AIService_GenerateAnswer_FullMethodName = "/ai.AIService/GenerateAnswer"
AIService_GenerateStateless_FullMethodName = "/ai.AIService/GenerateStateless"
AIService_HealthCheck_FullMethodName = "/ai.AIService/HealthCheck"
AIService_CreateSession_FullMethodName = "/ai.AIService/CreateSession"
AIService_AskInSession_FullMethodName = "/ai.AIService/AskInSession"
@ -33,6 +34,8 @@ const (
type AIServiceClient interface {
// GenerateAnswer генерирует ответ на запрос
GenerateAnswer(ctx context.Context, in *AIRequest, opts ...grpc.CallOption) (*AIResponse, error)
// GenerateStateless генерирует ответ из массива messages (system+history+user)
GenerateStateless(ctx context.Context, in *StatelessRequest, opts ...grpc.CallOption) (*AIResponse, error)
// HealthCheck проверяет здоровье сервиса
HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error)
// CreateSession созда новую AI сессию
@ -59,6 +62,16 @@ func (c *aIServiceClient) GenerateAnswer(ctx context.Context, in *AIRequest, opt
return out, nil
}
func (c *aIServiceClient) GenerateStateless(ctx context.Context, in *StatelessRequest, opts ...grpc.CallOption) (*AIResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AIResponse)
err := c.cc.Invoke(ctx, AIService_GenerateStateless_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *aIServiceClient) HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(HealthCheckResponse)
@ -97,6 +110,8 @@ func (c *aIServiceClient) AskInSession(ctx context.Context, in *AskInSessionRequ
type AIServiceServer interface {
// GenerateAnswer генерирует ответ на запрос
GenerateAnswer(context.Context, *AIRequest) (*AIResponse, error)
// GenerateStateless генерирует ответ из массива messages (system+history+user)
GenerateStateless(context.Context, *StatelessRequest) (*AIResponse, error)
// HealthCheck проверяет здоровье сервиса
HealthCheck(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error)
// CreateSession созда новую AI сессию
@ -116,6 +131,9 @@ type UnimplementedAIServiceServer struct{}
func (UnimplementedAIServiceServer) GenerateAnswer(context.Context, *AIRequest) (*AIResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GenerateAnswer not implemented")
}
func (UnimplementedAIServiceServer) GenerateStateless(context.Context, *StatelessRequest) (*AIResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GenerateStateless not implemented")
}
func (UnimplementedAIServiceServer) HealthCheck(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) {
return nil, status.Error(codes.Unimplemented, "method HealthCheck not implemented")
}
@ -164,6 +182,24 @@ func _AIService_GenerateAnswer_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _AIService_GenerateStateless_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StatelessRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AIServiceServer).GenerateStateless(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AIService_GenerateStateless_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AIServiceServer).GenerateStateless(ctx, req.(*StatelessRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AIService_HealthCheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(HealthCheckRequest)
if err := dec(in); err != nil {
@ -229,6 +265,10 @@ var AIService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GenerateAnswer",
Handler: _AIService_GenerateAnswer_Handler,
},
{
MethodName: "GenerateStateless",
Handler: _AIService_GenerateStateless_Handler,
},
{
MethodName: "HealthCheck",
Handler: _AIService_HealthCheck_Handler,