開發博客:AI面試官個性化出題MCP功能最終完善
本周作為項目開發的最后沖刺階段,我們致力于進一步增強AI面試官在個性化題目生成方面的能力。核心工作是新增和優化了一系列MCP(Multi-turn Conversation Protocol)工具,旨在為AI面試官提供更豐富、更精準的用戶畫像和知識背景,從而生成更具針對性的面試題目。
目前整個MCP工具鏈的結構如下:
本周主要完成的MCP功能模塊包括:query_user_submission_stats
,query_user_articles
,以及search_articles_by_keyword
。以下將對這些功能進行詳細說明。
1. query_user_submission_stats
:用戶答題數據統計
- 功能描述: 此工具通過分析用戶在在線判題系統(OJ)中的答題記錄,評估用戶的代碼熟練度和能力水平。統計信息包括用戶嘗試過的題目總數、成功解答的題目總數,以及成功解答題目按難度(簡單、中等、困難)的分布情況。
- 實現邏輯:
- 工具接收用戶ID(
userId
)作為輸入。首先對userId
進行校驗,確保其為有效的整型數字字符串。 - 從
oj_code_submission
數據庫表中查詢指定用戶的所有提交記錄,提取problem_id
和status
。 - 使用
Set
數據結構統計用戶嘗試過的所有題目ID(attemptedProblemIds
)和狀態為“accepted”的題目ID(acceptedProblemIds
),以實現自動去重。 - 若用戶有成功解答的題目(
acceptedProblemIds
不為空),則進一步從oj_problem
表中查詢這些已通過題目的難度(difficulty
)。 - 根據查詢到的難度信息,統計“簡單”、“中等”、“困難”各自的數量。
- 最終返回一個包含總嘗試題目數(
totalAttempted
)、總通過題目數(totalAccepted
)以及按難度分類的通過題目數(acceptedByDifficulty
)的JSON對象。 - 包含完整的錯誤處理機制,如無效
userId
或數據庫查詢失敗等情況。
- 工具接收用戶ID(
- 價值: AI面試官可以利用這些數據了解候選人的實際編程能力和薄弱環節,從而調整面試題目的難度和類型,實現更精準的考察。
- 代碼實現:
server.tool("query_user_submission_stats","統計用戶的答題記錄信息,包括已完成題目數和完成題目的按難度分類統計",{userId: z.string().describe("用戶ID,為整形數字的字符串格式"),},async ({ userId }) => {try {const mysqlPool = getMySQL();const userIdInt = parseInt(userId);if (isNaN(userIdInt)) {return {content: [{ type: "text", text: `無效的userId格式: ${userId}` }],isError: true};}// 獲取用戶的提交記錄const [submissions] = await mysqlPool.query(`SELECT problem_id, status FROM oj_code_submission WHERE user_id = ?`, [userIdInt]);// 統計已嘗試和已通過的題目const attemptedProblemIds = new Set();const acceptedProblemIds = new Set();const ACCEPTED_STATUS = "accepted";for (const submission of submissions) {const problemId = submission.problem_id;// 所有提交過的題目ID(自動去重)attemptedProblemIds.add(problemId);// 僅添加ACCEPTED狀態的題目ID(自動去重)if (ACCEPTED_STATUS.toLowerCase() === submission.status.toLowerCase()) {acceptedProblemIds.add(problemId);}}// 查詢已通過題目的難度分布const acceptedProblemsList = Array.from(acceptedProblemIds);let difficultyStats = {easy: 0,medium: 0,hard: 0};if (acceptedProblemsList.length > 0) {const [problemDifficulties] = await mysqlPool.query(`SELECT id, difficulty FROM oj_problem WHERE id IN (?)`, [acceptedProblemsList]);// 按難度統計for (const problem of problemDifficulties) {const difficulty = problem.difficulty ? problem.difficulty.toLowerCase() : 'unknown';if (difficulty === '簡單') difficultyStats.easy++;else if (difficulty === '中等') difficultyStats.medium++;else if (difficulty === '困難') difficultyStats.hard++;}}// 構建統計結果const stats = {totalAttempted: attemptedProblemIds.size,totalAccepted: acceptedProblemIds.size,acceptedByDifficulty: difficultyStats};return {content: [{ type: "text", text: JSON.stringify(stats, null, 2) }]};} catch (error) {console.error(`查詢用戶答題統計時發生錯誤: ${error.message}`);return {content: [{ type: "text", text: `查詢用戶答題統計時發生內部錯誤: ${error.message}` }],isError: true};}} );
2. query_user_articles
:用戶論壇發帖分析
- 功能描述: 該工具用于檢索并分析用戶近期在社區論壇中發布的文章。目的是從用戶的發帖內容中提取其關注的技術方向、感興趣的公司、討論過的面試題目等信息,作為個性化出題的參考。
- 實現邏輯:
- 工具接收用戶ID(
userId
)作為輸入,并進行有效性校驗。 - 通過聯合查詢
forest_article
(文章主表)和forest_article_content
(文章內容表),獲取指定article_author_id
用戶的最多20篇最新發布的文章,包括文章標題、標簽、瀏覽/評論/點贊數、創建時間、預覽內容及完整內容。 - 若未找到用戶文章,則返回相應提示。
- 如果查詢到文章,且配置了DashScope的API密鑰(
DASHSCOPE_API_KEY
)和應用ID(DASHSCOPE_SUM_APP_ID
),則將獲取的文章數據(JSON格式)作為輸入,調用DashScope大模型服務進行內容分析和總結。Prompt中指定為“模式一以分析下面內容”。 - AI服務返回對用戶發帖內容的提煉信息,該信息將作為出題參考返回。
- 若AI調用失敗、未配置API密鑰或應用ID,則直接返回原始查詢到的文章數據(JSON格式)。
- 包含數據庫查詢和AI服務調用的錯誤處理。
- 工具接收用戶ID(
- 價值: 通過用戶自身的言論,AI面試官能更深入地了解候選人的求職意向、技術棧偏好以及對特定問題的看法,為生成高度個性化的面試場景和問題提供素材。
- 代碼實現:
server.tool("query_user_articles","根據用戶ID獲取該用戶發布文章,用于作為用戶個性化問題出題參考",{userId: z.string().describe("用戶ID,為整形數字的字符串格式"),},async ({ userId }) => {try {const mysqlPool = getMySQL();const userIdInt = parseInt(userId);if (isNaN(userIdInt)) {return {content: [{ type: "text", text: `無效的userId格式: ${userId}` }],isError: true};}// 聯合查詢獲取用戶的文章及其內容const [articles] = await mysqlPool.query(`SELECT a.id, a.article_title, a.article_tags, a.article_view_count,a.article_comment_count,a.article_thumbs_up_count,a.created_time,a.article_preview_content,c.article_contentFROM forest_article aLEFT JOIN forest_article_content c ON a.id = c.id_articleWHERE a.article_author_id = ?ORDER BY a.created_time DESCLIMIT 20`, [userIdInt]);if (!articles || articles.length === 0) {return {content: [{ type: "text", text: `未找到用戶ID為${userId}的文章` }]};}// 調用AI處理查詢結果const apiKey = process.env.DASHSCOPE_API_KEY;const appId = process.env.DASHSCOPE_SUM_APP_ID;if (!apiKey || !appId) {console.error('DashScope API Key or App ID not configured.');return {content: [{ type: "text", text: JSON.stringify(articles, null, 2) }]};}const url = `https://dashscope.aliyuncs.com/api/v1/apps/${appId}/completion`;const data = {input: {prompt: `以模式一以分析下面內容:\n${JSON.stringify(articles)}`},parameters: {},debug: {}};try {const response = await axios.post(url, data, {headers: {'Authorization': `Bearer ${apiKey}`,'Content-Type': 'application/json'}});if (response.status === 200 && response.data.output && response.data.output.text) {return {content: [{ type: "text", text: "獲取到以下信息作為你的出題參考"+response.data.output.text }]};} } catch (aiError) {console.error(`Error calling DashScope: ${aiError.message}`);// 如果AI調用失敗,返回原始查詢結果return {content: [{ type: "text", text: JSON.stringify(articles, null, 2) }]};}} catch (error) {console.error(`查詢用戶文章時發生錯誤: ${error.message}`);return {content: [{ type: "text", text: `查詢用戶文章時發生內部錯誤: ${error.message}` }],isError: true};}} );
3. search_articles_by_keyword
:社區內容關鍵詞檢索
- 功能描述: 此工具允許根據特定關鍵詞(如目標公司名稱“阿里”、“騰訊”等)在社區論壇中搜索相關的文章,如面經分享、技術探討、解題思路等,為AI面試官提供針對性的出題參考。
- 實現邏輯:
- 工具接收搜索關鍵詞(
keyword
)作為輸入,并校驗關鍵詞非空。 - 構建SQL的
LIKE
查詢模式(%keyword%
),在forest_article
表的article_title
字段和forest_article_content
表的article_content
字段中進行模糊匹配。 - 查詢并返回按創建時間倒序排列的最多20篇相關文章,包含與
query_user_articles
類似的字段信息。 - 若未找到匹配文章,則返回相應提示。
- 與
query_user_articles
類似,如果查詢到文章且配置了DashScope服務,則將文章數據發送給大模型進行分析總結。Prompt中指定為“模式二以分析下面內容”。 - AI服務返回對搜索結果的提煉信息,作為出題參考。
- 若AI調用失敗、未配置或關鍵詞無效,則返回原始文章數據或錯誤信息。
- 包含數據庫查詢和AI服務調用的錯誤處理。
- 工具接收搜索關鍵詞(
- 價值: 當AI面試官需要針對特定公司或技術領域出題時,此工具能快速從社區中聚合相關的高價值信息,確保面試問題的前沿性和針對性,例如了解某公司常考的知識點或最新的技術趨勢。
- 代碼實現:
server.tool("search_articles_by_keyword","根據企業相關關鍵詞(如阿里,騰訊)獲取社區中提及相關出題知識點,用于作為出題參考",{keyword: z.string().describe("搜索關鍵詞"),},async ({ keyword }) => {try {if (!keyword || keyword.trim() === "") {return {content: [{ type: "text", text: "搜索關鍵詞不能為空" }],isError: true};}const mysqlPool = getMySQL();const searchKeyword = `%${keyword}%`; // 構建LIKE匹配模式// 聯合查詢匹配標題或內容的文章const [articles] = await mysqlPool.query(`SELECT a.id, a.article_title, a.article_tags, a.article_view_count,a.article_comment_count,a.article_thumbs_up_count,a.created_time,a.article_preview_content,c.article_contentFROM forest_article aLEFT JOIN forest_article_content c ON a.id = c.id_articleWHERE a.article_title LIKE ? OR c.article_content LIKE ?ORDER BY a.created_time DESCLIMIT 20`, [searchKeyword, searchKeyword]);if (!articles || articles.length === 0) {return {content: [{ type: "text", text: `未找到包含關鍵詞"${keyword}"的文章` }]};}// 調用AI處理查詢結果const apiKey = process.env.DASHSCOPE_API_KEY;const appId = process.env.DASHSCOPE_SUM_APP_ID;if (!apiKey || !appId) {console.error('DashScope API Key or App ID not configured.');return {content: [{ type: "text", text: JSON.stringify(articles, null, 2) }]};}const url = `https://dashscope.aliyuncs.com/api/v1/apps/${appId}/completion`;const data = {input: {prompt: `以模式二以分析下面內容:\n${JSON.stringify(articles)}`},parameters: {},debug: {}};try {const response = await axios.post(url, data, {headers: {'Authorization': `Bearer ${apiKey}`,'Content-Type': 'application/json'}});if (response.status === 200 && response.data.output && response.data.output.text) {return {content: [{ type: "text", text:"獲取到以下信息作為你的出題參考"+ response.data.output.text }]};} } catch (aiError) {console.error(`Error calling DashScope: ${aiError.message}`);// 如果AI調用失敗,返回原始查詢結果return {content: [{ type: "text", text: JSON.stringify(articles, null, 2) }]};}} catch (error) {console.error(`關鍵詞搜索文章時發生錯誤: ${error.message}`);return {content: [{ type: "text", text: `關鍵詞搜索文章時發生內部錯誤: ${error.message}` }],isError: true};}} );
代碼集成說明
上述三個核心功能均已通過server.tool
方法在服務端進行了注冊。每個工具都明確了其名稱、功能描述、輸入參數模式(使用zod
進行定義和校驗)以及異步執行函數。這種模塊化的工具設計,使得AI面試官能夠根據對話上下文和面試需求,靈活地調用這些外部能力。代碼實現細節已在各功能模塊中展示。
本周工作總結與意義
通過本周新增的這三個MCP工具,AI面試官獲取個性化信息的能力得到了顯著加強:
- 更精準的能力評估: 基于用戶的實際刷題數據,準確判斷其編程水平。
- 更深入的意向洞察: 通過分析用戶發帖,了解其技術偏好和求職目標。
- 更相關的知識獲取: 結合社區中關于目標公司的熱門討論,使面試題目更貼近實際。
這些工具的組合使AI面試官能夠構建一個更全面的用戶畫像,從而設計出既能考察核心能力,又能體現候選人特點和意向的面試流程。