Commit 462d9f21 authored by Wade's avatar Wade

mv qa

parent b3490554
This diff is collapsed.
...@@ -5,15 +5,23 @@ go 1.24.1 ...@@ -5,15 +5,23 @@ go 1.24.1
require ( require (
github.com/cohesion-org/deepseek-go v1.3.1 github.com/cohesion-org/deepseek-go v1.3.1
github.com/firebase/genkit/go v0.5.4 github.com/firebase/genkit/go v0.5.4
github.com/lib/pq v1.10.9
github.com/milvus-io/milvus-sdk-go/v2 v2.4.2
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/rs/zerolog v1.34.0
github.com/stretchr/testify v1.10.0
github.com/swaggo/http-swagger v1.3.4
github.com/swaggo/swag v1.16.4
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1180
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/lkeap v1.0.1179
github.com/test-go/testify v1.1.4
golang.org/x/time v0.11.0
) )
require ( require (
cloud.google.com/go v0.118.0 // indirect cloud.google.com/go v0.118.0 // indirect
cloud.google.com/go/auth v0.16.1 // indirect cloud.google.com/go/auth v0.16.1 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.7.0 // indirect cloud.google.com/go/compute/metadata v0.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.0 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect github.com/KyleBanks/depth v1.2.1 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/blues/jsonata-go v1.5.4 // indirect github.com/blues/jsonata-go v1.5.4 // indirect
...@@ -46,37 +54,16 @@ require ( ...@@ -46,37 +54,16 @@ require (
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/mailru/easyjson v0.9.0 // indirect github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mbleigh/raymond v0.0.0-20250414171441-6b3a58ab9e0a // indirect github.com/mbleigh/raymond v0.0.0-20250414171441-6b3a58ab9e0a // indirect
github.com/microsoft/kiota-abstractions-go v1.9.2 // indirect
github.com/microsoft/kiota-authentication-azure-go v1.3.0 // indirect
github.com/microsoft/kiota-http-go v1.5.2 // indirect
github.com/microsoft/kiota-serialization-form-go v1.1.2 // indirect
github.com/microsoft/kiota-serialization-json-go v1.1.2 // indirect
github.com/microsoft/kiota-serialization-multipart-go v1.1.2 // indirect
github.com/microsoft/kiota-serialization-text-go v1.1.2 // indirect
github.com/microsoftgraph/msgraph-sdk-go v1.72.0 // indirect
github.com/microsoftgraph/msgraph-sdk-go-core v1.3.2 // indirect
github.com/milvus-io/milvus-proto/go-api/v2 v2.4.10-0.20240819025435-512e3b98866a // indirect github.com/milvus-io/milvus-proto/go-api/v2 v2.4.10-0.20240819025435-512e3b98866a // indirect
github.com/milvus-io/milvus-sdk-go/v2 v2.4.2 // indirect
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
github.com/ollama/ollama v0.6.5 // indirect github.com/ollama/ollama v0.6.5 // indirect
github.com/pgvector/pgvector-go v0.3.0 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/rs/zerolog v1.34.0 // indirect
github.com/std-uritemplate/std-uritemplate/go/v2 v2.0.3 // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/swaggo/files v1.0.1 // indirect github.com/swaggo/files v1.0.1 // indirect
github.com/swaggo/http-swagger v1.3.4 // indirect
github.com/swaggo/swag v1.16.4 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1180 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/lkeap v1.0.1179 // indirect
github.com/test-go/testify v1.1.4 // indirect
github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect
...@@ -93,18 +80,16 @@ require ( ...@@ -93,18 +80,16 @@ require (
golang.org/x/crypto v0.38.0 // indirect golang.org/x/crypto v0.38.0 // indirect
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
golang.org/x/net v0.40.0 // indirect golang.org/x/net v0.40.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.14.0 // indirect golang.org/x/sync v0.14.0 // indirect
golang.org/x/sys v0.33.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect golang.org/x/text v0.25.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.33.0 // indirect golang.org/x/tools v0.33.0 // indirect
google.golang.org/api v0.235.0 // indirect
google.golang.org/genai v1.5.0 // indirect google.golang.org/genai v1.5.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 // indirect
google.golang.org/grpc v1.72.1 // indirect google.golang.org/grpc v1.72.1 // indirect
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
replace github.com/firebase/genkit/go => github.com/wade-liwei/genkit-web/go v0.0.0-20250605093206-aab2d64e9700 replace github.com/firebase/genkit/go => github.com/wade-liwei/genkit-web/go v0.0.0-20250605093206-aab2d64e9700
\ No newline at end of file
This diff is collapsed.
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
"github.com/wade-liwei/agentchat/plugins/graphrag" "github.com/wade-liwei/agentchat/plugins/graphrag"
"github.com/wade-liwei/agentchat/plugins/knowledge" // Import knowledge package "github.com/wade-liwei/agentchat/plugins/knowledge" // Import knowledge package
"github.com/wade-liwei/agentchat/plugins/milvus" "github.com/wade-liwei/agentchat/plugins/milvus"
"github.com/wade-liwei/agentchat/plugins/question"
"github.com/firebase/genkit/go/plugins/evaluators" "github.com/firebase/genkit/go/plugins/evaluators"
"github.com/firebase/genkit/go/plugins/googlegenai" "github.com/firebase/genkit/go/plugins/googlegenai"
...@@ -247,7 +248,7 @@ func main() { ...@@ -247,7 +248,7 @@ func main() {
log.Fatal().Msg(err.Error()) log.Fatal().Msg(err.Error())
} }
qa, err := InitQAStore(*pgConnString) qa, err := question.InitQAStore(*pgConnString)
if err != nil { if err != nil {
log.Fatal().Msgf("InitQAStore failed: %v", err) log.Fatal().Msgf("InitQAStore failed: %v", err)
} }
...@@ -276,7 +277,7 @@ func main() { ...@@ -276,7 +277,7 @@ func main() {
log.Info().Msgf("input--------%s", string(inputAsJson)) log.Info().Msgf("input--------%s", string(inputAsJson))
idx, lastQa, lastok, err := qa.WriteAndGetLatestQA(context.Background(), QA{ idx, lastQa, lastok, err := qa.WriteAndGetLatestQA(context.Background(), question.QA{
FromID: &input.FromID, FromID: &input.FromID,
From: &input.From, From: &input.From,
Question: &input.Content, Question: &input.Content,
......
package main package question
import ( import (
"context" "context"
......
package qa
// import (
// "context"
// "database/sql"
// "testing"
// "time"
// _ "github.com/lib/pq"
// "github.com/stretchr/testify/assert"
// "github.com/stretchr/testify/require"
// "github.com/wade-liwei/agentchat/plugins/qa"
// )
// // TestQAStore 测试 QAStore 的读写功能
// func TestQAStore(t *testing.T) {
// // 初始化测试数据库连接
// store, err := qa.InitQAStore()
// require.NoError(t, err, "failed to initialize QAStore")
// defer store.(*qaStore).db.Close()
// ctx := context.Background()
// // 清理测试数据(可选,确保测试环境干净)
// // cleanup := func() {
// // _, err := store.(*qaStore).db.ExecContext(ctx, "TRUNCATE TABLE qa RESTART IDENTITY")
// // require.NoError(t, err, "failed to truncate qa table")
// // }
// // cleanup()
// t.Run("WriteQA_Insert", func(t *testing.T) {
// // 测试插入新记录
// qa := QA{
// Question: stringPtr("What is Go?"),
// Answer: stringPtr("A programming language"),
// Summary: stringPtr("Go introduction"),
// From: stringPtr("Alice"),
// FromID: stringPtr("user123"),
// To: stringPtr("Bob"),
// ToID: stringPtr("user456"),
// }
// id, err := store.WriteQA(ctx, qa)
// require.NoError(t, err, "failed to insert QA")
// assert.NotZero(t, id, "inserted ID should not be zero")
// // 验证数据库中的记录
// var stored QA
// row := store.(*qaStore).db.QueryRowContext(ctx, `
// SELECT id, created_at, question, answer, summary, "from", "to", from_id, to_id
// FROM qa
// WHERE id = $1`, id)
// var question, answer, summary, from, to, fromID, toID sql.NullString
// err = row.Scan(&stored.ID, &stored.CreatedAt, &question, &answer, &summary, &from, &to, &fromID, &toID)
// require.NoError(t, err, "failed to query inserted QA")
// // 设置结构体字段
// if question.Valid {
// stored.Question = &question.String
// }
// if answer.Valid {
// stored.Answer = &answer.String
// }
// if summary.Valid {
// stored.Summary = &summary.String
// }
// if from.Valid {
// stored.From = &from.String
// }
// if to.Valid {
// stored.To = &to.String
// }
// if fromID.Valid {
// stored.FromID = &fromID.String
// }
// if toID.Valid {
// stored.ToID = &toID.String
// }
// // 验证插入的数据
// assert.Equal(t, qa.Question, stored.Question)
// assert.Equal(t, qa.Answer, stored.Answer)
// assert.Equal(t, qa.Summary, stored.Summary)
// assert.Equal(t, qa.From, stored.From)
// assert.Equal(t, qa.To, stored.To)
// assert.Equal(t, qa.FromID, stored.FromID)
// assert.Equal(t, qa.ToID, stored.ToID)
// })
// t.Run("WriteQA_Update", func(t *testing.T) {
// // 先插入一条记录
// qa := QA{
// Question: stringPtr("What is Python?"),
// Answer: stringPtr("Another language"),
// FromID: stringPtr("user789"),
// }
// id, err := store.WriteQA(ctx, qa)
// require.NoError(t, err, "failed to insert QA for update test")
// // 更新记录
// updatedQA := QA{
// ID: id,
// Question: stringPtr("Updated: What is Python?"),
// Answer: stringPtr("A versatile language"),
// Summary: stringPtr("Python summary"),
// FromID: stringPtr("user789"),
// }
// updatedID, err := store.WriteQA(ctx, updatedQA)
// require.NoError(t, err, "failed to update QA")
// assert.Equal(t, id, updatedID, "updated ID should match inserted ID")
// // 验证更新后的记录
// var stored QA
// row := store.(*qaStore).db.QueryRowContext(ctx, `
// SELECT id, created_at, question, answer, summary, "from", "to", from_id, to_id
// FROM qa
// WHERE id = $1`, id)
// var question, answer, summary, from, to, fromID, toID sql.NullString
// err = row.Scan(&stored.ID, &stored.CreatedAt, &question, &answer, &summary, &from, &to, &fromID, &toID)
// require.NoError(t, err, "failed to query updated QA")
// if question.Valid {
// stored.Question = &question.String
// }
// if answer.Valid {
// stored.Answer = &answer.String
// }
// if summary.Valid {
// stored.Summary = &summary.String
// }
// if fromID.Valid {
// stored.FromID = &fromID.String
// }
// assert.Equal(t, updatedQA.Question, stored.Question)
// assert.Equal(t, updatedQA.Answer, stored.Answer)
// assert.Equal(t, updatedQA.Summary, stored.Summary)
// assert.Equal(t, updatedQA.FromID, stored.FromID)
// })
// t.Run("GetLatestQA", func(t *testing.T) {
// // 插入多条记录以测试视图
// qa1 := QA{
// Question: stringPtr("First question"),
// Answer: stringPtr("First answer"),
// FromID: stringPtr("user123"),
// CreatedAt: time.Now().Add(-2 * time.Hour),
// }
// _, err := store.WriteQA(ctx, qa1)
// require.NoError(t, err, "failed to insert first QA")
// qa2 := QA{
// Question: stringPtr("Second question"),
// Answer: stringPtr("Second answer"),
// FromID: stringPtr("user123"),
// CreatedAt: time.Now(),
// }
// _, err = store.WriteQA(ctx, qa2)
// require.NoError(t, err, "failed to insert second QA")
// // 查询最新记录
// fromID := stringPtr("user123")
// results, err := store.GetLatestQA(ctx, fromID)
// require.NoError(t, err, "failed to get latest QA")
// require.Len(t, results, 1, "should return exactly one record for from_id")
// // 验证返回的记录是最新的一条
// assert.Equal(t, qa2.Question, results[0].Question)
// assert.Equal(t, qa2.Answer, results[0].Answer)
// assert.Equal(t, qa2.FromID, results[0].FromID)
// })
// t.Run("GetLatestQA_NullFromID", func(t *testing.T) {
// // 插入一条 from_id NULL 的记录
// qa := QA{
// Question: stringPtr("Null from_id question"),
// Answer: stringPtr("Null from_id answer"),
// FromID: nil,
// }
// _, err := store.WriteQA(ctx, qa)
// require.NoError(t, err, "failed to insert QA with null from_id")
// // 查询 from_id NULL 的记录
// results, err := store.GetLatestQA(ctx, nil)
// require.NoError(t, err, "failed to get latest QA for null from_id")
// assert.NotEmpty(t, results, "should return records for null from_id")
// assert.Nil(t, results[0].FromID, "from_id should be nil")
// assert.Equal(t, qa.Question, results[0].Question)
// })
// // 清理测试数据
// // cleanup()
// }
package main
import (
"context"
"database/sql"
"testing"
"time"
_ "github.com/lib/pq"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestQAStore 测试 QAStore 的读写功能
func TestQAStore(t *testing.T) {
// 初始化测试数据库连接
store, err := InitQAStore()
require.NoError(t, err, "failed to initialize QAStore")
defer store.(*qaStore).db.Close()
ctx := context.Background()
// 清理测试数据(可选,确保测试环境干净)
// cleanup := func() {
// _, err := store.(*qaStore).db.ExecContext(ctx, "TRUNCATE TABLE qa RESTART IDENTITY")
// require.NoError(t, err, "failed to truncate qa table")
// }
// cleanup()
t.Run("WriteQA_Insert", func(t *testing.T) {
// 测试插入新记录
qa := QA{
Question: stringPtr("What is Go?"),
Answer: stringPtr("A programming language"),
Summary: stringPtr("Go introduction"),
From: stringPtr("Alice"),
FromID: stringPtr("user123"),
To: stringPtr("Bob"),
ToID: stringPtr("user456"),
}
id, err := store.WriteQA(ctx, qa)
require.NoError(t, err, "failed to insert QA")
assert.NotZero(t, id, "inserted ID should not be zero")
// 验证数据库中的记录
var stored QA
row := store.(*qaStore).db.QueryRowContext(ctx, `
SELECT id, created_at, question, answer, summary, "from", "to", from_id, to_id
FROM qa
WHERE id = $1`, id)
var question, answer, summary, from, to, fromID, toID sql.NullString
err = row.Scan(&stored.ID, &stored.CreatedAt, &question, &answer, &summary, &from, &to, &fromID, &toID)
require.NoError(t, err, "failed to query inserted QA")
// 设置结构体字段
if question.Valid {
stored.Question = &question.String
}
if answer.Valid {
stored.Answer = &answer.String
}
if summary.Valid {
stored.Summary = &summary.String
}
if from.Valid {
stored.From = &from.String
}
if to.Valid {
stored.To = &to.String
}
if fromID.Valid {
stored.FromID = &fromID.String
}
if toID.Valid {
stored.ToID = &toID.String
}
// 验证插入的数据
assert.Equal(t, qa.Question, stored.Question)
assert.Equal(t, qa.Answer, stored.Answer)
assert.Equal(t, qa.Summary, stored.Summary)
assert.Equal(t, qa.From, stored.From)
assert.Equal(t, qa.To, stored.To)
assert.Equal(t, qa.FromID, stored.FromID)
assert.Equal(t, qa.ToID, stored.ToID)
})
t.Run("WriteQA_Update", func(t *testing.T) {
// 先插入一条记录
qa := QA{
Question: stringPtr("What is Python?"),
Answer: stringPtr("Another language"),
FromID: stringPtr("user789"),
}
id, err := store.WriteQA(ctx, qa)
require.NoError(t, err, "failed to insert QA for update test")
// 更新记录
updatedQA := QA{
ID: id,
Question: stringPtr("Updated: What is Python?"),
Answer: stringPtr("A versatile language"),
Summary: stringPtr("Python summary"),
FromID: stringPtr("user789"),
}
updatedID, err := store.WriteQA(ctx, updatedQA)
require.NoError(t, err, "failed to update QA")
assert.Equal(t, id, updatedID, "updated ID should match inserted ID")
// 验证更新后的记录
var stored QA
row := store.(*qaStore).db.QueryRowContext(ctx, `
SELECT id, created_at, question, answer, summary, "from", "to", from_id, to_id
FROM qa
WHERE id = $1`, id)
var question, answer, summary, from, to, fromID, toID sql.NullString
err = row.Scan(&stored.ID, &stored.CreatedAt, &question, &answer, &summary, &from, &to, &fromID, &toID)
require.NoError(t, err, "failed to query updated QA")
if question.Valid {
stored.Question = &question.String
}
if answer.Valid {
stored.Answer = &answer.String
}
if summary.Valid {
stored.Summary = &summary.String
}
if fromID.Valid {
stored.FromID = &fromID.String
}
assert.Equal(t, updatedQA.Question, stored.Question)
assert.Equal(t, updatedQA.Answer, stored.Answer)
assert.Equal(t, updatedQA.Summary, stored.Summary)
assert.Equal(t, updatedQA.FromID, stored.FromID)
})
t.Run("GetLatestQA", func(t *testing.T) {
// 插入多条记录以测试视图
qa1 := QA{
Question: stringPtr("First question"),
Answer: stringPtr("First answer"),
FromID: stringPtr("user123"),
CreatedAt: time.Now().Add(-2 * time.Hour),
}
_, err := store.WriteQA(ctx, qa1)
require.NoError(t, err, "failed to insert first QA")
qa2 := QA{
Question: stringPtr("Second question"),
Answer: stringPtr("Second answer"),
FromID: stringPtr("user123"),
CreatedAt: time.Now(),
}
_, err = store.WriteQA(ctx, qa2)
require.NoError(t, err, "failed to insert second QA")
// 查询最新记录
fromID := stringPtr("user123")
results, err := store.GetLatestQA(ctx, fromID)
require.NoError(t, err, "failed to get latest QA")
require.Len(t, results, 1, "should return exactly one record for from_id")
// 验证返回的记录是最新的一条
assert.Equal(t, qa2.Question, results[0].Question)
assert.Equal(t, qa2.Answer, results[0].Answer)
assert.Equal(t, qa2.FromID, results[0].FromID)
})
t.Run("GetLatestQA_NullFromID", func(t *testing.T) {
// 插入一条 from_id 为 NULL 的记录
qa := QA{
Question: stringPtr("Null from_id question"),
Answer: stringPtr("Null from_id answer"),
FromID: nil,
}
_, err := store.WriteQA(ctx, qa)
require.NoError(t, err, "failed to insert QA with null from_id")
// 查询 from_id 为 NULL 的记录
results, err := store.GetLatestQA(ctx, nil)
require.NoError(t, err, "failed to get latest QA for null from_id")
assert.NotEmpty(t, results, "should return records for null from_id")
assert.Nil(t, results[0].FromID, "from_id should be nil")
assert.Equal(t, qa.Question, results[0].Question)
})
// 清理测试数据
// cleanup()
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment