
简介基于Python的智能面试系统源码面向计算机相关专业学生、研究人员及开发者核心解决招聘流程中候选人回答难以标准化评估的问题。系统运用自然语言处理与机器学习算法对面试回答进行智能分析辅助面试官快速判断候选人能力。压缩包体积为三百四十四KB共十三个文件包含四个Python核心代码文件、一个csv标注数据集、一个用于容器部署的Dockerfile及依赖配置文件、两张界面预览图另附项目说明文档与README。系统采用模块化设计注释完整目录清晰便于快速定位和二次开发。已有九十人学习。通过该项目可获得完整可运行源码、带标注的面试问答数据集以及涵盖设计理念、功能模块、使用方法和扩展建议的详细说明适合作为毕业设计或课程设计参考。实践过程中可深入理解自然语言处理与机器学习在智能面试评估中的落地方式掌握文本特征提取、模型训练与结果分析等关键技能提升编程和项目实战能力。1. 智能面试系统到底拆出了什么一个能跑的 Streamlit LLM 面试评估项目拿到这份基于 Python 的智能面试系统源码包第一反应是查文件清单。解压之后发现东西比想象中克制两个核心 Python 文件、一份配置、一个 CSV 数据集、一个 Dockerfile 和一份 fly.toml没有堆砌无关模块。interview_streamlit.py 是主程序oai_client.py 负责和大模型对话utils.py 做数据预处理data/inputs.csv 是标注好的问答数据。这套结构意味着它不是一个 PPT 式的毕业设计壳子而是一个能本地跑通、能部署、能换数据继续训练的最小可用系统。对正在做课程设计的学生、想入门 NLP 落地项目的开发者来说这个包的价值在于你能在一晚上之内把「面试官提问 → 候选人回答 → 模型评估 → 结果展示」这条链路完整跑起来然后基于它改成自己的东西。2. 架构与核心文件三个 Python 文件如何分工协作2.1 interview_streamlit.py界面层与业务流程编排这个文件是整个系统的门面。Streamlit 的写法让 UI 和业务逻辑混在一个文件里初次看会觉得乱但实际跑起来反而好改——所有状态都在 session_state 里流转不需要额外的前后端分离。主流程我拆成四步加载题库、生成面试问题、接收候选人回答、调用评估逻辑并展示结果。其中生成问题和评估都走 oai_client.py不直接裸调 API这个封装是合理的后续换模型或者加缓存都方便。# interview_streamlit.py 核心骨架简化自源码 import streamlit as st from oai_client import generate_question, evaluate_answer from utils import load_questions, normalize_text st.set_page_config(page_titleAI 面试官, layoutwide) questions load_questions(data/inputs.csv) if history not in st.session_state: st.session_state.history [] # 每次从题库随机抽一题走大模型生成追问 question generate_question(questions.sample(1).iloc[0][question]) answer st.text_area(候选人回答, height150) if st.button(提交评估) and answer.strip(): score, comment evaluate_answer(question, answer) st.session_state.history.append((question, answer, score, comment)) st.metric(综合评分, f{score}/10) st.write(comment)这段逻辑说明几点generate_question接收的是从 CSV 里抽样出来的一道题返回的是大模型基于原题生成的追问evaluate_answer返回一个分数和一段评语直接展示在页面上。实际使用时你会发现 session_state 里只存了 history没有做持久化意味着刷新页面数据就没了这是源码的一个简化取舍。2.2 oai_client.py大模型调用的统一入口oai_client.py 是本项目的核心。它把 OpenAI 接口封装成两个业务函数一个用于生成面试问题一个用于评估回答。这种按业务语义封装的做法比直接写一堆openai.ChatCompletion.create散落在各处要好维护得多。# oai_client.py 简化结构 import openai from settings import OPENAI_API_KEY, MODEL_NAME, TEMPERATURE openai.api_key OPENAI_API_KEY def generate_question(base_question: str) - str: prompt f你是一名技术面试官请基于以下问题生成一个追问\n{base_question} resp openai.ChatCompletion.create( modelMODEL_NAME, messages[{role: user, content: prompt}], temperatureTEMPERATURE, max_tokens256 ) return resp.choices[0].message.content.strip()注意这里的temperature和max_tokens都从 settings.py 读取而不是硬编码。我一般会建议把max_tokens调大一点因为面试追问往往需要模型输出一两段完整的话256 个 token 在中文场景下可能被截断。另外新版 openai SDK 把ChatCompletion.create改成了client.chat.completions.create如果跑源码报错大概率是这个版本兼容问题。2.3 inputs.csv面试数据的标注格式与作用打开 data/inputs.csv你会发现它的结构非常朴素至少包含 question、category、difficulty、reference_answer 四列。这里的关键点是 reference_answer——模型评估候选人回答时会拿它做参照。没有这列评估就失去了锚点。question,category,difficulty,reference_answer 说说Python的GIL锁,Python,2,GIL是Global Interpreter Lock... 解释一下HTTP和HTTPS的区别,网络,1,HTTPS在HTTP基础上加了TLS... 设计一个秒杀系统的架构,系统设计,3,前端限流后端缓存异步队列...数据量不需要大一两百条就够课程设计和 demo 演示。这列数据对评估质量的影响远大于模型参数微调我后面会专门讲怎么扩充它。源码的数据是已经分词和清洗过的中文问答记录可以直接喂给流程跑通。2.4 settings.py 与 requirements.txt配置和依赖的边界settings.py 里集中管理 API Key、模型名、温度参数、最大 token 数。这是个小项目该有的分寸感——不引入 pydantic-settings 这类重型工具一个纯 Python 配置模块就够了。# settings.py 简化结构 import os OPENAI_API_KEY os.getenv(OPENAI_API_KEY, ) MODEL_NAME os.getenv(MODEL_NAME, gpt-3.5-turbo) TEMPERATURE float(os.getenv(TEMPERATURE, 0.7)) MAX_TOKENS int(os.getenv(MAX_TOKENS, 512))requirements.txt 锁定的是 streamlit、openai、pandas 这几个核心依赖。这里要提醒一句openai 的版本跨度很大0.x 和 1.x 的调用方式完全不同源码如果写的是旧版调用装最新版 openai 包会直接报错。建议按照 requirements.txt 里锁定的版本安装不要图新。3. 本地跑通全流程从环境准备到第一次面试评估3.1 创建虚拟环境并安装依赖拿到源码第一步不是看代码而是先建虚拟环境。Python 版本建议 3.9 或 3.10太新的版本某些依赖可能还没有对应 wheel。我用的是 venv不用 conda因为 conda 在部分 Linux 服务器上会跟系统 Python 产生路径纠缠。# 解压源码包 unzip intelligent_interview_system.zip cd intelligent_interview_system # 创建并激活虚拟环境 python3.9 -m venv venv source venv/bin/activate # Windows 上执行 venv\Scripts\activate # 安装依赖 pip install -r requirements.txt # 验证关键依赖版本 pip show streamlit openai pandas | grep -E Name|Version这里有个实际经验如果 pip 安装 streamlit 特别慢优先换国内镜像源而不是傻等。执行pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple之后重新安装速度能快一个数量级。装完依赖后不要急着启动先确认版本和源码预期一致——很多翻车都发生在 openai 版本不匹配上。3.2 配置环境变量与 API Keyoai_client.py 读取 settings.py 里的OPENAI_API_KEY而它来自环境变量。注意源码里不会把真实的 Key 写进文件这是底线。修改.env文件或者直接在终端 export 都行。# 方式一写入 .env 文件 echo OPENAI_API_KEYsk-xxxx .env echo MODEL_NAMEgpt-3.5-turbo .env echo TEMPERATURE0.7 .env # 方式二直接在命令行注入临时生效 export OPENAI_API_KEYsk-xxxx要说明的是gpt-3.5-turbo是当前性价比最高的模型选择。如果用的是新模型比如 gpt-4o-mini需要同步修改 MODEL_NAME。这个参数的坑在于不同模型的定价和响应速度差异巨大对面试评估这种多次调用的场景gpt-4 的成本很快会上去。3.3 启动 Streamlit 并跑通第一轮面试环境配好之后启动应用Streamlit 默认监听 8501 端口浏览器访问http://localhost:8501就能看到面试界面。streamlit run interview_streamlit.py --server.port 8501跑起来之后界面上应该能看到「AI 面试官」的标题区域、一道面试题、一个文本输入框和一个评分按钮。输入一段回答点击提交系统会在几秒内返回分数和评语。这里我要多说一句首次运行大概率会遇到响应慢或者超时。原因是代码里没有配置超时重试大模型接口偶发抖动时会直接抛异常。如果你看到openai.error.Timeout之类的报错并且在代码里加了while循环重试那说明你已经踩进了第一个坑。这是后话下一章细讲。4. 评估逻辑拆解oai_client.py 怎么把回答变成分数4.1 评估 prompt 的结构化设计evaluate_answer是整份源码里含金量最高的函数。它设计了一套结构化 prompt先给模型设定面试官身份再贴出面试题和参考回答最后让模型从多个维度打分。# oai_client.py 中评估函数关键部分 def evaluate_answer(question: str, user_answer: str) - tuple: prompt f 你是一名资深技术面试官请评估以下回答 面试题{question} 候选人回答{user_answer} 请从以下维度打分每项 1-10 分 - 技术准确性是否答对了核心知识点 - 逻辑清晰度表述是否有条理 - 深度与延伸是否展现出超出问题的理解 最后输出 JSON 格式结果例如 {{技术准确性: 8, 逻辑清晰度: 7, 深度与延伸: 6, 综合评分: 7, 评语: ...}} resp openai.ChatCompletion.create( modelMODEL_NAME, messages[{role: user, content: prompt}], temperature0.3, # 评估场景温度调低输出更稳定 max_tokens512 ) content resp.choices[0].message.content.strip() # 源码从这里解析 JSON 并返回 (综合评分, 评语) return parse_score(content)这个 prompt 有几个值得借鉴的设计温度降到 0.3让评估结果更稳定而非发散输出指定为 JSON 格式方便后续程序解析维度拆成三项再加综合分避免模型只给一个笼统分数。实际使用中你可以调整维度名来适配不同岗位方向——比如运维岗加「排障思路」维度产品岗加「用户思维」维度。4.2 JSON 解析与异常兜底模型返回的文本理论上应该是 JSON但实际请求中经常会出现多出一些前后缀文字或者整个 JSON 被截断的情况。源码里有一段处理这个问题的逻辑属于整份代码里最有工程经验的地方。import json import re def parse_score(content: str) - tuple: # 先尝试完整解析 try: data json.loads(content) return data.get(综合评分, 5), data.get(评语, 无评语) except json.JSONDecodeError: pass # 失败则用正则提取 JSON 片段 match re.search(r\{.*\}, content, re.DOTALL) if match: try: data json.loads(match.group()) return data.get(综合评分, 5), data.get(评语, ) except json.JSONDecodeError: pass # 都失败就给默认值 return 5, 模型输出格式异常无法解析评估结果这段代码的兜底策略很实用先完整解析失败后正则提取大括号片段再失败给默认分。三层防护保证了主流程不因模型输出格式问题崩掉。我见过不少调 LLM API 的项目卡在响应解析上这段逻辑可以直接抄走用在别处。4.3 上下文窗口与多轮对话的边界调用一次只评估一轮问答这是源码的当前实现。这意味着系统不会跨轮次记忆——候选人上一道题说了什么对当前评估没有影响。这个设计对单题评估足够但对完整面试场景有局限。要扩展成多轮面试常见做法是在 prompt 里拼接历史对话history \n.join( f面试官{q}\n候选人{a} for q, a in st.session_state.history[-5:] ) prompt f以下是面试前序对话\n{history}\n\n现在评估以下回答\n{question}\n{user_answer}但要注意上下文窗口限制拼接的历史不能无限制增长最多保留最近三轮到五轮。超过这个量token 消耗增长很快响应延迟也会明显增加。这是后续做多轮面试必须权衡的点。5. Fly.io 部署与避坑记录从 Dockerfile 到生产环境5.1 Dockerfile 与依赖缓存策略源码提供了 Dockerfile 和 fly.toml说明作者默认的部署目标是 Fly.io。Dockerfile 的写法决定镜像构建速度和最终体积这里有必要拆开看。FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8501 CMD [streamlit, run, interview_streamlit.py, --server.port8501, --server.address0.0.0.0]这个 Dockerfile 用了多阶段依赖缓存先复制 requirements.txt 单独安装依赖再复制源码。这意味着只要依赖没变重新构建时 pip install 层会命中缓存构建速度快很多。--no-cache-dir是为了减小镜像体积0.0.0.0地址是为了让外部流量能访问进去。fly.toml 里配置的是 app 名称和内部端口核心是把 8501 端口暴露给外部流量。这种配置文件的坑主要在端口不一致——如果 Dockerfile 里启动的是 8501fly.toml 必须同步。5.2 避坑记录四个反复出现的现场问题以下问题都是实际跑这个系统时流程里最常碰见的我按「现象 → 原因 → 解决」的方式记录。问题一openai 调用报 AttributeError提示 ChatCompletion 不存在现象运行 evaluate_answer 时抛错AttributeError: module openai has no attribute ChatCompletion。原因openai Python 包 1.0 之后把ChatCompletion.create改成了client.chat.completions.create源码写的旧接口直接失效。解决要么按 requirements.txt 锁定 openai 0.28.x 版本安装要么改造 oai_client.py 适配新接口。我建议改代码而不是降版本——新 SDK 才是长期出路。# 看当前实际安装的版本 pip show openai | grep Version # 如果高于 1.0改成旧版 pip install openai0.28,1.0问题二种子数据seed data与数据集的区分现象inputs.csv是一个非常小的文件几十行而不是完整的对话日志。原因这个文件是「种子数据」或「seed data」用于给系统提供初始问题模板和评估对照不是生产环境的完整题库。完整对话记录需要运行过程中通过日志积累源码的设计是把这套流程跑通再让你灌入自己的数据。解决不要纠结数据集大小先跑通流程再按业务需要扩充inputs.csv。具体扩充方法见第 6 章。问题三中文回答评分偏低准确性差现象候选人用中文回答但模型评分普遍偏低或者评语与回答内容不匹配。原因模型对中文语境的评估准确度不如英文且温度参数过高会导致评分波动。另外inputs.csv中的参考回答是模型 scoring 的锚点参考回答质量不高时选手的回答也会被压分。解决评估打分时把TEMPERATURE调到 0.2 以下并在 prompt 中明确指出「按中文表达习惯评估」必要时将MODEL_NAME换成对中文理解更强的模型。同时校验inputs.csv中参考回答的质量低质量的参考回答会直接拉低整个评估的区分度。# settings.py 中调整 TEMPERATURE 0.2问题四Fly.io 部署后页面白屏日志无异常现象fly launch部署成功访问域名时页面加载不出来但本地运行正常。原因多数是基于 Dockerfile 的端口配置与 fly.toml 的internal_port不一致。Streamlit 实际监听端口与 Fly 转发端口不匹配。解决确认 fly.toml 的internal_port 8501与 Dockerfile 中EXPOSE 8501一致。另外 Streamlit 启动时要加上--server.address0.0.0.0否则容器内只监听 localhost外部流量进不来。[services] internal_port 8501 protocol tcp问题五超时重试缺失偶尔抛 Timeout 异常现象调用 LLM 时偶发openai.error.Timeout程序直接中断。原因源码没有对 LLM 接口做超时重试网络抖动或 API 触发限流时直接抛异常。解决简单加一个重试装饰器最多重试 3 次每次间隔递增。import time from functools import wraps def retry_on_timeout(retries3, delay2): def decorator(func): wraps(func) def wrapper(*args, **kwargs): for i in range(retries): try: return func(*args, **kwargs) except Exception as e: if i retries - 1: raise e time.sleep(delay * (i 1)) return None return wrapper return decorator # 使用时给评估函数加上装饰器 retry_on_timeout(retries3, delay2) def evaluate_answer(question, answer): ...5.3 部署后的验证清单部署完成不是终点至少要过一遍验证清单访问一次首页确认页面正常渲染、输入回答提交一次确认 LLM 调用链路通、查看日志确认没有报错。这一步能省掉后续大量排查时间。# 查看部署状态和日志 fly status fly logs日志里重点看两个信息有没有连接 Fly 内部的错误以及 LLM API 调用的响应时间是否异常偏长。如果是后者换模型或者调整超时设置。6. 二次开发与扩展把系统改成自己的智能面试工具拿到这份源码如果只是跑一遍 demo 然后写进课程设计报告那浪费了一大半价值。它真正值得投入的地方在于把「面试题目」和「评估标准」定制成自己的方向。我给出三条扩展路径从简单到复杂任选其一都够写成一篇有深度的课程设计报告。第一扩充 inputs.csv 的题库这是最快见效的做法。把 Python 方向的题目换成 Java、前端或你论文方向的内容重新组织reference_answer。这里有一个关键技巧reference_answer的措辞要结构化用「要点1要点2」这种格式模型给候选人打分时才会按点给分。如果参考回答写得太散评分就会飘。第二修改评估 prompt 中的维度适配不同评估目标。源代码中评估维度是「技术准确性、逻辑清晰度、深度与延伸」用于综合技术岗不错。但如果你做的是校招场景可能要改成「沟通表达、解决问题、学习潜力」三组如果是运维岗改成「故障排查思路、安全意识、效率工具掌握度」。改 prompt 比改代码安全得多这也是这个系统设计得聪明的地方——维度和评估标准都沉淀在 oai_client.py 的字符串里。# 自定义评估维度的写法 dimensions { 技术准确性: 是否答对了核心知识点, 业务理解: 是否理解技术背后的业务场景, 表达与沟通: 是否清晰表达了自己的思路 } dim_prompt \n.join([f- {k}{v} for k, v in dimensions.items()])第三把流式输出加进评估界面。现在点击提交后页面会有几秒空白等待——这是大模型接口在等待完整响应。体验优化方案是用streamTrue把模型的 token 逐字打印在页面上候选人能看到 AI 是在「一笔一笔写」评语的。这个改动在 interview_streamlit.py 里大概加 30 行代码但对演示效果的提升非常明显答辩现场尤其有用。验收集成之后我习惯把整个流程再走一遍清空虚拟环境重新装依赖从零跑一遍 Streamlit确认评分能返回。这半小时的「后悔药」流程能拦掉绝大多数交付现场翻车。从那以后我每次拿到新源码包第一件事永远是先跑通再改代码而不是先改代码再跑通——这只智能面试系统希望你也能把它跑成自己的东西希望帮到你。本文还有配套的精品资源点击获取