Skip to content

问答系统

基于文档的问答

基本实现

java
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.segmenter.CharacterTextSegmenter;
import dev.langchain4j.data.segmenter.TextSegment;
import dev.langchain4j.embedding.openai.OpenAiEmbeddingModel;
import dev.langchain4j.embedding.EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import dev.langchain4j.retriever.EmbeddingStoreRetriever;
import dev.langchain4j.chain.rag.RetrievalAugmentedGenerationChain;
import dev.langchain4j.model.openai.OpenAiChatModel;

public class DocumentQASystem {
    public static void main(String[] args) {
        // 1. 加载文档
        Document document = FileSystemDocumentLoader.builder()
                .path("path/to/document.txt")
                .build()
                .load();

        // 2. 分割文档
        CharacterTextSegmenter segmenter = CharacterTextSegmenter.builder()
                .maxSegmentSize(1000)
                .overlapSize(100)
                .build();
        List<TextSegment> segments = segmenter.segment(document);

        // 3. 创建嵌入模型
        EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .build();

        // 4. 创建嵌入存储并添加文档片段
        EmbeddingStore embeddingStore = new InMemoryEmbeddingStore();
        embeddingStore.addAll(segments, embeddingModel);

        // 5. 创建检索器
        EmbeddingStoreRetriever retriever = EmbeddingStoreRetriever.builder()
                .embeddingStore(embeddingStore)
                .embeddingModel(embeddingModel)
                .maxResults(3)
                .minScore(0.7)
                .build();

        // 6. 创建模型
        OpenAiChatModel model = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .build();

        // 7. 创建 RAG 链
        RetrievalAugmentedGenerationChain ragChain = RetrievalAugmentedGenerationChain.builder()
                .retriever(retriever)
                .model(model)
                .build();

        // 8. 执行问答
        String question = "文档中关于量子计算的内容是什么?";
        String answer = ragChain.run(question);
        System.out.println("问题: " + question);
        System.out.println("回答: " + answer);
    }
}

高级实现

java
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.DirectoryDocumentLoader;
import dev.langchain4j.data.segmenter.SentenceTextSegmenter;
import dev.langchain4j.data.segmenter.TextSegment;
import dev.langchain4j.embedding.openai.OpenAiEmbeddingModel;
import dev.langchain4j.embedding.EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.chroma.ChromaEmbeddingStore;
import dev.langchain4j.retriever.EmbeddingStoreRetriever;
import dev.langchain4j.chain.rag.RetrievalAugmentedGenerationChain;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.prompt.PromptTemplate;

public class AdvancedDocumentQASystem {
    public static void main(String[] args) {
        // 1. 加载多个文档
        DirectoryDocumentLoader loader = DirectoryDocumentLoader.builder()
                .directoryPath("path/to/documents")
                .supportedFileExtensions(".txt", ".md", ".pdf")
                .build();
        List<Document> documents = loader.load();

        // 2. 分割文档
        SentenceTextSegmenter segmenter = SentenceTextSegmenter.builder()
                .maxSegmentSize(1000)
                .overlapSize(100)
                .build();
        List<TextSegment> allSegments = new ArrayList<>();
        for (Document document : documents) {
            allSegments.addAll(segmenter.segment(document));
        }

        // 3. 创建嵌入模型
        EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .build();

        // 4. 创建 Chroma 嵌入存储并添加文档片段
        EmbeddingStore embeddingStore = ChromaEmbeddingStore.builder()
                .baseUrl("http://localhost:8000")
                .collectionName("documents")
                .build();
        embeddingStore.addAll(allSegments, embeddingModel);

        // 5. 创建检索器
        EmbeddingStoreRetriever retriever = EmbeddingStoreRetriever.builder()
                .embeddingStore(embeddingStore)
                .embeddingModel(embeddingModel)
                .maxResults(5)
                .minScore(0.7)
                .build();

        // 6. 创建模型
        OpenAiChatModel model = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .modelName("gpt-4") // 使用更强大的模型
                .build();

        // 7. 创建自定义提示词模板
        PromptTemplate promptTemplate = PromptTemplate.from(
                "你是一个专业的问答系统,根据以下信息回答问题。\n" +
                "请确保回答基于提供的信息,不要添加外部知识。\n" +
                "如果信息不足,请明确说明。\n\n" +
                "信息:\n{information}\n\n" +
                "问题:{question}\n\n" +
                "回答:"
        );

        // 8. 创建 RAG 链
        RetrievalAugmentedGenerationChain ragChain = RetrievalAugmentedGenerationChain.builder()
                .retriever(retriever)
                .model(model)
                .promptTemplate(promptTemplate)
                .build();

        // 9. 执行问答
        String question = "量子计算的基本原理是什么?";
        String answer = ragChain.run(question);
        System.out.println("问题: " + question);
        System.out.println("回答: " + answer);
    }
}

多文档问答

基本实现

java
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.DirectoryDocumentLoader;
import dev.langchain4j.data.segmenter.CharacterTextSegmenter;
import dev.langchain4j.data.segmenter.TextSegment;
import dev.langchain4j.embedding.openai.OpenAiEmbeddingModel;
import dev.langchain4j.embedding.EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import dev.langchain4j.retriever.EmbeddingStoreRetriever;
import dev.langchain4j.chain.rag.RetrievalAugmentedGenerationChain;
import dev.langchain4j.model.openai.OpenAiChatModel;

public class MultiDocumentQASystem {
    public static void main(String[] args) {
        // 1. 加载目录中的所有文档
        DirectoryDocumentLoader loader = DirectoryDocumentLoader.builder()
                .directoryPath("path/to/documents")
                .supportedFileExtensions(".txt", ".md")
                .build();
        List<Document> documents = loader.load();

        // 2. 分割所有文档
        CharacterTextSegmenter segmenter = CharacterTextSegmenter.builder()
                .maxSegmentSize(1000)
                .overlapSize(100)
                .build();
        List<TextSegment> allSegments = new ArrayList<>();
        for (Document document : documents) {
            allSegments.addAll(segmenter.segment(document));
        }

        // 3. 创建嵌入模型
        EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .build();

        // 4. 创建嵌入存储并添加所有文档片段
        EmbeddingStore embeddingStore = new InMemoryEmbeddingStore();
        embeddingStore.addAll(allSegments, embeddingModel);

        // 5. 创建检索器
        EmbeddingStoreRetriever retriever = EmbeddingStoreRetriever.builder()
                .embeddingStore(embeddingStore)
                .embeddingModel(embeddingModel)
                .maxResults(5)
                .minScore(0.7)
                .build();

        // 6. 创建模型
        OpenAiChatModel model = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .build();

        // 7. 创建 RAG 链
        RetrievalAugmentedGenerationChain ragChain = RetrievalAugmentedGenerationChain.builder()
                .retriever(retriever)
                .model(model)
                .build();

        // 8. 执行问答
        String question = "这些文档中关于人工智能的内容是什么?";
        String answer = ragChain.run(question);
        System.out.println("问题: " + question);
        System.out.println("回答: " + answer);
    }
}

带元数据过滤的多文档问答

java
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.Metadata;
import dev.langchain4j.data.document.loader.DirectoryDocumentLoader;
import dev.langchain4j.data.segmenter.CharacterTextSegmenter;
import dev.langchain4j.data.segmenter.TextSegment;
import dev.langchain4j.embedding.openai.OpenAiEmbeddingModel;
import dev.langchain4j.embedding.EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import dev.langchain4j.retriever.EmbeddingStoreRetriever;
import dev.langchain4j.chain.rag.RetrievalAugmentedGenerationChain;
import dev.langchain4j.model.openai.OpenAiChatModel;

public class FilteredDocumentQASystem {
    public static void main(String[] args) {
        // 1. 加载目录中的所有文档
        DirectoryDocumentLoader loader = DirectoryDocumentLoader.builder()
                .directoryPath("path/to/documents")
                .supportedFileExtensions(".txt", ".md")
                .build();
        List<Document> documents = loader.load();

        // 2. 为文档添加元数据
        List<Document> documentsWithMetadata = new ArrayList<>();
        for (Document document : documents) {
            Metadata metadata = document.metadata().copy();
            // 添加自定义元数据
            metadata.put("category", getDocumentCategory(document.content()));
            documentsWithMetadata.add(Document.from(document.content(), metadata));
        }

        // 3. 分割所有文档
        CharacterTextSegmenter segmenter = CharacterTextSegmenter.builder()
                .maxSegmentSize(1000)
                .overlapSize(100)
                .build();
        List<TextSegment> allSegments = new ArrayList<>();
        for (Document document : documentsWithMetadata) {
            allSegments.addAll(segmenter.segment(document));
        }

        // 4. 创建嵌入模型
        EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .build();

        // 5. 创建嵌入存储并添加所有文档片段
        EmbeddingStore embeddingStore = new InMemoryEmbeddingStore();
        embeddingStore.addAll(allSegments, embeddingModel);

        // 6. 创建带过滤的检索器
        EmbeddingStoreRetriever retriever = EmbeddingStoreRetriever.builder()
                .embeddingStore(embeddingStore)
                .embeddingModel(embeddingModel)
                .maxResults(5)
                .minScore(0.7)
                .build();

        // 7. 创建模型
        OpenAiChatModel model = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .build();

        // 8. 创建 RAG 链
        RetrievalAugmentedGenerationChain ragChain = RetrievalAugmentedGenerationChain.builder()
                .retriever(retriever)
                .model(model)
                .build();

        // 9. 执行问答
        String question = "关于技术领域的内容是什么?";
        String answer = ragChain.run(question);
        System.out.println("问题: " + question);
        System.out.println("回答: " + answer);
    }
    
    private static String getDocumentCategory(String content) {
        // 简单的分类逻辑
        if (content.contains("技术") || content.contains("编程") || content.contains("计算机")) {
            return "技术";
        } else if (content.contains("商业") || content.contains("市场") || content.contains("经济")) {
            return "商业";
        } else if (content.contains("科学") || content.contains("研究") || content.contains("实验")) {
            return "科学";
        } else {
            return "其他";
        }
    }
}

复杂问题处理

多步骤问答

java
import dev.langchain4j.chain.sequential.SequentialChain;
import dev.langchain4j.chain.llm.LLMChain;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.prompt.PromptTemplate;

public class MultiStepQASystem {
    public static void main(String[] args) {
        // 创建模型
        OpenAiChatModel model = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .build();

        // 创建第一步链:分析问题
        PromptTemplate analysisTemplate = PromptTemplate.from(
                "分析以下问题,确定需要哪些信息来回答:\n{question}\n\n需要的信息:"
        );
        LLMChain analysisChain = LLMChain.builder()
                .promptTemplate(analysisTemplate)
                .model(model)
                .build();

        // 创建第二步链:检索信息
        PromptTemplate retrievalTemplate = PromptTemplate.from(
                "根据需要的信息,从知识库中检索相关内容:\n{required_info}\n\n检索到的信息:"
        );
        LLMChain retrievalChain = LLMChain.builder()
                .promptTemplate(retrievalTemplate)
                .model(model)
                .build();

        // 创建第三步链:生成答案
        PromptTemplate answerTemplate = PromptTemplate.from(
                "根据检索到的信息,回答原始问题:\n\n问题:{question}\n\n检索到的信息:{retrieved_info}\n\n回答:"
        );
        LLMChain answerChain = LLMChain.builder()
                .promptTemplate(answerTemplate)
                .model(model)
                .build();

        // 创建顺序链
        SequentialChain sequentialChain = SequentialChain.builder()
                .addChain(analysisChain, "question", "required_info")
                .addChain(retrievalChain, "required_info", "retrieved_info")
                .addChain(answerChain, "question,retrieved_info", "answer")
                .build();

        // 执行多步骤问答
        String question = "量子计算如何改变密码学?";
        Map<String, Object> inputs = new HashMap<>();
        inputs.put("question", question);

        Map<String, Object> results = sequentialChain.runForMap(inputs);
        System.out.println("问题: " + question);
        System.out.println("分析需要的信息: " + results.get("required_info"));
        System.out.println("检索到的信息: " + results.get("retrieved_info"));
        System.out.println("回答: " + results.get("answer"));
    }
}

带推理的问答

java
import dev.langchain4j.chain.llm.LLMChain;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.prompt.PromptTemplate;

public class ReasoningQASystem {
    public static void main(String[] args) {
        // 创建模型
        OpenAiChatModel model = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .modelName("gpt-4") // 使用更强大的模型进行推理
                .build();

        // 创建带推理的提示词模板
        PromptTemplate reasoningTemplate = PromptTemplate.from(
                "请逐步思考并回答以下问题:\n{question}\n\n思考过程:\n1. ")
                .build();

        // 创建链
        LLMChain chain = LLMChain.builder()
                .promptTemplate(reasoningTemplate)
                .model(model)
                .build();

        // 执行问答
        String question = "如果一个篮子里有 5 个苹果,你拿走了 3 个,然后又放回去 2 个,现在篮子里有几个苹果?";
        String response = chain.run(question);
        System.out.println("问题: " + question);
        System.out.println("回答: " + response);
    }
}

最佳实践

  1. 文档处理

    • 选择合适的文档加载器
    • 优化文本分割策略
    • 添加有意义的元数据
  2. 嵌入与检索

    • 选择合适的嵌入模型
    • 配置适当的检索参数
    • 考虑使用专业的向量数据库
  3. 提示词优化

    • 设计清晰的提示词模板
    • 明确任务要求
    • 提供足够的上下文
  4. 模型选择

    • 根据任务复杂度选择模型
    • 平衡性能和成本
    • 考虑使用更强大的模型处理复杂问题
  5. 系统设计

    • 模块化设计
    • 错误处理
    • 性能优化
  6. 评估与改进

    • 定期评估系统性能
    • 收集用户反馈
    • 持续优化系统