Query查询练习,使用map vector

本文介绍了一种高效的数据检索与统计方法,通过构建文本查询类,实现对输入文件中特定单词的快速查找及统计。该方法不仅能够读取文件并将其内容按行存储,还支持根据单词查询其所在行,并能统计文件中各单词的出现频率。通过实例代码展示整个流程,旨在提升数据处理效率。
/*************************************************************************
    > File Name: Query.h
    > Author:keson
    > Mail:keson@bupt.edu.cn
    > Created Time: 2014年11月05日 星期三 16时46分18秒
 ************************************************************************/

#ifndef _QUERY_H
#define _QUERY_H
#include<fstream>
#include<vector>
#include<string>
#include<sstream>
#include<map>
#include<set>
using namespace std;
class TextQuery
{
    public:
    TextQuery(std::ifstream &);            //构造函数
    
    TextQuery read(ifstream &file,TextQuery &item);  //读输入文件
    void print();    //打印读入的文件
    void account(ifstream &file);   //根据输入流将key值和value统计输入map
    void query(string &s);          //根据单词s打印出所在行
    void map_print();               //打印map的key值
    private:
    vector<string> vec;             //用来保存输入的每一行
    map<string,set<int>> word_map;  //每个单词作为key,行号的set集作为value

};
void TextQuery::map_print()         //打印出现的单词
{
    auto ret=word_map.begin();
    while(ret!=word_map.cend())
    {
        cout<<ret->first<<" ";
        ++ret;
    }
}
void TextQuery::query(string &s)         //根据输入的单词s,打印出所在行
{
    auto ret=word_map.find(s);
    if(ret!=word_map.cend())
    {
        auto set_it=(ret->second).cbegin();
        while(set_it!=(ret->second).cend())
        {
            cout<<*set_it<<"   "<<vec[*set_it-1]<<endl;
            ++set_it;
        }
    }
    else
    cout<<"could't find";
}
void TextQuery::account(ifstream &file)
{
    string fline,word;
    int line_num=0;
    while(getline(file,fline))
    {
        ++line_num;
        istringstream record(fline);   //将一行绑定到record流,分解成单词
        while(record>>word)
        {
            auto ret=word_map.find(word);
            if (ret!=word_map.cend())          //若该单词已经在map的key值出现,则插入行号
            {
             ret->second.insert(line_num);
            }
            else                               //若未出现,则插入key和对应的value
            {
             set<int> val={line_num};
             word_map.insert(make_pair(word,val));
            }   
        }
        
    }
}
void TextQuery::print()         //打印出vec中的内容
{
    for(auto c:vec)
        cout<<c<<endl;
}

TextQuery TextQuery::read(std::ifstream &file,TextQuery &item)
{

    string line;
    if(file)   //如果打开成功,读入每一行
    {
        while(getline(file,line))
        {
            (item.vec).push_back(line);
        }

    }
    else
      cerr<<"could't open";
    
    file.close();

    return item;
}

TextQuery::TextQuery(std::ifstream &file)
{
    read(file,*this);   //read读入初始化vec
    map<string,set<int>> word_map;

}
#endif




/*************************************************************************
    > File Name: Query.cpp
    > Author:keson
    > Mail:keson@bupt.edu.cn
    > Created Time: 2014年11月05日 星期三 16时38分07秒
 ************************************************************************/

#include<iostream>
#include<fstream>
#include"Query.h"
using namespace std;

int main()
{
    ifstream file("storyDataFile");
    TextQuery item(file);
    item.print();
    file.close();                     //关闭file流
    ifstream file2("storyDataFile");  //重新打开那个文件
    item.account(file2);
    cout<<"Enter the word you want to find "<<endl;
    string s;
    cin>>s;
    item.query(s);
   // item.map_print();
    return 0;
    
}
/*
void runQueries(ifstream &infile);


void runQueries(ifstream &infile)
{
    //infile是一个ifstream,指向我们要处理的文件
    Text tq(infile);  //保存建立并打印结果

    while(true)
    {
        cout<<"enter word to look for,or q to quit: ";
        string s;
    
        if(!(cin>>s)||s=="q") break;
        
        print(cout,tq.query(s))<<endl;
    }

}
*/


自行准备本地知识库资料(如本专业相关资料内容)作为大模型本地知识库的输入 教师侧:备课与设计: 根据所提供的本地课程大纲、课程知识库文档等自动设计教学内容,包括知识讲解、实训练习与指导、时间分布等。 · 考核内容生成: 根据教学内容自动生成考核题目及参考答案,考核题目种类可多样化,根据学科设计,如计算机类可设计相关编程题和答案 · 学情数据分析: 对学生提交的答案进行自动化检测,提供错误定位与修正建议。对学生整体数据进行分析,总结知识掌握情况与教学建议。 学生侧: · 在线学习助手: 对学生的提出的问题,结合教学内容进行解答; · 实时练习评测助手: 根据学生历史练习情况,以及学生的练习要求,生成随练题目,并对练习纠错。 管理侧: 用户管理:管理员/教师/学生等用户的基本管理 课件资源管理:按学科列表教师备课产生的课件、练习等资源,可以导出。 大屏概览: · 教师使用次数统计/活跃板块(当日/本周) · 学生使用次数统计/活跃板块(当日/本周) · 教学效率指数(备课与修正耗时、课后练习设计与修正耗时、课程优化方向(如:某学科通过率持续偏低) · 学生学习效果(平均正确率趋势、知识点掌握情况,高频错误知识点等) 非功能性需求 需明确使用至少1个开源大模型作为核心技术组件; 需采用本地知识库作为输入,知识库资料总量不大于100M; 生成的内容、练习与答案与本地知识库的关联性和准确性;(对抽取知识点设计的题目验证关联性和与答案的准确性有知识点说明) 告诉我教师端的后端部分该怎么做,使用spring boot3.5.3,大模型使用通义,要使用到redis和milvus,请给出一个完整的的项目,即使代码量巨大,你可以分步给出
最新发布
07-10
<think>我们正在构建一个教师端的后端系统,使用Spring Boot 3.5.3,集成通义大模型(这我们假设使用通义的API,因为通义大模型通常通过API调用),同时使用Redis和Milvus。 系统功能包括: 1. 备课与设计:根据课程大纲和知识库文档,调用大模型生成教学内容(包括知识讲解、实训练习、时间分布等)。 2. 考核内容生成:根据教学内容生成考核题目及参考答案。 3. 学情数据分析:分析学生提交的答案,提供错误定位与修正建议;分析整体学情数据。 技术栈: - Spring Boot 3.5.3 - Redis:用于缓存,例如缓存大模型生成的结果,提高响应速度 - Milvus:用于向量存储和相似度搜索,例如存储知识库的向量,便于在生成教学内容时检索相关知识 项目结构规划: - 控制器层(Controller):处理HTTP请求 - 服务层(Service):业务逻辑 - 数据访问层(Repository):操作数据库(如果需要的话,这我们可能还需要一个关系型数据库,比如MySQL,用于存储用户信息、课件资源等。但题目要求中管理侧还有用户管理、课件资源管理等,因此需要关系型数据库。但是题目要求使用Redis和Milvus,所以这我们主要关注这两个,关系型数据库可以自行补充,但为了简化,我们只关注核心功能,使用Redis和Milvus) 由于代码量巨大,我们分步骤实现核心功能模块: 步骤1:创建Spring Boot项目,添加依赖 步骤2:配置Redis和Milvus 步骤3:实现知识库的向量化存储(Milvus) 步骤4:调用通义大模型API(这使用模拟,因为实际API需要密钥) 步骤5:实现备课与设计功能 步骤6:实现考核内容生成 步骤7:实现学情数据分析 注意:由于通义大模型需要API key,我们这使用模拟的方式,重点在于整合流程。 下面开始逐步实现: 步骤1:创建Spring Boot项目,添加依赖 使用Spring Initializr创建项目,选择以下依赖: - Spring Web - Spring Data Redis - Lombok 另外,需要手动添加Milvus的Java SDK依赖。目前Milvus的Java SDK可以在Maven中央仓库找到,我们添加: - milvus-sdk-java: 2.3.0 (注意:版本可能更新,这以2.3.0为例) 同时,为了调用通义API,我们需要一个HTTP客户端,比如使用Spring的RestTemplate或者WebClient。 在pom.xml中添加: ```xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- Milvus Java SDK --> <dependency> <groupId>io.milvus</groupId> <artifactId>milvus-sdk-java</artifactId> <version>2.3.0</version> </dependency> <!-- 用于JSON处理 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- 用于模拟通义API调用,实际可能需要其他依赖,根据通义API的请求方式调整 --> </dependencies> ``` 步骤2:配置Redis和Milvus 在application.yml中配置: ```yaml spring: redis: host: localhost port: 6379 password: database: 0 milvus: host: localhost port: 19530 ``` 创建配置类读取Milvus配置: ```java @Configuration public class MilvusConfig { @Value("${milvus.host}") private String host; @Value("${milvus.port}") private int port; @Bean public MilvusServiceClient milvusServiceClient() { return new MilvusServiceClient(ConnectParam.newBuilder().withHost(host).withPort(port).build()); } } ``` 步骤3:知识库的向量化存储(Milvus) 首先,我们需要将本地的知识库文档(如txt、pdf等)进行向量化。这我们使用一个文本嵌入模型(embedding model)将文本转换为向量。由于通义大模型提供了文本嵌入的API,我们可以调用它。但为了简化,我们假设已经有一个嵌入服务(可以自己用一个本地模型,比如SentenceTransformer,但这我们重点在流程,所以用随机向量代替)。 注意:实际中,我们需要一个嵌入模型,这我们模拟一个嵌入服务。 创建知识库向量存储的步骤: - 读取知识库文档,分块(因为Milvus对向量搜索有长度限制) -每个分块调用嵌入服务得到向量 - 将向量和元数据(如文档ID、分块索引等)存入Milvus 由于这个步骤通常是一次性的,我们可以写一个初始化服务。 步骤4:调用通义大模型API 我们创建一个服务类,用于调用通义大模型API。这以通义千问为例(假设我们使用通义千问的API),实际API调用需要替换URL和API Key。 ```java @Service public class TongYiService { private static final String TONGYI_API_URL = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"; private static final String API_KEY = "your-api-key"; // 替换为你的API Key private final RestTemplate restTemplate; public TongYiService(RestTemplateBuilder restTemplateBuilder) { this.restTemplate = restTemplateBuilder.build(); } public String generateText(String prompt) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.set("Authorization", "Bearer " + API_KEY); Map<String, Object> requestBody = new HashMap<>(); requestBody.put("model", "qwen-turbo"); // 使用通义千问的turbo模型 Map<String, String> input = new HashMap<>(); input.put("prompt", prompt); requestBody.put("input", input); requestBody.put("parameters", Collections.singletonMap("temperature", 0.7)); HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers); ResponseEntity<Map> response = restTemplate.postForEntity(TONGYI_API_URL, request, Map.class); // 解析响应,这根据实际响应结构来 if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) { // 实际响应结构需要参考通义API文档,这假设返回中有output字段,output中有text Map<String, Object> body = response.getBody(); if (body.containsKey("output")) { Map<String, Object> output = (Map<String, Object>) body.get("output"); if (output.containsKey("text")) { return (String) output.get("text"); } } } return null; } } ``` 步骤5:实现备课与设计功能 备课与设计功能流程: 1. 教师输入课程大纲或选择知识库文档。 2. 系统根据输入的关键词或描述,在Milvus中检索相关的知识片段(向量相似度搜索)。 3. 将检索到的知识片段作为上下文,调用通义大模型生成教学内容(包括知识讲解、实训练习、时间分布等)。 首先,我们需要一个服务来执行向量搜索: ```java @Service @RequiredArgsConstructor public class VectorSearchService { private final MilvusServiceClient milvusClient; public List<String> searchSimilarTexts(String query, int topK) { // 将查询文本向量化,这需要调用嵌入服务,我们假设有一个嵌入服务 // 这为了简化,我们使用随机向量,实际中应该调用嵌入模型 List<Float> queryVector = getEmbedding(query); // 假设这个方法可以返回向量 // 构建搜索参数 List<String> outputFields = Collections.singletonList("text"); // 我们存储的字段中有一个是文本 SearchParam searchParam = SearchParam.newBuilder() .withCollectionName("knowledge_base") .withTopK(topK) .withMetricType(MetricType.IP) // 内积,也可以用L2 .withVectorFieldName("vector") // 向量字段名 .withVectors(Collections.singletonList(queryVector)) .withParams("{\"nprobe\":10}") // 搜索参数 .withOutputFields(outputFields) .build(); SearchResultsWrapper searchResults = milvusClient.search(searchParam); // 解析结果 List<SearchResultsWrapper.IDScore> scores = searchResults.getIDScore(0); List<String> texts = new ArrayList<>(); for (SearchResultsWrapper.IDScore score : scores) { Map<String, Object> entity = score.getEntity(); texts.add((String) entity.get("text")); } return texts; } private List<Float> getEmbedding(String text) { // 这模拟嵌入服务,返回一个随机向量(实际中应调用嵌入模型) // 假设向量维度为768 List<Float> vector = new ArrayList<>(768); Random random = new Random(); for (int i = 0; i < 768; i++) { vector.add(random.nextFloat()); } return vector; } } ``` 然后,备课服务: ```java @Service @RequiredArgsConstructor public class LessonPreparationService { private final VectorSearchService vectorSearchService; private final TongYiService tongYiService; private final RedisTemplate<String, String> redisTemplate; public String generateTeachingContent(String courseOutline) { // 先尝试从缓存中获取 String cacheKey = "teaching_content:" + courseOutline.hashCode(); String cachedContent = redisTemplate.opsForValue().get(cacheKey); if (cachedContent != null) { return cachedContent; } // 从Milvus中检索相关文本 List<String> relatedTexts = vectorSearchService.searchSimilarTexts(courseOutline, 5); String context = String.join("\n", relatedTexts); // 构建大模型的提示 String prompt = "你是一个教师,请根据以下课程大纲和相关知识库内容,设计教学内容,包括知识讲解、实训练习与指导、时间分布。\n" + "课程大纲:\n" + courseOutline + "\n" + "相关知识库内容:\n" + context; // 调用通义大模型 String content = tongYiService.generateText(prompt); // 存入缓存 redisTemplate.opsForValue().set(cacheKey, content, 1, TimeUnit.HOURS); // 缓存1小时 return content; } } ``` 步骤6:实现考核内容生成 类似地,我们可以设计一个生成考核题目的服务: ```java @Service @RequiredArgsConstructor public class ExamGenerationService { private final VectorSearchService vectorSearchService; private final TongYiService tongYiService; private final RedisTemplate<String, String> redisTemplate; public String generateExamQuestions(String teachingContent) { String cacheKey = "exam_questions:" + teachingContent.hashCode(); String cachedQuestions = redisTemplate.opsForValue().get(cacheKey); if (cachedQuestions != null) { return cachedQuestions; } // 同样可以检索相关文本,但这我们直接使用teachingContent作为上下文 String prompt = "你是一个教师,请根据以下教学内容,生成考核题目及参考答案。题目类型可以多样化,如选择题、填空题、编程题等。\n" + "教学内容:\n" + teachingContent; String questions = tongYiService.generateText(prompt); redisTemplate.opsForValue().set(cacheKey, questions, 1, TimeUnit.HOURS); return questions; } } ``` 步骤7:实现学情数据分析 学情数据分析包括两个部分: a. 单个学生答案的分析:调用大模型分析学生答案的错误,并给出建议。 b. 整体学情分析:收集多个学生的答题情况,分析知识点掌握情况。 这我们先实现单个学生答案分析: ```java @Service @RequiredArgsConstructor public class AnswerAnalysisService { private final TongYiService tongYiService; public String analyzeStudentAnswer(String question, String studentAnswer) { String prompt = "你是一个教师,请分析以下学生的答案,指出错误并给出修正建议。\n" + "题目:" + question + "\n" + "学生答案:" + studentAnswer; return tongYiService.generateText(prompt); } } ``` 整体学情分析需要存储学生的答题数据,然后进行统计。这我们可以设计一个简单的数据存储(比如MySQL表),然后分析每个知识点的正确率。由于涉及数据库设计,这不展开,但可以提供一个分析服务的框架: ```java @Service public class OverallAnalysisService { public String getOverallAnalysis(List<StudentAnswer> answers) { // 按知识点分组,计算正确率 // 这假设StudentAnswer中有知识点字段和是否正确字段 Map<String, List<StudentAnswer>> answersByKnowledgePoint = answers.stream() .collect(Collectors.groupingBy(StudentAnswer::getKnowledgePoint)); Map<String, Double> correctRateByKnowledgePoint = new HashMap<>(); for (Map.Entry<String, List<StudentAnswer>> entry : answersByKnowledgePoint.entrySet()) { long correctCount = entry.getValue().stream().filter(StudentAnswer::isCorrect).count(); double rate = (double) correctCount / entry.getValue().size(); correctRateByKnowledgePoint.put(entry.getKey(), rate); } // 生成分析报告 StringBuilder report = new StringBuilder(); report.append("知识点掌握情况分析:\n"); correctRateByKnowledgePoint.forEach((point, rate) -> { report.append(String.format("- %s: %.2f%%\n", point, rate * 100)); }); // 找出高频错误知识点 List<Map.Entry<String, Double>> lowRateList = correctRateByKnowledgePoint.entrySet().stream() .sorted(Map.Entry.comparingByValue()) .limit(3) // 取正确率最低的三个 .collect(Collectors.toList()); report.append("\n需要重点讲解的知识点(正确率最低的三个):\n"); lowRateList.forEach(entry -> { report.append(String.format("- %s: %.2f%%\n", entry.getKey(), entry.getValue() * 100)); }); return report.toString(); } } ``` 以上是核心功能的实现。由于项目非常庞大,我们只展示了关键部分。实际开发中,还需要考虑: - 异常处理 - 日志 - 事务管理 - 安全性 - 数据库设计(对于用户管理、课件资源管理、学生答题记录等) 最后,我们提供一些REST API接口供前端调用: ```java @RestController @RequestMapping("/api/teacher") @RequiredArgsConstructor public class TeacherController { private final LessonPreparationService lessonPreparationService; private final ExamGenerationService examGenerationService; private final AnswerAnalysisService answerAnalysisService; @PostMapping("/prepare-lesson") public ResponseEntity<String> prepareLesson(@RequestBody String courseOutline) { String content = lessonPreparationService.generateTeachingContent(courseOutline); return ResponseEntity.ok(content); } @PostMapping("/generate-exam") public ResponseEntity<String> generateExam(@RequestBody String teachingContent) { String questions = examGenerationService.generateExamQuestions(teachingContent); return ResponseEntity.ok(questions); } @PostMapping("/analyze-answer") public ResponseEntity<String> analyzeAnswer(@RequestBody AnswerAnalysisRequest request) { String analysis = answerAnalysisService.analyzeStudentAnswer(request.getQuestion(), request.getStudentAnswer()); return ResponseEntity.ok(analysis); } } ``` 注意:AnswerAnalysisRequest是一个简单的DTO: ```java @Data public class AnswerAnalysisRequest { private String question; private String studentAnswer; } ``` 由于代码量巨大,以上只展示了核心流程。在实际项目中,还需要完善细节,如错误处理、输入验证等。 最后,根据要求,在最后提出相关问题: §§相关问题§§: 1. 如何优化向量搜索的准确性和效率? 2. 如何处理大模型生成内容的缓存更新策略? 3. 如何设计数据库模型来存储学生答题记录以支持学情分析? 4. 如何确保调用通义大模型API的安全性(如API密钥的管理)?</think>下面我将为您设计一个基于Spring Boot 3.5.3的教师端后端系统,集成通义大模型、Redis和Milvus。由于代码量巨大,我将分模块展示核心实现。 ### 整体架构 ``` src ├── main │ ├── java/com/teacherplatform │ │ ├── config │ │ ├── controller │ │ ├── service │ │ │ ├── impl │ │ ├── repository │ │ ├── model │ │ ├── ai │ │ ├── task │ │ └── TeacherPlatformApplication.java │ └── resources └── test ``` ### 1. 依赖配置 (pom.xml) ```xml <dependencies> <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>3.5.3</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- Milvus --> <dependency> <groupId>io.milvus</groupId> <artifactId>milvus-sdk-java</artifactId> <version>2.3.0</version> </dependency> <!-- 通义API --> <dependency> <groupId>com.aliyun</groupId> <artifactId>alibabacloud-dashscope</artifactId> <version>2.4.0</version> </dependency> <!-- 其他工具 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> </dependencies> ``` ### 2. 配置文件 (application.yml) ```yaml spring: redis: host: localhost port: 6379 password: database: 0 milvus: host: localhost port: 19530 collection: knowledge_vectors tongyi: api-key: your_tongyi_api_key model: qwen-max embedding-endpoint: https://dashscope.aliyuncs.com/api/v1/embeddings ``` ### 3. Milvus 向量存储服务 ```java @Service public class MilvusService { private final MilvusServiceClient milvusClient; public MilvusService(@Value("${milvus.host}") String host, @Value("${milvus.port}") int port) { this.milvusClient = new MilvusServiceClient( ConnectParam.newBuilder().withHost(host).withPort(port).build() ); } public void storeKnowledgeVector(String docId, List<Float> vector) { List<InsertParam.Field> fields = new ArrayList<>(); fields.add(new InsertParam.Field("doc_id", DataType.VarChar, Collections.singletonList(docId))); fields.add(new InsertParam.Field("vector", DataType.FloatVector, Collections.singletonList(vector))); InsertParam insertParam = InsertParam.newBuilder() .withCollectionName("knowledge_vectors") .withFields(fields) .build(); milvusClient.insert(insertParam); } public List<String> searchSimilarKnowledge(List<Float> queryVector, int topK) { SearchParam searchParam = SearchParam.newBuilder() .withCollectionName("knowledge_vectors") .withMetricType(MetricType.COSINE) .withTopK(topK) .withVectors(Collections.singletonList(queryVector)) .withVectorFieldName("vector") .addOutputField("doc_id") .build(); SearchResultsWrapper results = milvusClient.search(searchParam); return results.getIDScore(0).stream() .map(score -> (String) score.get("doc_id")) .collect(Collectors.toList()); } } ``` ### 4. 通义大模型集成服务 ```java @Service public class TongyiAIService { private final String apiKey; private final String model; private final Rest
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值