mirror of
https://github.com/vxcontrol/langchaingo.git
synced 2026-07-20 14:13:36 -04:00
c544fb77bd
* all: add broad httprr coverage, update dependencies, organize go.mod file, bump to 1.23 update go version to 1.23 add lots of test coverage via httprr recordings update dependencies and organize go.mod add testutil/testctr which helps work around a testcontainers-go+colima bug expand the huggingface implementation and tests expand capabilities of the ollama package
192 lines
5.5 KiB
Go
192 lines
5.5 KiB
Go
package memory
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/tmc/langchaingo/llms"
|
|
)
|
|
|
|
func TestWindowBufferMemory(t *testing.T) {
|
|
ctx := context.Background()
|
|
t.Parallel()
|
|
|
|
m := NewConversationWindowBuffer(2)
|
|
|
|
result1, err := m.LoadMemoryVariables(ctx, map[string]any{})
|
|
require.NoError(t, err)
|
|
expected1 := map[string]any{"history": ""}
|
|
assert.Equal(t, expected1, result1)
|
|
|
|
err = m.SaveContext(ctx, map[string]any{"foo": "bar1"}, map[string]any{"bar": "foo1"})
|
|
require.NoError(t, err)
|
|
|
|
result2, err := m.LoadMemoryVariables(ctx, map[string]any{})
|
|
require.NoError(t, err)
|
|
|
|
expected2 := map[string]any{"history": "Human: bar1\nAI: foo1"}
|
|
assert.Equal(t, expected2, result2)
|
|
|
|
err = m.SaveContext(ctx, map[string]any{"foo": "bar2"}, map[string]any{"bar": "foo2"})
|
|
require.NoError(t, err)
|
|
|
|
result3, err := m.LoadMemoryVariables(ctx, map[string]any{})
|
|
require.NoError(t, err)
|
|
|
|
expected3 := map[string]any{"history": "Human: bar1\nAI: foo1\nHuman: bar2\nAI: foo2"}
|
|
assert.Equal(t, expected3, result3)
|
|
|
|
err = m.SaveContext(ctx, map[string]any{"foo": "bar3"}, map[string]any{"bar": "foo3"})
|
|
require.NoError(t, err)
|
|
|
|
result4, err := m.LoadMemoryVariables(ctx, map[string]any{})
|
|
require.NoError(t, err)
|
|
|
|
expected4 := map[string]any{"history": "Human: bar2\nAI: foo2\nHuman: bar3\nAI: foo3"}
|
|
assert.Equal(t, expected4, result4)
|
|
}
|
|
|
|
func TestWindowBufferMemoryReturnMessage(t *testing.T) {
|
|
ctx := context.Background()
|
|
t.Parallel()
|
|
m := NewConversationWindowBuffer(2, WithReturnMessages(true))
|
|
|
|
err := m.SaveContext(ctx, map[string]any{"foo": "bar1"}, map[string]any{"bar": "foo1"})
|
|
require.NoError(t, err)
|
|
|
|
err = m.SaveContext(ctx, map[string]any{"foo": "bar2"}, map[string]any{"bar": "foo2"})
|
|
require.NoError(t, err)
|
|
|
|
err = m.SaveContext(ctx, map[string]any{"foo": "bar3"}, map[string]any{"bar": "foo3"})
|
|
require.NoError(t, err)
|
|
|
|
result, err := m.LoadMemoryVariables(ctx, map[string]any{})
|
|
require.NoError(t, err)
|
|
|
|
expectedChatHistory := NewChatMessageHistory(
|
|
WithPreviousMessages([]llms.ChatMessage{
|
|
llms.HumanChatMessage{Content: "bar2"},
|
|
llms.AIChatMessage{Content: "foo2"},
|
|
llms.HumanChatMessage{Content: "bar3"},
|
|
llms.AIChatMessage{Content: "foo3"},
|
|
}),
|
|
)
|
|
|
|
messages, err := expectedChatHistory.Messages(ctx)
|
|
require.NoError(t, err)
|
|
expected := map[string]any{"history": messages}
|
|
assert.Equal(t, expected, result)
|
|
}
|
|
|
|
func TestWindowBufferMemoryWithPreLoadedHistory(t *testing.T) {
|
|
ctx := context.Background()
|
|
t.Parallel()
|
|
|
|
m := NewConversationWindowBuffer(2, WithChatHistory(NewChatMessageHistory(
|
|
WithPreviousMessages([]llms.ChatMessage{
|
|
llms.HumanChatMessage{Content: "bar1"},
|
|
llms.AIChatMessage{Content: "foo1"},
|
|
llms.HumanChatMessage{Content: "bar2"},
|
|
llms.AIChatMessage{Content: "foo2"},
|
|
llms.HumanChatMessage{Content: "bar3"},
|
|
llms.AIChatMessage{Content: "foo3"},
|
|
}),
|
|
)))
|
|
|
|
result, err := m.LoadMemoryVariables(ctx, map[string]any{})
|
|
require.NoError(t, err)
|
|
expected := map[string]any{"history": "Human: bar2\nAI: foo2\nHuman: bar3\nAI: foo3"}
|
|
assert.Equal(t, expected, result)
|
|
}
|
|
|
|
func TestConversationWindowBuffer_cutMessages(t *testing.T) {
|
|
t.Parallel()
|
|
type fields struct {
|
|
ConversationBuffer ConversationBuffer
|
|
ConversationWindowSize int
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
messages []llms.ChatMessage
|
|
wantMessages []llms.ChatMessage
|
|
isCut bool
|
|
}{
|
|
{
|
|
name: "empty messages, do not need cut",
|
|
fields: fields{
|
|
ConversationBuffer: *NewConversationBuffer(),
|
|
ConversationWindowSize: 1,
|
|
},
|
|
messages: []llms.ChatMessage{},
|
|
wantMessages: []llms.ChatMessage{},
|
|
isCut: false,
|
|
},
|
|
{
|
|
name: "message less than buffer size, do not need cut",
|
|
fields: fields{
|
|
ConversationBuffer: *NewConversationBuffer(),
|
|
ConversationWindowSize: 1,
|
|
},
|
|
messages: []llms.ChatMessage{
|
|
llms.HumanChatMessage{Content: "foo"},
|
|
llms.AIChatMessage{Content: "bar"},
|
|
},
|
|
wantMessages: []llms.ChatMessage{
|
|
llms.HumanChatMessage{Content: "foo"},
|
|
llms.AIChatMessage{Content: "bar"},
|
|
},
|
|
isCut: false,
|
|
},
|
|
{
|
|
name: "add human message, will cut",
|
|
fields: fields{
|
|
ConversationBuffer: *NewConversationBuffer(),
|
|
ConversationWindowSize: 1,
|
|
},
|
|
messages: []llms.ChatMessage{
|
|
llms.HumanChatMessage{Content: "foo"},
|
|
llms.AIChatMessage{Content: "bar"},
|
|
llms.HumanChatMessage{Content: "foo1"},
|
|
},
|
|
wantMessages: []llms.ChatMessage{
|
|
llms.AIChatMessage{Content: "bar"},
|
|
llms.HumanChatMessage{Content: "foo1"},
|
|
},
|
|
isCut: true,
|
|
},
|
|
{
|
|
name: "message more than buffer size, will cut",
|
|
fields: fields{
|
|
ConversationBuffer: *NewConversationBuffer(),
|
|
ConversationWindowSize: 1,
|
|
},
|
|
messages: []llms.ChatMessage{
|
|
llms.HumanChatMessage{Content: "foo"},
|
|
llms.AIChatMessage{Content: "bar"},
|
|
llms.HumanChatMessage{Content: "foo1"},
|
|
llms.AIChatMessage{Content: "bar1"},
|
|
},
|
|
wantMessages: []llms.ChatMessage{
|
|
llms.HumanChatMessage{Content: "foo1"},
|
|
llms.AIChatMessage{Content: "bar1"},
|
|
},
|
|
isCut: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
wb := &ConversationWindowBuffer{
|
|
ConversationBuffer: tt.fields.ConversationBuffer,
|
|
ConversationWindowSize: tt.fields.ConversationWindowSize,
|
|
}
|
|
cut, isCut := wb.cutMessages(tt.messages)
|
|
assert.Equalf(t, tt.wantMessages, cut, "cutMessages(%s), want:%v, get:%v", tt.name, tt.wantMessages, cut)
|
|
assert.Equalf(t, tt.isCut, isCut, "cutMessages(%s), want:%t, get:%t", tt.name, tt.isCut, isCut)
|
|
})
|
|
}
|
|
}
|