Enha: add openrouter parser
This commit is contained in:
		| @@ -27,61 +27,6 @@ var ( | |||||||
| 	GuesserSimplePrompt = `we are playing game of alias;\n you were given a clue: \"%s\";\nplease return your guess and words that could be meant by the clue, but you do not wish to open yet, in json like:\n{\n\"guess\": \"most_relevant_word_to_the_clue\",\n\"could_be\": [\"this\", \"that\", ...]\n}\nhere is the words that left:\n%s` | 	GuesserSimplePrompt = `we are playing game of alias;\n you were given a clue: \"%s\";\nplease return your guess and words that could be meant by the clue, but you do not wish to open yet, in json like:\n{\n\"guess\": \"most_relevant_word_to_the_clue\",\n\"could_be\": [\"this\", \"that\", ...]\n}\nhere is the words that left:\n%s` | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type DSResp struct { |  | ||||||
| 	ID      string `json:"id"` |  | ||||||
| 	Choices []struct { |  | ||||||
| 		Text         string `json:"text"` |  | ||||||
| 		Index        int    `json:"index"` |  | ||||||
| 		FinishReason string `json:"finish_reason"` |  | ||||||
| 	} `json:"choices"` |  | ||||||
| 	Created           int    `json:"created"` |  | ||||||
| 	Model             string `json:"model"` |  | ||||||
| 	SystemFingerprint string `json:"system_fingerprint"` |  | ||||||
| 	Object            string `json:"object"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type LLMResp struct { |  | ||||||
| 	Index           int    `json:"index"` |  | ||||||
| 	Content         string `json:"content"` |  | ||||||
| 	Tokens          []any  `json:"tokens"` |  | ||||||
| 	IDSlot          int    `json:"id_slot"` |  | ||||||
| 	Stop            bool   `json:"stop"` |  | ||||||
| 	Model           string `json:"model"` |  | ||||||
| 	TokensPredicted int    `json:"tokens_predicted"` |  | ||||||
| 	TokensEvaluated int    `json:"tokens_evaluated"` |  | ||||||
| 	Prompt          string `json:"prompt"` |  | ||||||
| 	HasNewLine      bool   `json:"has_new_line"` |  | ||||||
| 	Truncated       bool   `json:"truncated"` |  | ||||||
| 	StopType        string `json:"stop_type"` |  | ||||||
| 	StoppingWord    string `json:"stopping_word"` |  | ||||||
| 	TokensCached    int    `json:"tokens_cached"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type MimeResp struct { |  | ||||||
| 	Clue   string   `json:"clue"` |  | ||||||
| 	Number string   `json:"number"` |  | ||||||
| 	Answer []string `json:"words_I_mean_my_team_to_open"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type GusserResp struct { |  | ||||||
| 	Guesses []string `json:"guesses"` |  | ||||||
| 	CouldBe []string `json:"could_be"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type Bot struct { |  | ||||||
| 	Role      string         `json:"role"` |  | ||||||
| 	Team      string         `json:"team"` |  | ||||||
| 	cfg       *config.Config `json:"-"` |  | ||||||
| 	RoomID    string         `json:"room_id"` // can we get a room from here? |  | ||||||
| 	BotName   string         `json:"bot_name"` |  | ||||||
| 	log       *slog.Logger   `json:"-"` |  | ||||||
| 	LLMParser RespParser     `json:"-"` |  | ||||||
| 	// channels for communicaton |  | ||||||
| 	// channels are not serializable |  | ||||||
| 	// SignalsCh chan bool |  | ||||||
| 	// DoneCh    chan bool |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func convertToSliceOfStrings(value any) ([]string, error) { | func convertToSliceOfStrings(value any) ([]string, error) { | ||||||
| 	switch v := value.(type) { | 	switch v := value.(type) { | ||||||
| 	case []string: | 	case []string: | ||||||
| @@ -299,6 +244,8 @@ func NewBot(role, team, name, roomID string, cfg *config.Config, recovery bool) | |||||||
| 	bot.LLMParser = NewLCPRespParser(bot.log) | 	bot.LLMParser = NewLCPRespParser(bot.log) | ||||||
| 	if strings.Contains(cfg.LLMConfig.URL, "api.deepseek.com") { | 	if strings.Contains(cfg.LLMConfig.URL, "api.deepseek.com") { | ||||||
| 		bot.LLMParser = NewDeepSeekParser(bot.log) | 		bot.LLMParser = NewDeepSeekParser(bot.log) | ||||||
|  | 	} else if strings.Contains(cfg.LLMConfig.URL, "openrouter.ai") { | ||||||
|  | 		bot.LLMParser = NewOpenRouterParser(bot.log) | ||||||
| 	} | 	} | ||||||
| 	// add to room | 	// add to room | ||||||
| 	room, err := getRoomByID(bot.RoomID) | 	room, err := getRoomByID(bot.RoomID) | ||||||
|   | |||||||
							
								
								
									
										86
									
								
								llmapi/models.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								llmapi/models.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | |||||||
|  | package llmapi | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"gralias/config" | ||||||
|  | 	"log/slog" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type OpenRouterResp struct { | ||||||
|  | 	ID       string `json:"id"` | ||||||
|  | 	Provider string `json:"provider"` | ||||||
|  | 	Model    string `json:"model"` | ||||||
|  | 	Object   string `json:"object"` | ||||||
|  | 	Created  int    `json:"created"` | ||||||
|  | 	Choices  []struct { | ||||||
|  | 		Logprobs           any    `json:"logprobs"` | ||||||
|  | 		FinishReason       string `json:"finish_reason"` | ||||||
|  | 		NativeFinishReason string `json:"native_finish_reason"` | ||||||
|  | 		Index              int    `json:"index"` | ||||||
|  | 		Message            struct { | ||||||
|  | 			Role      string `json:"role"` | ||||||
|  | 			Content   string `json:"content"` | ||||||
|  | 			Refusal   any    `json:"refusal"` | ||||||
|  | 			Reasoning any    `json:"reasoning"` | ||||||
|  | 		} `json:"message"` | ||||||
|  | 	} `json:"choices"` | ||||||
|  | 	Usage struct { | ||||||
|  | 		PromptTokens     int `json:"prompt_tokens"` | ||||||
|  | 		CompletionTokens int `json:"completion_tokens"` | ||||||
|  | 		TotalTokens      int `json:"total_tokens"` | ||||||
|  | 	} `json:"usage"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type DSResp struct { | ||||||
|  | 	ID      string `json:"id"` | ||||||
|  | 	Choices []struct { | ||||||
|  | 		Text         string `json:"text"` | ||||||
|  | 		Index        int    `json:"index"` | ||||||
|  | 		FinishReason string `json:"finish_reason"` | ||||||
|  | 	} `json:"choices"` | ||||||
|  | 	Created           int    `json:"created"` | ||||||
|  | 	Model             string `json:"model"` | ||||||
|  | 	SystemFingerprint string `json:"system_fingerprint"` | ||||||
|  | 	Object            string `json:"object"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type LLMResp struct { | ||||||
|  | 	Index           int    `json:"index"` | ||||||
|  | 	Content         string `json:"content"` | ||||||
|  | 	Tokens          []any  `json:"tokens"` | ||||||
|  | 	IDSlot          int    `json:"id_slot"` | ||||||
|  | 	Stop            bool   `json:"stop"` | ||||||
|  | 	Model           string `json:"model"` | ||||||
|  | 	TokensPredicted int    `json:"tokens_predicted"` | ||||||
|  | 	TokensEvaluated int    `json:"tokens_evaluated"` | ||||||
|  | 	Prompt          string `json:"prompt"` | ||||||
|  | 	HasNewLine      bool   `json:"has_new_line"` | ||||||
|  | 	Truncated       bool   `json:"truncated"` | ||||||
|  | 	StopType        string `json:"stop_type"` | ||||||
|  | 	StoppingWord    string `json:"stopping_word"` | ||||||
|  | 	TokensCached    int    `json:"tokens_cached"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type MimeResp struct { | ||||||
|  | 	Clue   string   `json:"clue"` | ||||||
|  | 	Number string   `json:"number"` | ||||||
|  | 	Answer []string `json:"words_I_mean_my_team_to_open"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type GusserResp struct { | ||||||
|  | 	Guesses []string `json:"guesses"` | ||||||
|  | 	CouldBe []string `json:"could_be"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Bot struct { | ||||||
|  | 	Role      string         `json:"role"` | ||||||
|  | 	Team      string         `json:"team"` | ||||||
|  | 	cfg       *config.Config `json:"-"` | ||||||
|  | 	RoomID    string         `json:"room_id"` // can we get a room from here? | ||||||
|  | 	BotName   string         `json:"bot_name"` | ||||||
|  | 	log       *slog.Logger   `json:"-"` | ||||||
|  | 	LLMParser RespParser     `json:"-"` | ||||||
|  | 	// channels for communicaton | ||||||
|  | 	// channels are not serializable | ||||||
|  | 	// SignalsCh chan bool | ||||||
|  | 	// DoneCh    chan bool | ||||||
|  | } | ||||||
| @@ -88,3 +88,40 @@ func (p *lcpRespParser) ParseBytes(body []byte) (map[string]any, error) { | |||||||
| 	} | 	} | ||||||
| 	return respMap, nil | 	return respMap, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type openRouterParser struct { | ||||||
|  | 	log *slog.Logger | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewOpenRouterParser(log *slog.Logger) *openRouterParser { | ||||||
|  | 	return &openRouterParser{log: log} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *openRouterParser) ParseBytes(body []byte) (map[string]any, error) { | ||||||
|  | 	// parsing logic here | ||||||
|  | 	resp := OpenRouterResp{} | ||||||
|  | 	if err := json.Unmarshal(body, &resp); err != nil { | ||||||
|  | 		p.log.Error("failed to unmarshal", "error", err) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if len(resp.Choices) == 0 { | ||||||
|  | 		p.log.Error("empty choices", "resp", resp) | ||||||
|  | 		err := errors.New("empty choices in resp") | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	text := resp.Choices[0].Message.Content | ||||||
|  | 	li := strings.Index(text, "{") | ||||||
|  | 	ri := strings.LastIndex(text, "}") | ||||||
|  | 	if li < 0 || ri < 1 { | ||||||
|  | 		p.log.Error("not a json", "msg", text) | ||||||
|  | 		err := fmt.Errorf("fn: ParseBytes, not a json; data: %s", text) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	sj := text[li : ri+1] | ||||||
|  | 	respMap := make(map[string]any) | ||||||
|  | 	if err := json.Unmarshal([]byte(sj), &respMap); err != nil { | ||||||
|  | 		p.log.Error("failed to unmarshal response", "error", err, "string-json", sj) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return respMap, nil | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder