Commit 89fcd46e authored by Wade's avatar Wade

update qa

parent 1e8a8704
{"level":"info","pid":13887,"time":1749196484,"caller":"/Users/wade/project/wuban/agentchat/log.go:68","message":"This message appears when log level set to Debug or Info"}
{"level":"info","pid":13887,"method":"DeepSeek.Init","time":1749196484,"caller":"/Users/wade/project/wuban/agentchat/plugins/deepseek/deepseek.go:91","message":"Initializing DeepSeek plugin"}
{"level":"info","pid":13887,"method":"DeepSeek.Init","time":1749196484,"caller":"/Users/wade/project/wuban/agentchat/plugins/deepseek/deepseek.go:104","message":"Initialization successful"}
{"level":"info","pid":13887,"method":"Milvus.Init","time":1749196484,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:75","message":"Initializing Milvus plugin"}
{"level":"info","pid":13887,"method":"Milvus.Init","time":1749196485,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:87","message":"Initialization successful"}
{"level":"info","pid":13887,"method":"GraphKnowledge.Init","time":1749196485,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:299","message":"Initializing GraphKnowledge plugin"}
{"level":"info","pid":13887,"method":"NewClient","ip":"54.92.111.204","port":5670,"time":1749196485,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:93","message":"Creating new GraphRAG client"}
{"level":"info","pid":13887,"method":"GraphKnowledge.Init","time":1749196485,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:311","message":"Initialization successful"}
{"level":"info","pid":13887,"method":"DefineIndexerAndRetriever","collection":"chatRag1","dimension":768,"time":1749196485,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:152","message":"Defining indexer and retriever"}
{"level":"info","pid":13887,"method":"Milvus.newDocStore","collection":"chatRag1","dimension":768,"time":1749196485,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:201","message":"Creating new doc store"}
{"level":"info","pid":13887,"method":"Milvus.newDocStore","collection":"chatRag1","time":1749196486,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:302","message":"Doc store created successfully"}
{"level":"info","pid":13887,"method":"DefineIndexerAndRetriever","collection":"chatRag1","time":1749196486,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:182","message":"Indexer and retriever defined successfully"}
{"level":"info","pid":13887,"method":"DefineIndexerAndRetriever","time":1749196486,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:357","message":"Defining indexer and retriever"}
{"level":"info","pid":13887,"method":"GraphKnowledge.newDocStore","space_id":"","model_name":"Qwen/Qwen2.5-Coder-32B-Instruct","time":1749196486,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:393","message":"Creating new doc store"}
{"level":"info","pid":13887,"method":"GraphKnowledge.newDocStore","time":1749196486,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:399","message":"Doc store created successfully"}
{"level":"info","pid":13887,"method":"DefineIndexerAndRetriever","time":1749196486,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:376","message":"Indexer and retriever defined successfully"}
{"level":"info","pid":13887,"method":"NewKnowledgeClient","endpoint":"lkeap.tencentcloudapi.com","region":"ap-guangzhou","secret_id":"","token":"","time":1749196487,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:43","message":"Creating new KnowledgeClient"}
{"level":"info","pid":13887,"method":"KnowledgeClient.Init","time":1749196487,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:51","message":"Initializing KnowledgeClient"}
{"level":"info","pid":13887,"method":"KnowledgeClient.Init","time":1749196487,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:109","message":"Initialization successful"}
{"level":"info","pid":13887,"time":1749196487,"caller":"/Users/wade/project/wuban/agentchat/main.go:267","message":"KnowledgeClient initialized successfully"}
{"level":"info","pid":14403,"time":1749196957,"caller":"/Users/wade/project/wuban/agentchat/log.go:68","message":"This message appears when log level set to Debug or Info"}
{"level":"info","pid":14403,"method":"DeepSeek.Init","time":1749196957,"caller":"/Users/wade/project/wuban/agentchat/plugins/deepseek/deepseek.go:91","message":"Initializing DeepSeek plugin"}
{"level":"info","pid":14403,"method":"DeepSeek.Init","time":1749196957,"caller":"/Users/wade/project/wuban/agentchat/plugins/deepseek/deepseek.go:104","message":"Initialization successful"}
{"level":"info","pid":14403,"method":"Milvus.Init","time":1749196957,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:75","message":"Initializing Milvus plugin"}
{"level":"info","pid":14403,"method":"Milvus.Init","time":1749196958,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:87","message":"Initialization successful"}
{"level":"info","pid":14403,"method":"GraphKnowledge.Init","time":1749196958,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:299","message":"Initializing GraphKnowledge plugin"}
{"level":"info","pid":14403,"method":"NewClient","ip":"54.92.111.204","port":5670,"time":1749196958,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:93","message":"Creating new GraphRAG client"}
{"level":"info","pid":14403,"method":"GraphKnowledge.Init","time":1749196958,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:311","message":"Initialization successful"}
{"level":"info","pid":14403,"method":"DefineIndexerAndRetriever","collection":"chatRag1","dimension":768,"time":1749196958,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:152","message":"Defining indexer and retriever"}
{"level":"info","pid":14403,"method":"Milvus.newDocStore","collection":"chatRag1","dimension":768,"time":1749196958,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:201","message":"Creating new doc store"}
{"level":"info","pid":14403,"method":"Milvus.newDocStore","collection":"chatRag1","time":1749196959,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:302","message":"Doc store created successfully"}
{"level":"info","pid":14403,"method":"DefineIndexerAndRetriever","collection":"chatRag1","time":1749196959,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:182","message":"Indexer and retriever defined successfully"}
{"level":"info","pid":14403,"method":"DefineIndexerAndRetriever","time":1749196959,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:357","message":"Defining indexer and retriever"}
{"level":"info","pid":14403,"method":"GraphKnowledge.newDocStore","space_id":"","model_name":"Qwen/Qwen2.5-Coder-32B-Instruct","time":1749196959,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:393","message":"Creating new doc store"}
{"level":"info","pid":14403,"method":"GraphKnowledge.newDocStore","time":1749196959,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:399","message":"Doc store created successfully"}
{"level":"info","pid":14403,"method":"DefineIndexerAndRetriever","time":1749196959,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:376","message":"Indexer and retriever defined successfully"}
{"level":"info","pid":14403,"method":"NewKnowledgeClient","endpoint":"lkeap.tencentcloudapi.com","region":"ap-guangzhou","secret_id":"","token":"","time":1749196960,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:43","message":"Creating new KnowledgeClient"}
{"level":"info","pid":14403,"method":"KnowledgeClient.Init","time":1749196960,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:51","message":"Initializing KnowledgeClient"}
{"level":"info","pid":14403,"method":"KnowledgeClient.Init","time":1749196960,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:109","message":"Initialization successful"}
{"level":"info","pid":14403,"time":1749196960,"caller":"/Users/wade/project/wuban/agentchat/main.go:267","message":"KnowledgeClient initialized successfully"}
{"level":"info","pid":14676,"time":1749197161,"caller":"/Users/wade/project/wuban/agentchat/log.go:68","message":"This message appears when log level set to Debug or Info"}
{"level":"info","pid":14676,"method":"DeepSeek.Init","time":1749197161,"caller":"/Users/wade/project/wuban/agentchat/plugins/deepseek/deepseek.go:91","message":"Initializing DeepSeek plugin"}
{"level":"info","pid":14676,"method":"DeepSeek.Init","time":1749197161,"caller":"/Users/wade/project/wuban/agentchat/plugins/deepseek/deepseek.go:104","message":"Initialization successful"}
{"level":"info","pid":14676,"method":"Milvus.Init","time":1749197161,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:75","message":"Initializing Milvus plugin"}
{"level":"info","pid":14676,"method":"Milvus.Init","time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:87","message":"Initialization successful"}
{"level":"info","pid":14676,"method":"GraphKnowledge.Init","time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:299","message":"Initializing GraphKnowledge plugin"}
{"level":"info","pid":14676,"method":"NewClient","ip":"54.92.111.204","port":5670,"time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:93","message":"Creating new GraphRAG client"}
{"level":"info","pid":14676,"method":"GraphKnowledge.Init","time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:311","message":"Initialization successful"}
{"level":"info","pid":14676,"method":"DefineIndexerAndRetriever","collection":"chatRag1","dimension":768,"time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:152","message":"Defining indexer and retriever"}
{"level":"info","pid":14676,"method":"Milvus.newDocStore","collection":"chatRag1","dimension":768,"time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:201","message":"Creating new doc store"}
{"level":"info","pid":14676,"method":"Milvus.newDocStore","collection":"chatRag1","time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:302","message":"Doc store created successfully"}
{"level":"info","pid":14676,"method":"DefineIndexerAndRetriever","collection":"chatRag1","time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:182","message":"Indexer and retriever defined successfully"}
{"level":"info","pid":14676,"method":"DefineIndexerAndRetriever","time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:357","message":"Defining indexer and retriever"}
{"level":"info","pid":14676,"method":"GraphKnowledge.newDocStore","space_id":"","model_name":"Qwen/Qwen2.5-Coder-32B-Instruct","time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:393","message":"Creating new doc store"}
{"level":"info","pid":14676,"method":"GraphKnowledge.newDocStore","time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:399","message":"Doc store created successfully"}
{"level":"info","pid":14676,"method":"DefineIndexerAndRetriever","time":1749197162,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:376","message":"Indexer and retriever defined successfully"}
{"level":"info","pid":14676,"method":"NewKnowledgeClient","endpoint":"lkeap.tencentcloudapi.com","region":"ap-guangzhou","secret_id":"","token":"","time":1749197163,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:43","message":"Creating new KnowledgeClient"}
{"level":"info","pid":14676,"method":"KnowledgeClient.Init","time":1749197163,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:51","message":"Initializing KnowledgeClient"}
{"level":"info","pid":14676,"method":"KnowledgeClient.Init","time":1749197163,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:109","message":"Initialization successful"}
{"level":"info","pid":14676,"time":1749197163,"caller":"/Users/wade/project/wuban/agentchat/main.go:267","message":"KnowledgeClient initialized successfully"}
{"level":"info","pid":14767,"time":1749197208,"caller":"/Users/wade/project/wuban/agentchat/log.go:68","message":"This message appears when log level set to Debug or Info"}
{"level":"info","pid":14767,"method":"DeepSeek.Init","time":1749197208,"caller":"/Users/wade/project/wuban/agentchat/plugins/deepseek/deepseek.go:91","message":"Initializing DeepSeek plugin"}
{"level":"info","pid":14767,"method":"DeepSeek.Init","time":1749197208,"caller":"/Users/wade/project/wuban/agentchat/plugins/deepseek/deepseek.go:104","message":"Initialization successful"}
{"level":"info","pid":14767,"method":"Milvus.Init","time":1749197208,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:75","message":"Initializing Milvus plugin"}
{"level":"info","pid":14767,"method":"Milvus.Init","time":1749197209,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:87","message":"Initialization successful"}
{"level":"info","pid":14767,"method":"GraphKnowledge.Init","time":1749197209,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:299","message":"Initializing GraphKnowledge plugin"}
{"level":"info","pid":14767,"method":"NewClient","ip":"54.92.111.204","port":5670,"time":1749197209,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:93","message":"Creating new GraphRAG client"}
{"level":"info","pid":14767,"method":"GraphKnowledge.Init","time":1749197209,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:311","message":"Initialization successful"}
{"level":"info","pid":14767,"method":"DefineIndexerAndRetriever","collection":"chatRag1","dimension":768,"time":1749197209,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:152","message":"Defining indexer and retriever"}
{"level":"info","pid":14767,"method":"Milvus.newDocStore","collection":"chatRag1","dimension":768,"time":1749197209,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:201","message":"Creating new doc store"}
{"level":"info","pid":14767,"method":"Milvus.newDocStore","collection":"chatRag1","time":1749197210,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:302","message":"Doc store created successfully"}
{"level":"info","pid":14767,"method":"DefineIndexerAndRetriever","collection":"chatRag1","time":1749197210,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:182","message":"Indexer and retriever defined successfully"}
{"level":"info","pid":14767,"method":"DefineIndexerAndRetriever","time":1749197210,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:357","message":"Defining indexer and retriever"}
{"level":"info","pid":14767,"method":"GraphKnowledge.newDocStore","space_id":"","model_name":"Qwen/Qwen2.5-Coder-32B-Instruct","time":1749197210,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:393","message":"Creating new doc store"}
{"level":"info","pid":14767,"method":"GraphKnowledge.newDocStore","time":1749197210,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:399","message":"Doc store created successfully"}
{"level":"info","pid":14767,"method":"DefineIndexerAndRetriever","time":1749197210,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:376","message":"Indexer and retriever defined successfully"}
{"level":"info","pid":14767,"method":"NewKnowledgeClient","endpoint":"lkeap.tencentcloudapi.com","region":"ap-guangzhou","secret_id":"","token":"","time":1749197210,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:43","message":"Creating new KnowledgeClient"}
{"level":"info","pid":14767,"method":"KnowledgeClient.Init","time":1749197210,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:51","message":"Initializing KnowledgeClient"}
{"level":"info","pid":14767,"method":"KnowledgeClient.Init","time":1749197210,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:109","message":"Initialization successful"}
{"level":"info","pid":14767,"time":1749197210,"caller":"/Users/wade/project/wuban/agentchat/main.go:267","message":"KnowledgeClient initialized successfully"}
{"level":"info","pid":14767,"time":1749197238,"caller":"/Users/wade/project/wuban/agentchat/main.go:281","message":"input--------{\"content\":\"What is the capital of UK?\",\"from\":\"Alice\",\"from_id\":\"user123\",\"to\":\"string\",\"to_id\":\"user456\",\"model\":\"gpt-3.5-turbo\",\"apiKey\":\"sk-1234567890abcdef\",\"milvus\":true}"}
{"level":"info","pid":14767,"time":1749197331,"caller":"/Users/wade/project/wuban/agentchat/main.go:281","message":"input--------{\"content\":\"What is the capital of UK?\",\"from\":\"Alice\",\"from_id\":\"user123\",\"to\":\"string\",\"to_id\":\"user456\",\"model\":\"gpt-3.5-turbo\",\"apiKey\":\"sk-1234567890abcdef\",\"milvus\":true}"}
{"level":"info","pid":15018,"time":1749197572,"caller":"/Users/wade/project/wuban/agentchat/log.go:68","message":"This message appears when log level set to Debug or Info"}
{"level":"info","pid":15018,"method":"DeepSeek.Init","time":1749197572,"caller":"/Users/wade/project/wuban/agentchat/plugins/deepseek/deepseek.go:91","message":"Initializing DeepSeek plugin"}
{"level":"info","pid":15018,"method":"DeepSeek.Init","time":1749197572,"caller":"/Users/wade/project/wuban/agentchat/plugins/deepseek/deepseek.go:104","message":"Initialization successful"}
{"level":"info","pid":15018,"method":"Milvus.Init","time":1749197572,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:75","message":"Initializing Milvus plugin"}
{"level":"info","pid":15018,"method":"Milvus.Init","time":1749197574,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:87","message":"Initialization successful"}
{"level":"info","pid":15018,"method":"GraphKnowledge.Init","time":1749197574,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:299","message":"Initializing GraphKnowledge plugin"}
{"level":"info","pid":15018,"method":"NewClient","ip":"54.92.111.204","port":5670,"time":1749197574,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:93","message":"Creating new GraphRAG client"}
{"level":"info","pid":15018,"method":"GraphKnowledge.Init","time":1749197574,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:311","message":"Initialization successful"}
{"level":"info","pid":15018,"method":"DefineIndexerAndRetriever","collection":"chatRag1","dimension":768,"time":1749197574,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:152","message":"Defining indexer and retriever"}
{"level":"info","pid":15018,"method":"Milvus.newDocStore","collection":"chatRag1","dimension":768,"time":1749197574,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:201","message":"Creating new doc store"}
{"level":"info","pid":15018,"method":"Milvus.newDocStore","collection":"chatRag1","time":1749197575,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:302","message":"Doc store created successfully"}
{"level":"info","pid":15018,"method":"DefineIndexerAndRetriever","collection":"chatRag1","time":1749197575,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:182","message":"Indexer and retriever defined successfully"}
{"level":"info","pid":15018,"method":"DefineIndexerAndRetriever","time":1749197575,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:357","message":"Defining indexer and retriever"}
{"level":"info","pid":15018,"method":"GraphKnowledge.newDocStore","space_id":"","model_name":"Qwen/Qwen2.5-Coder-32B-Instruct","time":1749197575,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:393","message":"Creating new doc store"}
{"level":"info","pid":15018,"method":"GraphKnowledge.newDocStore","time":1749197575,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:399","message":"Doc store created successfully"}
{"level":"info","pid":15018,"method":"DefineIndexerAndRetriever","time":1749197575,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:376","message":"Indexer and retriever defined successfully"}
{"level":"info","pid":15018,"method":"NewKnowledgeClient","endpoint":"lkeap.tencentcloudapi.com","region":"ap-guangzhou","secret_id":"","token":"","time":1749197576,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:43","message":"Creating new KnowledgeClient"}
{"level":"info","pid":15018,"method":"KnowledgeClient.Init","time":1749197576,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:51","message":"Initializing KnowledgeClient"}
{"level":"info","pid":15018,"method":"KnowledgeClient.Init","time":1749197576,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:109","message":"Initialization successful"}
{"level":"info","pid":15018,"time":1749197576,"caller":"/Users/wade/project/wuban/agentchat/main.go:267","message":"KnowledgeClient initialized successfully"}
{"level":"info","pid":15018,"time":1749197593,"caller":"/Users/wade/project/wuban/agentchat/main.go:281","message":"input--------{\"content\":\"What is the capital of UK?\",\"from\":\"Alice\",\"from_id\":\"user123\",\"to\":\"string\",\"to_id\":\"user456\",\"model\":\"gpt-3.5-turbo\",\"apiKey\":\"sk-1234567890abcdef\",\"milvus\":true}"}
{"level":"info","pid":15018,"time":1749197593,"caller":"/Users/wade/project/wuban/agentchat/main.go:307","message":"qaAsJson--------{\"ID\":48,\"CreatedAt\":\"2025-06-06T07:06:25.067252Z\",\"FromID\":\"user123\",\"From\":\"Alice\",\"Question\":\"What is the capital of UK?\",\"Answer\":\"I'm sorry, but I don't have the information to answer your question about the capital of the UK based on the provided context. The context mentions Paris as the capital of France and the USA as the largest importer of coffee, but it doesn't include information about the UK.\\n\",\"Summary\":\"Conversation summary: What is the capital of the UK?\",\"To\":\"Bob\",\"ToID\":\"user456\",\"Milvus\":false,\"Graph\":false}"}
{"level":"info","pid":15018,"method":"docStore.Retrieve","collection":"chatRag1","time":1749197593,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:450","message":"Starting retrieve operation"}
{"level":"info","pid":15018,"method":"docStore.Retrieve","collection":"chatRag1","documents":2,"time":1749197598,"caller":"/Users/wade/project/wuban/agentchat/plugins/milvus/milvus.go:640","message":"Retrieve operation completed successfully"}
{"level":"info","pid":15018,"time":1749197598,"caller":"/Users/wade/project/wuban/agentchat/main.go:333","message":"promptInput.Context: Paris is the capital of France?\nUSA is the largest importer of coffee?\n"}
{"level":"info","pid":15018,"method":"docStore.Retrieve","space_id":"","time":1749197598,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:755","message":"Starting retrieve operation"}
{"level":"info","pid":15018,"method":"docStore.Retrieve","space_id":"","documents":1,"time":1749197606,"caller":"/Users/wade/project/wuban/agentchat/plugins/graphrag/graph.go:892","message":"Retrieve operation completed successfully"}
{"level":"info","pid":15018,"time":1749197606,"caller":"/Users/wade/project/wuban/agentchat/main.go:348","message":"promptInput.Graph : 知识库中提供的内容不足以回答此问题\n\n<references title=\"References\" references=\"[]\" />\n"}
{"level":"info","pid":15018,"from":"Alice","from_id":"user123","to":"string","to_id":"user456","promptInput.Query":"What is the capital of UK?","resp.Text()":"I'm sorry, but the provided context doesn't contain information about the capital of the UK.\n","promptInput.Summary":"Conversation summary: What is the capital of the UK?","time":1749197607,"caller":"/Users/wade/project/wuban/agentchat/main.go:375","message":"QueryRewriteWithSummary"}
{"level":"info","pid":15018,"method":"KnowledgeClient.QueryRewriteWithSummary","user_question":"What is the capital of UK?","assistant_answer":"I'm sorry, but the provided context doesn't contain information about the capital of the UK.\n","history_summary":"Conversation summary: What is the capital of the UK?","time":1749197607,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:256","message":"Starting query rewrite with summary operation"}
{"level":"info","pid":15018,"method":"KnowledgeClient.QueryRewrite","message_count":3,"model":"lke-query-rewrite-base","time":1749197607,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:131","message":"Starting query rewrite operation"}
{"level":"info","pid":15018,"method":"KnowledgeClient.QueryRewrite","rewritten_query":"Conversation summary: Conversation summary: What is the capital of the UK?","request_id":"17ee0ba6-92ef-4fee-a388-4fec87c6db85","usage":{"InputTokens":74,"OutputTokens":15,"TotalTokens":89},"raw_response":"{\"Response\":{\"Content\":\"Conversation summary: Conversation summary: What is the capital of the UK?\",\"Usage\":{\"InputTokens\":74,\"OutputTokens\":15,\"TotalTokens\":89},\"RequestId\":\"17ee0ba6-92ef-4fee-a388-4fec87c6db85\"}}","time":1749197611,"caller":"/Users/wade/project/wuban/agentchat/plugins/knowledge/knowledge.go:237","message":"Query rewrite operation completed successfully"}
{"level":"info","pid":15018,"from":"Alice","from_id":"user123","to":"string","to_id":"user456","question":"What is the capital of UK?","context":"Paris is the capital of France?\nUSA is the largest importer of coffee?\n","graph":"知识库中提供的内容不足以回答此问题\n\n<references title=\"References\" references=\"[]\" />\n","last summary":"Conversation summary: What is the capital of the UK?","answer":"I'm sorry, but the provided context doesn't contain information about the capital of the UK.\n","time":1749197612,"caller":"/Users/wade/project/wuban/agentchat/main.go:401","message":"Question and answer pair recorded"}
......@@ -152,7 +152,7 @@ paths:
/chat:
post:
summary: Send a chat message
description: Sends a chat message to the Genkit AI workflow and returns a response.
description: Sends a chat message to the Genkit AI workflow and returns a response, with optional Milvus and GraphRAG indexing flags.
tags:
- Chat
requestBody:
......@@ -184,12 +184,19 @@ paths:
example: "user123"
to:
type: string
description: The recipient of the chat message
example: "Bob"
description: The recipient of the chat message example Bob
to_id:
type: string
description: The unique identifier for the recipient
example: "user456"
milvus:
type: boolean
description: Whether to use Milvus indexing for the chat content
example: true
graph:
type: boolean
description: Whether to use GraphRAG indexing for the chat content
example: false
required:
- content
responses:
......
package main
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
"time"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/wade-liwei/agentchat/plugins/milvus"
)
func startServer(g *genkit.Genkit, db *sql.DB, indexer ai.Indexer, retriever ai.Retriever, embedder ai.Embedder, apiKey string) {
http.HandleFunc("/idx/milvus", handleIndex(indexer, embedder, "Milvus"))
http.HandleFunc("/idx/graphrag", handleIndex(indexer, embedder, "GraphRAG")) // 如果需要支持 GraphRAG
http.HandleFunc("/index", handleIndexTrigger(g, db, indexer, apiKey))
http.HandleFunc("/askQuestion", handleAskQuestion(g, retriever))
addr := fmt.Sprintf(":%s", *port)
log.Printf("Starting server on %s", addr)
if err := http.ListenAndServe(addr, nil); err != nil {
log.Fatalf("Server failed: %v", err)
}
}
func handleIndex(indexer ai.Indexer, embedder ai.Embedder, indexType string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, `{"error":"Method not allowed"}`, http.StatusMethodNotAllowed)
return
}
var req IndexRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, `{"error":"Invalid request body"}`, http.StatusBadRequest)
return
}
if req.Question == "" || req.Answer == "" {
http.Error(w, `{"error":"Missing required fields: question and answer"}`, http.StatusBadRequest)
return
}
var userID *int64
if req.UserID != nil {
id, err := strconv.ParseInt(*req.UserID, 10, 64)
if err != nil {
http.Error(w, `{"error":"Invalid user_id format"}`, http.StatusBadRequest)
return
}
userID = &id
}
// 构造文本内容
text := req.Question + " " + req.Answer
if req.Summary != nil {
text += " " + *req.Summary
}
// 构造元数据
metadata := map[string]interface{}{
"username": req.Username,
"user_id": userID,
}
// 生成唯一 ID(由于 Milvus 插件的 schema idField AutoID,这里仅用于响应)
id := time.Now().UnixNano()
// 创建文档
doc := &ai.Document{
Content: []*ai.Part{ai.NewTextPart(text)},
Metadata: metadata,
}
// 使用 Indexer 写入 Milvus
err := ai.Index(r.Context(), indexer, ai.WithDocs(doc))
if err != nil {
log.Printf("Failed to index %s data: %v", indexType, err)
http.Error(w, `{"error":"Failed to store data"}`, http.StatusInternalServerError)
return
}
resp := IndexResponse{ID: id}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(resp); err != nil {
log.Printf("Failed to encode response: %v", err)
}
}
}
func handleIndexTrigger(g *genkit.Genkit, db *sql.DB, indexer ai.Indexer, expectedAPIKey string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, `{"error":"Method not allowed"}`, http.StatusMethodNotAllowed)
return
}
var req IndexTriggerRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, `{"error":"Invalid request body"}`, http.StatusBadRequest)
return
}
if req.APIKey != expectedAPIKey {
http.Error(w, `{"error":"Invalid API key"}`, http.StatusBadRequest)
return
}
if err := indexExistingRows(r.Context(), db, indexer); err != nil {
log.Printf("Failed to index data: %v", err)
http.Error(w, `{"error":"Failed to index data"}`, http.StatusInternalServerError)
return
}
resp := IndexTriggerResponse{Message: "Indexing completed successfully"}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(resp); err != nil {
log.Printf("Failed to encode response: %v", err)
}
}
}
func handleAskQuestion(g *genkit.Genkit, retriever ai.Retriever) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, `{"error":"Method not allowed"}`, http.StatusMethodNotAllowed)
return
}
var input struct {
Question string `json:"Question"`
Show string `json:"Show"`
}
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
http.Error(w, `{"error":"Invalid request body"}`, http.StatusBadRequest)
return
}
if input.Question == "" || input.Show == "" {
http.Error(w, `{"error":"Missing required fields: Question and Show"}`, http.StatusBadRequest)
return
}
// 创建查询文档
queryDoc := &ai.Document{
Content: []*ai.Part{ai.NewTextPart(input.Question)},
}
// 使用 Retriever 检索
retrieverOptions := &milvus.RetrieverOptions{
Count: 3, // 获取前 3 个结果
MetricType: "L2",
}
result, err := ai.Retrieve(r.Context(), retriever, ai.WithQuery(queryDoc), ai.WithOptions(retrieverOptions))
if err != nil {
log.Printf("Failed to retrieve data: %v", err)
http.Error(w, `{"error":"Failed to process question"}`, http.StatusInternalServerError)
return
}
// 构造响应(可以根据需要处理检索结果)
var responseText string
for _, doc := range result.Documents {
for _, part := range doc.Content {
if part.IsText() {
responseText += part.Text + "\n"
}
}
}
resp := struct {
Response string `json:"response"`
}{Response: responseText}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(resp); err != nil {
log.Printf("Failed to encode response: %v", err)
}
}
}
func indexExistingRows(ctx context.Context, db *sql.DB, indexer ai.Indexer) error {
rows, err := db.QueryContext(ctx, `SELECT id, question, answer, summary FROM qa`)
if err != nil {
return err
}
defer rows.Close()
var docs []*ai.Document
for rows.Next() {
var id int64
var question, answer, summary sql.NullString
if err := rows.Scan(&id, &question, &answer, &summary); err != nil {
return err
}
content := question.String
if answer.Valid {
content += " " + answer.String
}
if summary.Valid {
content += " " + summary.String
}
docs = append(docs, &ai.Document{
Content: []*ai.Part{ai.NewTextPart(content)},
Metadata: map[string]interface{}{
"id": id,
},
})
}
if err := rows.Err(); err != nil {
return err
}
return ai.Index(ctx, indexer, ai.WithDocs(docs...))
}
\ No newline at end of file
......@@ -32,12 +32,15 @@ import (
type ChatInput struct {
Content string `json:"content,omitempty"`
Model string `json:"model,omitempty"`
APIKey string `json:"apiKey,omitempty"`
From string `json:"from,omitempty"` // 替换 Username
FromID string `json:"from_id,omitempty"` // 替换 UserID
To string `json:"to,"`
ToID string `json:"to_id,omitempty"`
//
Model string `json:"model,omitempty"`
APIKey string `json:"apiKey,omitempty"`
Milvus bool `json:"milvus,omitempty"`
Graph bool `json:"graph,omitempty"`
}
// DocumentInput 结构体用于文档索引接口
......@@ -283,6 +286,8 @@ func main() {
Question: &input.Content,
To: &input.To,
ToID: &input.ToID,
Milvus: &input.Milvus,
Graph: &input.Graph,
})
if err != nil {
......@@ -358,18 +363,18 @@ func main() {
if lastok {
if promptInput.Summary == ""{
promptInput.Summary = resp.Text()
if promptInput.Summary == "" {
promptInput.Summary = resp.Text()
}
log.Info().
Str("from",input.From).
Str("from_id",input.FromID).
Str("to",input.To).
Str("to_id",input.ToID).
Str("promptInput.Query",promptInput.Query).
Str("resp.Text()",resp.Text()).
Str("promptInput.Summary",promptInput.Summary).Msg("QueryRewriteWithSummary")
Str("from", input.From).
Str("from_id", input.FromID).
Str("to", input.To).
Str("to_id", input.ToID).
Str("promptInput.Query", promptInput.Query).
Str("resp.Text()", resp.Text()).
Str("promptInput.Summary", promptInput.Summary).Msg("QueryRewriteWithSummary")
res, err := kc.QueryRewriteWithSummary(context.Background(), promptInput.Query, resp.Text(), promptInput.Summary)
......@@ -378,7 +383,7 @@ func main() {
} else {
qa.UpdateQAFields(context.Background(), idx, res.RewrittenQuery, resp.Text())
/*
{"RewrittenQuery":"Conversation summary: The available knowledge base does not contain information about the capital of the UK.","RawResponse":{"Response":{"Content":"Conversation summary: The available knowledge base does not contain information about the capital of the UK.","Usage":{"InputTokens":74,"OutputTokens":19,"TotalTokens":93},"RequestId":"15f1ce0c-a83f-4d95-af22-33a3bd829e8d"}}}
{"RewrittenQuery":"Conversation summary: The available knowledge base does not contain information about the capital of the UK.","RawResponse":{"Response":{"Content":"Conversation summary: The available knowledge base does not contain information about the capital of the UK.","Usage":{"InputTokens":74,"OutputTokens":19,"TotalTokens":93},"RequestId":"15f1ce0c-a83f-4d95-af22-33a3bd829e8d"}}}
*/
}
} else {
......@@ -386,10 +391,10 @@ func main() {
}
log.Info().
Str("from",input.From).
Str("from_id",input.FromID).
Str("to",input.To).
Str("to_id",input.ToID).
Str("from", input.From).
Str("from_id", input.FromID).
Str("to", input.To).
Str("to_id", input.ToID).
Str("question", promptInput.Query).
Str("context", promptInput.Context).
Str("graph", promptInput.Graph).
......
......@@ -144,8 +144,8 @@ func TestKnowledgeClient_QueryRewriteWithSummary(t *testing.T) {
name: "ValidWithSummary",
userQuestion: "你的家在哪里",
assistantAnswer: "国内",
historySummary: "null", //"User asked about location preferences earlier.",
expectError: true, // Expect error due to potentially invalid credentials
historySummary: "null", //"User asked about location preferences earlier.",
expectError: true, // Expect error due to potentially invalid credentials
},
}
......
......@@ -8,10 +8,13 @@ create table public.qa (
"to" text null,
from_id text null,
to_id text null,
milvus boolean null default false,
graph boolean null default false,
constraint qa_pkey primary key (id)
) TABLESPACE pg_default;
CREATE VIEW public.qa_latest_from_id AS
SELECT DISTINCT ON (qa.from_id)
qa.id,
......@@ -22,7 +25,9 @@ SELECT DISTINCT ON (qa.from_id)
qa."from",
qa."to",
qa.from_id,
qa.to_id
qa.to_id,
qa.milvus,
qa.graph
FROM
qa
WHERE
......
......@@ -19,6 +19,8 @@ type QA struct {
Summary *string // 可空的摘要
To *string // 可空的 to
ToID *string // 可空的 to_id
Milvus *bool // 可空的 milvus,默认为 false
Graph *bool // 可空的 graph,默认为 false
}
// QAStore 定义 DAO 接口
......@@ -45,9 +47,6 @@ func NewQAStore(db *sql.DB) QAStore {
// 初始化数据库连接并返回 QAStore
func InitQAStore(connString string) (QAStore, error) {
// Supabase 提供的连接字符串
//connString := "postgresql://postgres.awcfgdodiuqnlsobcivq:P99IU9NEoDRPsBfb@aws-0-ap-southeast-1.pooler.supabase.com:5432/postgres"
// 打开数据库连接
db, err := sql.Open("postgres", connString)
if err != nil {
......@@ -66,7 +65,7 @@ func InitQAStore(connString string) (QAStore, error) {
func (s *qaStore) GetLatestQA(ctx context.Context, fromID *string) ([]QA, error) {
query := `
SELECT id, created_at, question, answer, summary, "from", "to", from_id, to_id
SELECT id, created_at, question, answer, summary, "from", "to", from_id, to_id, milvus, graph
FROM qa_latest_from_id
WHERE from_id = $1 OR (from_id IS NULL AND $1 IS NULL)`
args := []interface{}{fromID}
......@@ -84,7 +83,8 @@ func (s *qaStore) GetLatestQA(ctx context.Context, fromID *string) ([]QA, error)
for rows.Next() {
var qa QA
var question, answer, summary, from, to, fromIDVal, toIDVal sql.NullString
if err := rows.Scan(&qa.ID, &qa.CreatedAt, &question, &answer, &summary, &from, &to, &fromIDVal, &toIDVal); err != nil {
var milvus, graph sql.NullBool
if err := rows.Scan(&qa.ID, &qa.CreatedAt, &question, &answer, &summary, &from, &to, &fromIDVal, &toIDVal, &milvus, &graph); err != nil {
return nil, fmt.Errorf("scan row: %w", err)
}
if question.Valid {
......@@ -108,6 +108,12 @@ func (s *qaStore) GetLatestQA(ctx context.Context, fromID *string) ([]QA, error)
if toIDVal.Valid {
qa.ToID = &toIDVal.String
}
if milvus.Valid {
qa.Milvus = &milvus.Bool
}
if graph.Valid {
qa.Graph = &graph.Bool
}
results = append(results, qa)
}
if err := rows.Err(); err != nil {
......@@ -121,8 +127,8 @@ func (s *qaStore) WriteQA(ctx context.Context, qa QA) (int64, error) {
// 更新记录
query := `
UPDATE qa
SET question = $1, answer = $2, summary = $3, "from" = $4, "to" = $5, from_id = $6, to_id = $7
WHERE id = $8
SET question = $1, answer = $2, summary = $3, "from" = $4, "to" = $5, from_id = $6, to_id = $7, milvus = $8, graph = $9
WHERE id = $10
RETURNING id`
var updatedID int64
err := s.db.QueryRowContext(ctx, query,
......@@ -133,6 +139,8 @@ func (s *qaStore) WriteQA(ctx context.Context, qa QA) (int64, error) {
derefString(qa.To),
derefString(qa.FromID),
derefString(qa.ToID),
derefBool(qa.Milvus),
derefBool(qa.Graph),
qa.ID,
).Scan(&updatedID)
if err == sql.ErrNoRows {
......@@ -146,8 +154,8 @@ func (s *qaStore) WriteQA(ctx context.Context, qa QA) (int64, error) {
// 插入新记录
query := `
INSERT INTO qa (question, answer, summary, "from", "to", from_id, to_id)
VALUES ($1, $2, $3, $4, $5, $6, $7)
INSERT INTO qa (question, answer, summary, "from", "to", from_id, to_id, milvus, graph)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING id`
var newID int64
err := s.db.QueryRowContext(ctx, query,
......@@ -158,6 +166,8 @@ func (s *qaStore) WriteQA(ctx context.Context, qa QA) (int64, error) {
derefString(qa.To),
derefString(qa.FromID),
derefString(qa.ToID),
derefBool(qa.Milvus),
derefBool(qa.Graph),
).Scan(&newID)
if err != nil {
return 0, fmt.Errorf("insert qa: %w", err)
......@@ -225,463 +235,28 @@ func derefString(p *string) interface{} {
return *p
}
// package main
// import (
// "context"
// "database/sql"
// "flag"
// "fmt"
// "time"
// _ "github.com/lib/pq"
// )
// var (
// connString = flag.String("dbconn", "", "database connection string")
// )
// type QA struct {
// ID int64 // 主键
// CreatedAt time.Time // 创建时间
// FromID *string // 可空的 from_id
// From *string // 可空的 from
// Question *string // 可空的问题
// Answer *string // 可空的答案
// Summary *string // 可空的摘要
// To *string // 可空的 to
// ToID *string // 可空的 to_id
// }
// // QAStore 定义 DAO 接口
// type QAStore interface {
// // GetLatestQA 从 qa_latest_from_id 视图读取指定 from_id 的最新记录
// GetLatestQA(ctx context.Context, fromID *string) ([]QA, error)
// // WriteQA 插入或更新 qa 表记录
// WriteQA(ctx context.Context, qa QA) (int64, error)
// // WriteAndGetLatestQA 先查询最新记录,再写入 QA 记录,返回写入的 ID、第一条查询结果、是否查询到结果和错误
// WriteAndGetLatestQA(ctx context.Context, qa QA) (int64, *QA, bool, error)
// // UpdateSummary 根据 idx 更新 qa 表中指定记录的 summary 字段
// UpdateSummary(ctx context.Context, idx int64, summary string) error
// }
// // qaStore 是 QAStore 接口的实现
// type qaStore struct {
// db *sql.DB
// }
// // NewQAStore 创建新的 QAStore 实例
// func NewQAStore(db *sql.DB) QAStore {
// return &qaStore{db: db}
// }
// // 初始化数据库连接并返回 QAStore
// func InitQAStore() (QAStore, error) {
// // Supabase 提供的连接字符串
// connString := "postgresql://postgres.awcfgdodiuqnlsobcivq:P99IU9NEoDRPsBfb@aws-0-ap-southeast-1.pooler.supabase.com:5432/postgres"
// // 打开数据库连接
// db, err := sql.Open("postgres", connString)
// if err != nil {
// return nil, fmt.Errorf("open database: %w", err)
// }
// // 测试数据库连接
// if err := db.Ping(); err != nil {
// db.Close()
// return nil, fmt.Errorf("ping database: %w", err)
// }
// // 返回 QAStore 实例
// return NewQAStore(db), nil
// }
// func (s *qaStore) GetLatestQA(ctx context.Context, fromID *string) ([]QA, error) {
// query := `
// SELECT id, created_at, question, answer, summary, "from", "to", from_id, to_id
// FROM qa_latest_from_id
// WHERE from_id = $1 OR (from_id IS NULL AND $1 IS NULL)`
// args := []interface{}{fromID}
// if fromID == nil {
// args = []interface{}{nil}
// }
// rows, err := s.db.QueryContext(ctx, query, args...)
// if err != nil {
// return nil, fmt.Errorf("query qa_latest_from_id: %w", err)
// }
// defer rows.Close()
// var results []QA
// for rows.Next() {
// var qa QA
// var question, answer, summary, from, to, fromIDVal, toIDVal sql.NullString
// if err := rows.Scan(&qa.ID, &qa.CreatedAt, &question, &answer, &summary, &from, &to, &fromIDVal, &toIDVal); err != nil {
// return nil, fmt.Errorf("scan row: %w", err)
// }
// if question.Valid {
// qa.Question = &question.String
// }
// if answer.Valid {
// qa.Answer = &answer.String
// }
// if summary.Valid {
// qa.Summary = &summary.String
// }
// if from.Valid {
// qa.From = &from.String
// }
// if to.Valid {
// qa.To = &to.String
// }
// if fromIDVal.Valid {
// qa.FromID = &fromIDVal.String
// }
// if toIDVal.Valid {
// qa.ToID = &toIDVal.String
// }
// results = append(results, qa)
// }
// if err := rows.Err(); err != nil {
// return nil, fmt.Errorf("row iteration: %w", err)
// }
// return results, nil
// }
// func (s *qaStore) WriteQA(ctx context.Context, qa QA) (int64, error) {
// if qa.ID != 0 {
// // 更新记录
// query := `
// UPDATE qa
// SET question = $1, answer = $2, summary = $3, "from" = $4, "to" = $5, from_id = $6, to_id = $7
// WHERE id = $8
// RETURNING id`
// var updatedID int64
// err := s.db.QueryRowContext(ctx, query,
// derefString(qa.Question),
// derefString(qa.Answer),
// derefString(qa.Summary),
// derefString(qa.From),
// derefString(qa.To),
// derefString(qa.FromID),
// derefString(qa.ToID),
// qa.ID,
// ).Scan(&updatedID)
// if err == sql.ErrNoRows {
// return 0, fmt.Errorf("no record found with id %d", qa.ID)
// }
// if err != nil {
// return 0, fmt.Errorf("update qa: %w", err)
// }
// return updatedID, nil
// }
// // 插入新记录
// query := `
// INSERT INTO qa (question, answer, summary, "from", "to", from_id, to_id)
// VALUES ($1, $2, $3, $4, $5, $6, $7)
// RETURNING id`
// var newID int64
// err := s.db.QueryRowContext(ctx, query,
// derefString(qa.Question),
// derefString(qa.Answer),
// derefString(qa.Summary),
// derefString(qa.From),
// derefString(qa.To),
// derefString(qa.FromID),
// derefString(qa.ToID),
// ).Scan(&newID)
// if err != nil {
// return 0, fmt.Errorf("insert qa: %w", err)
// }
// return newID, nil
// }
// func (s *qaStore) WriteAndGetLatestQA(ctx context.Context, qa QA) (int64, *QA, bool, error) {
// // 先查询最新记录
// results, err := s.GetLatestQA(ctx, qa.FromID)
// if err != nil {
// return 0, nil, false, fmt.Errorf("get latest qa: %w", err)
// }
// // 检查查询结果是否为空
// var latestQA *QA
// hasResult := len(results) > 0
// if hasResult {
// latestQA = &results[0] // 取第一条记录
// } else {
// latestQA = nil // 空结果
// }
// // 写入记录
// id, err := s.WriteQA(ctx, qa)
// if err != nil {
// return 0, latestQA, hasResult, fmt.Errorf("write qa: %w", err)
// }
// // 返回写入的 ID、第一条查询结果和 hasResult
// return id, latestQA, hasResult, nil
// }
// // UpdateSummary 根据 idx 更新 qa 表中指定记录的 summary 字段
// func (s *qaStore) UpdateSummary(ctx context.Context, idx int64, summary string) error {
// query := `
// UPDATE qa
// SET summary = $1
// WHERE id = $2`
// result, err := s.db.ExecContext(ctx, query, summary, idx)
// if err != nil {
// return fmt.Errorf("update summary: %w", err)
// }
// rowsAffected, err := result.RowsAffected()
// if err != nil {
// return fmt.Errorf("check rows affected: %w", err)
// }
// if rowsAffected == 0 {
// return fmt.Errorf("no record found with id %d", idx)
// }
// return nil
// }
// // 辅助函数:处理指针类型的空值
// func stringPtr(s string) *string {
// return &s
// }
// func derefString(p *string) interface{} {
// if p == nil {
// return nil
// }
// return *p
// }
// package main
// import (
// "context"
// "database/sql"
// "flag"
// "fmt"
// "time"
// _ "github.com/lib/pq"
// )
// var (
// connString = flag.String("dbconn", "", "database connection string")
// )
// type QA struct {
// ID int64 // 主键
// CreatedAt time.Time // 创建时间
// FromID *string // 可空的 from_id
// From *string // 可空的 from
// Question *string // 可空的问题
// Answer *string // 可空的答案
// Summary *string // 可空的摘要
// To *string // 可空的 to
// ToID *string // 可空的 to_id
// }
// // QAStore 定义 DAO 接口
// type QAStore interface {
// // GetLatestQA 从 qa_latest_from_id 视图读取指定 from_id 的最新记录
// GetLatestQA(ctx context.Context, fromID *string) ([]QA, error)
// // WriteQA 插入或更新 qa 表记录
// WriteQA(ctx context.Context, qa QA) (int64, error)
// // WriteAndGetLatestQA 先查询最新记录,再写入 QA 记录,返回写入的 ID、第一条查询结果、是否查询到结果和错误
// WriteAndGetLatestQA(ctx context.Context, qa QA) (int64, *QA, bool, error)
// }
// // qaStore 是 QAStore 接口的实现
// type qaStore struct {
// db *sql.DB
// }
// // NewQAStore 创建新的 QAStore 实例
// func NewQAStore(db *sql.DB) QAStore {
// return &qaStore{db: db}
// }
// // 初始化数据库连接并返回 QAStore
// func InitQAStore() (QAStore, error) {
// // Supabase 提供的连接字符串
// connString := "postgresql://postgres.awcfgdodiuqnlsobcivq:P99IU9NEoDRPsBfb@aws-0-ap-southeast-1.pooler.supabase.com:5432/postgres"
// // 打开数据库连接
// db, err := sql.Open("postgres", connString)
// if err != nil {
// return nil, fmt.Errorf("open database: %w", err)
// }
// // 测试数据库连接
// if err := db.Ping(); err != nil {
// db.Close()
// return nil, fmt.Errorf("ping database: %w", err)
// }
// // 返回 QAStore 实例
// return NewQAStore(db), nil
// }
// func (s *qaStore) GetLatestQA(ctx context.Context, fromID *string) ([]QA, error) {
// query := `
// SELECT id, created_at, question, answer, summary, "from", "to", from_id, to_id
// FROM qa_latest_from_id
// WHERE from_id = $1 OR (from_id IS NULL AND $1 IS NULL)`
// args := []interface{}{fromID}
// if fromID == nil {
// args = []interface{}{nil}
// }
// rows, err := s.db.QueryContext(ctx, query, args...)
// if err != nil {
// return nil, fmt.Errorf("query qa_latest_from_id: %w", err)
// }
// defer rows.Close()
// var results []QA
// for rows.Next() {
// var qa QA
// var question, answer, summary, from, to, fromIDVal, toIDVal sql.NullString
// if err := rows.Scan(&qa.ID, &qa.CreatedAt, &question, &answer, &summary, &from, &to, &fromIDVal, &toIDVal); err != nil {
// return nil, fmt.Errorf("scan row: %w", err)
// }
// if question.Valid {
// qa.Question = &question.String
// }
// if answer.Valid {
// qa.Answer = &answer.String
// }
// if summary.Valid {
// qa.Summary = &summary.String
// }
// if from.Valid {
// qa.From = &from.String
// }
// if to.Valid {
// qa.To = &to.String
// }
// if fromIDVal.Valid {
// qa.FromID = &fromIDVal.String
// }
// if toIDVal.Valid {
// qa.ToID = &toIDVal.String
// }
// results = append(results, qa)
// }
// if err := rows.Err(); err != nil {
// return nil, fmt.Errorf("row iteration: %w", err)
// }
// return results, nil
// }
// func (s *qaStore) WriteQA(ctx context.Context, qa QA) (int64, error) {
// if qa.ID != 0 {
// // 更新记录
// query := `
// UPDATE qa
// SET question = $1, answer = $2, summary = $3, "from" = $4, "to" = $5, from_id = $6, to_id = $7
// WHERE id = $8
// RETURNING id`
// var updatedID int64
// err := s.db.QueryRowContext(ctx, query,
// derefString(qa.Question),
// derefString(qa.Answer),
// derefString(qa.Summary),
// derefString(qa.From),
// derefString(qa.To),
// derefString(qa.FromID),
// derefString(qa.ToID),
// qa.ID,
// ).Scan(&updatedID)
// if err == sql.ErrNoRows {
// return 0, fmt.Errorf("no record found with id %d", qa.ID)
// }
// if err != nil {
// return 0, fmt.Errorf("update qa: %w", err)
// }
// return updatedID, nil
// }
// // 插入新记录
// query := `
// INSERT INTO qa (question, answer, summary, "from", "to", from_id, to_id)
// VALUES ($1, $2, $3, $4, $5, $6, $7)
// RETURNING id`
// var newID int64
// err := s.db.QueryRowContext(ctx, query,
// derefString(qa.Question),
// derefString(qa.Answer),
// derefString(qa.Summary),
// derefString(qa.From),
// derefString(qa.To),
// derefString(qa.FromID),
// derefString(qa.ToID),
// ).Scan(&newID)
// if err != nil {
// return 0, fmt.Errorf("insert qa: %w", err)
// }
// return newID, nil
// }
// // WriteAndGetLatestQA 先查询最新记录,再写入 QA 记录,返回写入的 ID、第一条查询结果、是否查询到结果和错误
// func (s *qaStore) WriteAndGetLatestQA(ctx context.Context, qa QA) (int64, *QA, bool, error) {
// // 先查询最新记录
// results, err := s.GetLatestQA(ctx, qa.FromID)
// if err != nil {
// return 0, nil, false, fmt.Errorf("get latest qa: %w", err)
// }
// // 检查查询结果是否为空
// var latestQA *QA
// hasResult := len(results) > 0
// if hasResult {
// latestQA = &results[0] // 取第一条记录
// } else {
// latestQA = nil // 空结果
// }
// // 写入记录
// id, err := s.WriteQA(ctx, qa)
// if err != nil {
// return 0, latestQA, hasResult, fmt.Errorf("write qa: %w", err)
// }
// // 返回写入的 ID、第一条查询结果和 hasResult
// return id, latestQA, hasResult, nil
// }
// // 辅助函数:处理指针类型的空值
// func stringPtr(s string) *string {
// return &s
// }
func boolPtr(b bool) *bool {
return &b
}
// func derefString(p *string) interface{} {
// if p == nil {
// return nil
// }
// return *p
// }
func derefBool(p *bool) interface{} {
if p == nil {
return nil
}
return *p
}
// package main
// package question
// import (
// "context"
// "database/sql"
// "flag"
// "fmt"
// "time"
// _ "github.com/lib/pq"
// )
// var (
// connString = flag.String("dbconn", "", "database connection string")
// )
// type QA struct {
// ID int64 // 主键
// CreatedAt time.Time // 创建时间
......@@ -700,6 +275,10 @@ func derefString(p *string) interface{} {
// GetLatestQA(ctx context.Context, fromID *string) ([]QA, error)
// // WriteQA 插入或更新 qa 表记录
// WriteQA(ctx context.Context, qa QA) (int64, error)
// // WriteAndGetLatestQA 先查询最新记录,再写入 QA 记录,返回写入的 ID、第一条查询结果、是否查询到结果和错误
// WriteAndGetLatestQA(ctx context.Context, qa QA) (int64, *QA, bool, error)
// // UpdateQAFields 根据 idx 更新 qa 表中指定记录的 summary 和 answer 字段
// UpdateQAFields(ctx context.Context, idx int64, summary, answer string) error
// }
// // qaStore 是 QAStore 接口的实现
......@@ -713,9 +292,9 @@ func derefString(p *string) interface{} {
// }
// // 初始化数据库连接并返回 QAStore
// func InitQAStore() (QAStore, error) {
// func InitQAStore(connString string) (QAStore, error) {
// // Supabase 提供的连接字符串
// connString := "postgresql://postgres.awcfgdodiuqnlsobcivq:P99IU9NEoDRPsBfb@aws-0-ap-southeast-1.pooler.supabase.com:5432/postgres"
// //connString := "postgresql://postgres.awcfgdodiuqnlsobcivq:P99IU9NEoDRPsBfb@aws-0-ap-southeast-1.pooler.supabase.com:5432/postgres"
// // 打开数据库连接
// db, err := sql.Open("postgres", connString)
......@@ -834,6 +413,54 @@ func derefString(p *string) interface{} {
// return newID, nil
// }
// func (s *qaStore) WriteAndGetLatestQA(ctx context.Context, qa QA) (int64, *QA, bool, error) {
// // 先查询最新记录
// results, err := s.GetLatestQA(ctx, qa.FromID)
// if err != nil {
// return 0, nil, false, fmt.Errorf("get latest qa: %w", err)
// }
// // 检查查询结果是否为空
// var latestQA *QA
// hasResult := len(results) > 0
// if hasResult {
// latestQA = &results[0] // 取第一条记录
// } else {
// latestQA = nil // 空结果
// }
// // 写入记录
// id, err := s.WriteQA(ctx, qa)
// if err != nil {
// return 0, latestQA, hasResult, fmt.Errorf("write qa: %w", err)
// }
// // 返回写入的 ID、第一条查询结果和 hasResult
// return id, latestQA, hasResult, nil
// }
// // UpdateQAFields 根据 idx 更新 qa 表中指定记录的 summary 和 answer 字段
// func (s *qaStore) UpdateQAFields(ctx context.Context, idx int64, summary, answer string) error {
// query := `
// UPDATE qa
// SET summary = $1, answer = $2
// WHERE id = $3`
// result, err := s.db.ExecContext(ctx, query, summary, answer, idx)
// if err != nil {
// return fmt.Errorf("update qa fields: %w", err)
// }
// rowsAffected, err := result.RowsAffected()
// if err != nil {
// return fmt.Errorf("check rows affected: %w", err)
// }
// if rowsAffected == 0 {
// return fmt.Errorf("no record found with id %d", idx)
// }
// return nil
// }
// // 辅助函数:处理指针类型的空值
// func stringPtr(s string) *string {
// return &s
......
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