项目实训:vue + flask + RAG实现模拟面试

 效果展示

完整流程

语音上传逻辑

具体实现

1.上传面试相关信息,简历,公司,岗位,并上传简历

前端:

<template>
  <div class="chatHome">
    <div class="chatLeft">
      <div class="title">
        <h1>职跃助手</h1>
      </div>

      <el-form class="user-settings" ref="form" :model="form" label-width="80px" label-position="top">
        <el-form-item class="settings-unit">
          <span class="settings-text">选择岗位</span>
          <el-select class="my-selector" v-model="form.job" placeholder="请选择岗位">
            <el-option
                v-for="item in jobOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            />
          </el-select>
        </el-form-item>

        <el-form-item class="settings-unit">
          <span class="settings-text">选择公司</span>
          <el-select class="my-selector" v-model="form.company" placeholder="请选择公司">
            <el-option
                v-for="item in companyOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            />
          </el-select>
        </el-form-item>

        <el-form-item class="settings-unit">
          <span class="settings-text">选择面试类型</span>
          <el-select class="my-selector" v-model="form.interview" placeholder="请选择面试类型">
            <el-option
                v-for="item in interviewOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            />
          </el-select>
        </el-form-item>

        <el-form-item class="settings-unit">
          <div class="flex-container">
            <span class="settings-text">上传你的简历</span>
            <div class="my-selector">
              <input type="file" style="color: white" @change="onFileChange" />
            </div>
          </div>
        </el-form-item>
      </el-form>
      <el-button type="primary" style="margin-left: 90px; margin-top: 40px" @click="onSubmit">开始面试</el-button>


表单上传

onSubmit() {
      const formData = new FormData();
      // 添加文本字段
      for (let key in this.form) {
        formData.append(key, this.form[key]);
      }
      // 添加文件
      console.log(this.file)
      if (this.file) {
        formData.append('file', this.file);
      }
      // 使用axios或fetch发送POST请求
      // 假设你的Flask后端API地址是 '/upload'
      // delete formData.headers['Content-Type'];
      request.post('/upload_file', formData, {
        headers: {
          // 注意:当使用 FormData 时,不需要手动设置 Content-Type
          // axios 会自动处理
        },
      })
          .then(response => {
            if (response.code == 200){
              this.$message("上传成功~🥳");
              console.log(response.result)
              this.question = response.result
            }
          })
          .catch(error => {
            console.error(error);
            // 处理错误
          });
    },

后端接收相关信息。

# 侧边栏表单上传文件上传:包含工作+公司+简历
@app.route('/upload_file', methods=['POST'])
def upload_file():
    job = request.form.get('job')
    company = request.form.get('company')
    interview = request.form.get('interview')
    f = request.files.get('file')
    # 如果文件不存在
    if f is None or f.filename == '':
        return jsonify({'code': 400, 'message': 'No file part in the request'}), 400
    # 保存文件
    fname = secure_filename(f.filename)  # 使用secure_filename来避免安全问题
    file_path = fname  # 这不是一个完整的路径,只是一个文件名
    try:
        f.save(file_path)  # 使用f.save而不是手动打开和写入文件
    except Exception as e:
        return jsonify({'code': 500, 'message': f'Failed to save file: {str(e)}'}), 500
        # 项目经历
    text = pyMuPDF_fitz(file_path, './img_tmp')
    if interview == "技术面":
        prompt = f"这是我的简历{text},请提取出我的软件项目经历,字数不超过600字"
    else:
        prompt = f"这是我的简历{text},请提取出我的荣誉奖项,校园经历,个人评价,字数不超过600字"
    extracted = Turing2(prompt)
    question = f"你是{company}公司的面试官,我要面试{job}岗位,现在要进行{interview},这是我的简历相关信息{extracted},请你现在问5个面试问题,每个问题以问号结尾,确保每个问题一行"
    result = Turing(question)
    return jsonify({
        'code': 200,
        'result': result
    })

2.返回面试问题逻辑

1.接受前端的表单信息,并保存解析文件,因为文件可能不能直接读,这里采用ocr技术,提取简历中的信息,

2.识别出的简历信息传给大模型GLM,调用该接口,返回与该面试有关的信息,比如技术面返回项目经历,hr面返回冗余奖项,校园经历等(此处大模型制作信息提取)

# GLM3对话
def Turing2(text_words=""):
    # 准备请求体(JSON格式)
    payload = {
        "query": text_words,
        "conversation_id": "",  # 你可以根据需要设置此ID
        "history_len": -1,
        "history": [

        ],
        "stream": False,
        "model_name": "chatglm3-6b",
        "temperature": 0.7,
        "max_tokens": 0,  # 注意:max_tokens为0可能表示无限制,但具体取决于API的实现
        "prompt_name": "default"
    }

    # 发送POST请求,并设置Content-Type为application/json
    headers = {'Content-Type': 'application/json'}
    response = requests.post(url2, json=payload, headers=headers)

    # 检查响应状态码并打印响应内容
    if response.status_code == 200:
        print('请求成功')
        json_str = response.text.split(': ', 1)[1]  # 使用split分割字符串,只取第二个部分(索引为1)
        try:
            # 解析JSON字符串
            data = json.loads(json_str)
            # 提取text字段的值
            text = data['text']
            print('文本内容:', text)
            return text
        except (json.JSONDecodeError, KeyError) as e:
            print('解析JSON或访问字段时出错:', e)
    else:
        print(f'请求失败,状态码:{response.status_code}')

3.构建prompt

    question = f"你是{company}公司的面试官,我要面试{job}岗位,
现在要进行{interview},这是我的简历相关信息{extracted},
请你现在问5个面试问题,每个问题以问号结尾,确保每个问题一行"

4.返回面试问题。根据prompt检索知识库中相关的面试问题,公司信息,最后在交给GLM,返回最终面试问题。(此处为RAG技术)

# 与知识库对话
def Turing(text_words=""):
    # 准备请求体(JSON格式)
    payload = {
        "query": text_words,
        "knowledge_id": "tmpyr9658rr",
        "top_k": 3,
        "score_threshold": 0.6,
        "history": [

        ],
        "stream": False,
        "model_name": "chatglm3-6b",
        "temperature": 0.7,
        "max_tokens": 0,
        "prompt_name": "default"
    }
    # 发送POST请求,并设置Content-Type为application/json
    headers = {'Content-Type': 'application/json'}
    response = requests.post(url, json=payload, headers=headers)

    # 检查响应状态码并打印响应内容
    if response.status_code == 200:
        json_str = response.text.split(': ', 1)[1]  # 使用split分割字符串,只取第二个部分(索引为1)
        try:
            # 解析JSON字符串
            data = json.loads(json_str)
            # 提取text字段的值
            text = data['answer']
            result = text.split('\n')
            # 输出分割后的数组(列表)
            print(result)
            return result
        except (json.JSONDecodeError, KeyError) as e:
            print('解析JSON或访问字段时出错:', e)
    else:
        print(f'请求失败,状态码:{response.status_code}')

返回的结果

5.前端展示,面试官提问。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值