Compare commits
2 Commits
77c0396623
...
46a4374e69
| Author | SHA1 | Date |
|---|---|---|
|
|
46a4374e69 | |
|
|
2bd7333233 |
|
|
@ -32,6 +32,9 @@ func (m *mockLLM) DisambiguateBestMatch(ctx context.Context, msg string, candida
|
||||||
func (m *mockLLM) GetEmbeddings(ctx context.Context, input string) ([]float64, error) {
|
func (m *mockLLM) GetEmbeddings(ctx context.Context, input string) ([]float64, error) {
|
||||||
return m.embeddings, m.embeddingErr
|
return m.embeddings, m.embeddingErr
|
||||||
}
|
}
|
||||||
|
func (m *mockLLM) TranslateToEnglish(ctx context.Context, msg string) (string, error) {
|
||||||
|
return msg, nil
|
||||||
|
}
|
||||||
|
|
||||||
// --- Test VisitDB ---
|
// --- Test VisitDB ---
|
||||||
type testVisitDB struct {
|
type testVisitDB struct {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ type Config struct {
|
||||||
LLM struct {
|
LLM struct {
|
||||||
ExtractKeywordsPrompt string `yaml:"extract_keywords_prompt"`
|
ExtractKeywordsPrompt string `yaml:"extract_keywords_prompt"`
|
||||||
DisambiguatePrompt string `yaml:"disambiguate_prompt"`
|
DisambiguatePrompt string `yaml:"disambiguate_prompt"`
|
||||||
|
TranslatePrompt string `yaml:"translate_prompt"`
|
||||||
} `yaml:"llm"`
|
} `yaml:"llm"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
llm:
|
llm:
|
||||||
extract_keywords_prompt: "You will extract structured data from the user input. Input text: {{.Message}}. Return ONLY valid minified JSON object with keys: translate (English translation of input), keyword (array of 3-5 concise English veterinary-related keywords derived strictly from the input), animal (animal mentioned or 'unknown'). Example: {\"translate\":\"dog has diarrhea\",\"keyword\":[\"diarrhea\",\"digestive\"],\"animal\":\"dog\"}. Do not add extra text, markdown, or quotes outside JSON."
|
extract_keywords_prompt: "You will extract structured data from the user input. Input text: {{.Message}}. Return ONLY valid minified JSON object with keys: translate (English translation of input), keyword (array of 3-5 concise English veterinary-related keywords derived strictly from the input), animal (animal mentioned or 'unknown'). Example: {\"translate\":\"dog has diarrhea\",\"keyword\":[\"diarrhea\",\"digestive\"],\"animal\":\"dog\"}. Do not add extra text, markdown, or quotes outside JSON."
|
||||||
disambiguate_prompt: "Given candidate visit entries (JSON array): {{.Entries}} and user message: {{.Message}} choose the best matching visit's ID. Return ONLY JSON: {\"visitReason\":\"<one of the candidate IDs or empty string if none>\"}. No other text."
|
disambiguate_prompt: "Given candidate visit entries (JSON array): {{.Entries}} and user message: {{.Message}} choose the best matching visit's ID. Return ONLY JSON: {\"visitReason\":\"<one of the candidate IDs or empty string if none>\"}. No other text."
|
||||||
|
translate_prompt: "Translate the following veterinary-related sentence to English. Input: '{{.Message}}'. Return ONLY the English translation, no extra text, no markdown, no quotes. If already English, return as is."
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,9 @@ func (m *mockHandleChatLLM) DisambiguateBestMatch(ctx context.Context, msg strin
|
||||||
func (m *mockHandleChatLLM) GetEmbeddings(ctx context.Context, input string) ([]float64, error) {
|
func (m *mockHandleChatLLM) GetEmbeddings(ctx context.Context, input string) ([]float64, error) {
|
||||||
return m.embeddings, m.embeddingErr
|
return m.embeddings, m.embeddingErr
|
||||||
}
|
}
|
||||||
|
func (m *mockHandleChatLLM) TranslateToEnglish(ctx context.Context, msg string) (string, error) {
|
||||||
|
return msg, nil
|
||||||
|
}
|
||||||
|
|
||||||
// mapChatRepo is an in-memory implementation of ChatRepositoryAPI for tests.
|
// mapChatRepo is an in-memory implementation of ChatRepositoryAPI for tests.
|
||||||
type mapChatRepo struct {
|
type mapChatRepo struct {
|
||||||
|
|
|
||||||
1
llm.go
1
llm.go
|
|
@ -15,6 +15,7 @@ type LLMClientAPI interface {
|
||||||
ExtractKeywords(ctx context.Context, message string) (map[string]interface{}, error)
|
ExtractKeywords(ctx context.Context, message string) (map[string]interface{}, error)
|
||||||
DisambiguateBestMatch(ctx context.Context, message string, candidates []Visit) (string, error)
|
DisambiguateBestMatch(ctx context.Context, message string, candidates []Visit) (string, error)
|
||||||
GetEmbeddings(ctx context.Context, input string) ([]float64, error)
|
GetEmbeddings(ctx context.Context, input string) ([]float64, error)
|
||||||
|
TranslateToEnglish(ctx context.Context, message string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Format Utilities ---
|
// --- Format Utilities ---
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,10 @@ func (m *MockLLMClient) GetEmbeddings(ctx context.Context, input string) ([]floa
|
||||||
return []float64{0.1, 0.2, 0.3}, nil
|
return []float64{0.1, 0.2, 0.3}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MockLLMClient) TranslateToEnglish(ctx context.Context, message string) (string, error) {
|
||||||
|
return message, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewLLMClientFromEnv(t *testing.T) {
|
func TestNewLLMClientFromEnv(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
-- +goose Up
|
||||||
|
CREATE EXTENSION IF NOT EXISTS vector;
|
||||||
|
|
||||||
|
CREATE TABLE sentence_embeddings (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
visit_id INTEGER NOT NULL,
|
||||||
|
sentence TEXT NOT NULL,
|
||||||
|
translated TEXT,
|
||||||
|
embeddings VECTOR(1536) NOT NULL,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
DROP TABLE IF EXISTS sentence_embeddings;
|
||||||
|
DROP EXTENSION IF EXISTS vector;
|
||||||
|
|
||||||
|
|
@ -166,3 +166,19 @@ func (llm *OllamaClient) GetEmbeddings(ctx context.Context, input string) ([]flo
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("unrecognized embedding response: %.200s", string(raw))
|
return nil, fmt.Errorf("unrecognized embedding response: %.200s", string(raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (llm *OllamaClient) TranslateToEnglish(ctx context.Context, message string) (string, error) {
|
||||||
|
prompt, err := renderPrompt(appConfig.LLM.TranslatePrompt, map[string]string{"Message": message})
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Error("[CONFIG] Failed to render Translate prompt")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
logrus.WithField("prompt", prompt).Info("[LLM] TranslateToEnglish prompt")
|
||||||
|
|
||||||
|
resp, err := llm.ollamaCompletion(ctx, prompt, nil)
|
||||||
|
logrus.WithFields(logrus.Fields{"response": resp, "err": err}).Info("[LLM] TranslateToEnglish response")
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(resp), nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -198,3 +198,19 @@ func (llm *OpenAIClient) GetEmbeddings(ctx context.Context, input string) ([]flo
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("unrecognized embedding response: %.200s", string(raw))
|
return nil, fmt.Errorf("unrecognized embedding response: %.200s", string(raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (llm *OpenAIClient) TranslateToEnglish(ctx context.Context, message string) (string, error) {
|
||||||
|
prompt, err := renderPrompt(appConfig.LLM.TranslatePrompt, map[string]string{"Message": message})
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Error("[CONFIG] Failed to render Translate prompt")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
logrus.WithField("prompt", prompt).Info("[LLM] TranslateToEnglish prompt")
|
||||||
|
|
||||||
|
resp, err := llm.openAICompletion(ctx, prompt, nil)
|
||||||
|
logrus.WithFields(logrus.Fields{"response": resp, "err": err}).Info("[LLM] TranslateToEnglish response")
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(resp), nil
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue