C#學習:基于LLM的簡歷評估程序

前言

在pocketflow的例子中看到了一個基于LLM的簡歷評估程序的例子,感覺還挺好玩的,為了練習一下C#,我最近使用C#重寫了一個。

準備不同的簡歷:

image-20250528183949844

查看效果:

image-20250528184200364

image-20250528184258947

不足之處是現實的簡歷應該是pdf格式的,后面可以考慮轉化為圖片然后用VLM來試試。

C#學習

在使用C#重寫的過程中,學習到的一些東西。

KeyValuePair學習

使用到了KeyValuePair

KeyValuePair<TKey, TValue> 是 C# 中一個用于表示鍵值對的結構體(struct),它是一個泛型類型,可以存儲兩個相關聯的值:一個鍵(key)和一個值(value)。

主要特點:

不可變性:KeyValuePair 是一個只讀結構,一旦創建就不能修改其鍵或值。

泛型實現

public struct KeyValuePair<TKey, TValue>

其中 TKey 是鍵的類型,TValue 是值的類型。

使用示例:

// 創建 KeyValuePair
KeyValuePair<string, int> pair = new KeyValuePair<string, int>("Age", 25);// 訪問鍵和值
Console.WriteLine($"Key: {pair.Key}"); // 輸出: Key: Age
Console.WriteLine($"Value: {pair.Value}"); // 輸出: Value: 25// 在集合中使用
List<KeyValuePair<string, int>> pairs = new List<KeyValuePair<string, int>>
{new KeyValuePair<string, int>("John", 25),new KeyValuePair<string, int>("Mary", 30)
};

KeyValuePair 通常在以下場景中使用:

作為 Dictionary 的枚舉結果

Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("One", 1);
dict.Add("Two", 2);foreach (KeyValuePair<string, int> kvp in dict)
{Console.WriteLine($"Key: {kvp.Key}, Value: {kvp.Value}");
}

方法返回鍵值對

public KeyValuePair<string, int> GetPersonInfo()
{return new KeyValuePair<string, int>("Age", 25);
}

LINQ 操作中

var dict = new Dictionary<string, int>();
// ... 添加一些數據
var filtered = dict.Where(kvp => kvp.Value > 10).Select(kvp => kvp.Key);

需要注意的是,如果需要可修改的鍵值對集合,應該使用 Dictionary<TKey, TValue> 而不是 KeyValuePair 的集合。Dictionary 提供了更多的功能和更好的性能。KeyValuePair 主要用于表示單個鍵值對關系,特別是在遍歷或傳遞數據時。

YAML內容解析

根據這個提示詞:

                string prompt = $@"
評估以下簡歷并確定候選人是否符合高級技術職位的要求。
資格標準:
- 至少具有相關領域的學士學位
- 至少3年相關工作經驗
- 與職位相關的強大技術技能簡歷內容:
{content}請以YAML格式返回您的評估:
```yaml
candidate_name: [候選人姓名]
qualifies: [true/false]
reasons:- [資格認定/不認定的第一個原因]- [第二個原因(如果適用)]
```
";

LLM會返回一個YAML格式的內容,如下所示:

image-20250528190501147

需要解析這個YAML格式內容。

 public static Dictionary<string, object> ParseSimpleYaml(string yaml){var result = new Dictionary<string, object>();string[] lines = yaml.Split('\n');string currentKey = null;List<string> currentList = null;int currentIndentation = 0;for (int i = 0; i < lines.Length; i++){string line = lines[i].Trim();if (string.IsNullOrEmpty(line) || line.StartsWith("#"))continue;int indentation = lines[i].TakeWhile(c => c == ' ').Count();// Handle list itemsif (line.StartsWith("- ")){if (currentList == null){currentList = new List<string>();result[currentKey] = currentList;}string listItem = line.Substring(2).Trim();currentList.Add(listItem);continue;}// Parse key-value pairsint colonIndex = line.IndexOf(':');if (colonIndex > 0){currentKey = line.Substring(0, colonIndex).Trim();string value = line.Substring(colonIndex + 1).Trim();currentIndentation = indentation;currentList = null;// Check if this is a multi-line value with |if (value == "|"){StringBuilder multiline = new StringBuilder();i++;// Collect all indented lineswhile (i < lines.Length && (lines[i].StartsWith("    ") || string.IsNullOrWhiteSpace(lines[i]))){if (!string.IsNullOrWhiteSpace(lines[i]))multiline.AppendLine(lines[i].Substring(4)); // Remove indentationi++;}i--; // Step back to process the next non-indented line in the outer loopresult[currentKey] = multiline.ToString().Trim();}else if (!string.IsNullOrEmpty(value)){// Simple key-valueresult[currentKey] = value;}}}return result;}

解析結果:

image-20250528190559917

C#條件運算符和空合并運算符

 string name = evaluation.TryGetValue("candidate_name", out var candidateNameValue)? candidateNameValue?.ToString() ?? "未知": "未知";

evaluation.TryGetValue(“candidate_name”, out var candidateNameValue)

  • TryGetValue 是 Dictionary 類的一個方法

  • 它嘗試獲取鍵為 “candidate_name” 的值

  • 如果找到了值,返回 true,并將值存儲在 candidateNameValue 變量中

  • 如果沒找到值,返回 false,candidateNameValue 將為默認值

? 條件運算符(三元運算符)

  • 格式為:condition ? value IfTrue : value If False

  • 如果 TryGetValue 返回 true,執行 :前面的部分

  • 如果 TryGetValue 返回 false,執行 : 后面的 “未知”

candidateNameValue?.ToString()

?. 是空條件運算符

  • 如果 candidateNameValue 不為 null,則調用 ToString()

  • 如果 candidateNameValue 為 null,則返回 null

?? “未知”

?? 是空合并運算符

  • 如果左邊的值為 null,則使用右邊的值(“未知”)

動態類型轉換

List<Dictionary<string, object>> evaluations = null;
var objectList = shared["evaluations"] as List<object>;if (objectList != null)
{evaluations = objectList.Select(item => item as Dictionary<string, object>).Where(dict => dict != null).ToList();
}

這種寫法是因為在C#中處理動態類型轉換時需要特別小心,尤其是在處理集合類型時。

  1. 首先,shared 是一個 Dictionary<string, object>,這意味著存儲在其中的值都是 object 類型。

  2. shared[“evaluations”] 實際上存儲的是一個列表,但由于存在字典中時是 object 類型,我們需要安全地將其轉換回實際的類型。

  3. 代碼使用了兩步轉換的原因是:

  • 第一步:var objectList = shared[“evaluations”] as List;

這一步將 object 轉換為 List,因為列表中的每個元素此時仍然是 object 類型

  evaluations = objectList.Select(item => item as Dictionary<string, object>).Where(dict => dict != null).ToList();

這一步將列表中的每個 object 轉換為 Dictionary<string, object>,因為每個評估結果實際上是一個字典

使用 as 操作符而不是直接類型轉換(比如 (List)shared[“evaluations”])的原因是:

  • as 操作符在轉換失敗時會返回 null,而不是拋出異常

  • 這樣可以安全地進行類型檢查和轉換,避免運行時錯誤

使用 Where(dict => dict != null) 可以過濾掉任何轉換失敗的項,確保最終的列表中只包含有效的字典對象

這種寫法雖然看起來有點復雜,但它是一種安全和健壯的方式來處理動態類型轉換,特別是在處理可能包含不同類型數據的集合時。這種方式可以:

  • 避免運行時異常

  • 確保類型安全

  • 優雅地處理可能的空值或無效數據

最后

全部代碼已上傳至GitHub,地址:https://github.com/Ming-jiayou/PocketFlowSharp/tree/main/PocketFlowSharpSamples.Console/Resume_Qualification_Demo

推薦閱讀

“Pocket Flow,一個僅用 100 行代碼實現的 LLM 框架”

使用PocketFlow構建Web Search Agent

手把手教你使用C#創建一個WebSearchAgent

使用PocketFlowSharp創建一個Human_Evaluation示例

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82825.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82825.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82825.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

git怎么合并兩個分支

git怎么合并分支代碼 注意: 第一步你得把當前分支合到遠程分支去才能有下面的操作 另外我是將develop分支代碼合并到release分支去 git 命令 查看本地所有分支 git branch切換分支 例如切換到release分支 git checkout release拉取代碼 git pull up release 合并分支 …

Android-kotlin協程學習總結

Kotlin協程實戰對話? ?真題1&#xff1a;協程與線程的本質區別是什么&#xff1f;為什么說協程是輕量級的&#xff1f;?? ?面試官?&#xff1a; “我看你項目中用協程替代了線程池&#xff0c;能說說協程和線程的核心區別嗎&#xff1f;為什么協程更適合高并發&#xf…

uni-app學習筆記十四-vue3中emit的使用

在組件傳值中&#xff0c;無論是props還是slot都是單向數據流&#xff0c;父組件向子組件傳值&#xff0c;子組件不能直接對父組件傳過來的值進行重新賦值。 下面學習子組件向父組件傳值的工具--emit。 在子組件emit設置傳遞的函數名和值 <template><view>子組件…

Java設計模式從基礎到實際運用

第一部分&#xff1a;設計模式基礎 1. 設計模式概述 設計模式(Design Pattern)是一套被反復使用、多數人知曉的、經過分類編目的代碼設計經驗的總結&#xff0c;它描述了在軟件設計過程中一些不斷重復出現的問題以及該問題的解決方案。設計模式是在特定環境下解決軟件設計問題…

鴻蒙OSUniApp 制作自定義的進度條組件#三方框架 #Uniapp

使用 UniApp 制作自定義的進度條組件 在移動應用開發中&#xff0c;進度條是非常常見的 UI 組件&#xff0c;無論是文件上傳、下載、任務進度還是表單填寫反饋&#xff0c;進度條都能為用戶提供直觀的進度提示。雖然 UniApp 提供了一些基礎的進度條能力&#xff0c;但在實際項…

Python爬蟲實戰:研究Beautiful Soup框架相關技術

1. 引言 1.1 研究背景與意義 隨著互聯網的快速發展,網絡上的數據量呈爆炸式增長。如何從海量的網頁數據中高效提取有價值的信息,成為信息科學領域的重要研究課題。網絡爬蟲作為一種自動獲取網頁內容的技術,能夠按照預設規則遍歷互聯網并采集數據,為信息檢索、輿情分析、商…

【Tips】關于PCI和PCIe的配置空間差異和io/memory io讀寫

最近在看同事2023年講的PCI基礎課&#xff0c;感覺確實是豁然開朗了&#xff0c;贊美同事。 PCIe實際上是PCI的擴展&#xff08;extended&#xff09;&#xff0c;PCIe設備相當于是迭代升級產品。 而PCIe的配置空間基于PCI原有的0xFF&#xff08;256字節&#xff09;配置空間…

桂花網體育運動監測方案:開啟幼兒園運動健康管理新篇章

在幼兒教育領域&#xff0c;運動能力的培養與健康監測始終是備受關注的核心環節。隨著科技的飛速發展&#xff0c;如何科學、有效地監測幼兒的運動狀態&#xff0c;成為了幼兒園教育者面臨的一大挑戰。桂花網體育運動監測方案憑借其高效、精準、智能化的特性&#xff0c;為幼兒…

Perforce P4產品簡介:無限擴展+全球協作+安全管控+工具集成(附下載)

本產品簡介由Perforce中國授權合作伙伴——龍智編輯整理&#xff0c;旨在帶您快速了解Perforce P4版本控制系統的強大之處。 世界級無限可擴展的版本控制系統 Perforce P4&#xff08;原Helix Core&#xff09;是業界領先的版本控制平臺&#xff0c;備受19家全球Top20 AAA級游…

pikachu靶場通關筆記08 XSS關卡04-DOM型XSS

目錄 一、XSS原理 二、DOM型XSS 三、源碼分析 1、進入靶場 2、XSS探測 3、源碼分析 四、滲透實戰 1、Payload1 2、Payload2 3、Payload3 本系列為通過《pikachu靶場通關筆記》的XSS關卡(共10關&#xff09;滲透集合&#xff0c;通過對XSS關卡源碼的代碼審計找到XSS風…

安全訪問 std::tuple 的容錯方法及氣象領域應用

安全訪問 std::tuple 的容錯方法及氣象領域應用 1. std::tuple 安全訪問的核心問題 1.1 元組結構性問題&#xff08;編譯時錯誤&#xff09; 當元組元素數量為空時&#xff08;std::tuple<>&#xff09;&#xff0c;任何訪問元素的嘗試都會導致編譯錯誤?&#xff1a;…

Webug4.0靶場通關筆記03- 第3關SQL注入之時間盲注(手注法+腳本法 兩種方法)

目錄 一、源碼分析 1.分析閉合 2.分析輸出 &#xff08;1&#xff09;查詢成功 &#xff08;2&#xff09;查詢失敗 &#xff08;3&#xff09;SQL語句執行報錯 二、第03關 延時注入 1.打開靶場 2.SQL手注 &#xff08;1&#xff09;盲注分析 &#xff08;2&#xf…

【大模型學習網絡互聯】Memory-Mapped I/O MMIO語義與MEM語義

MMIO語義和MEM語義的區別 嗯&#xff0c;用戶要求更詳細地區分MMIO和MEM語義&#xff0c;看來之前的中文對比雖然系統但還不夠深入。用戶可能是嵌入式開發者或OS內核學習者&#xff0c;需要從硬件行為層面理解差異。 用戶連續追問MMIO相關概念&#xff0c;說明ta在接觸底層開發…

如何在使用kickstart安裝物理機操作系統的過程中核對服務器的SN

原因 在使用kickstart對物理機進行重裝的時候&#xff0c;由于自動化配置&#xff0c;掛載鏡像重啟之后就會自動化開始安裝部署&#xff0c;不夠安全&#xff0c;萬一選錯服務器沒有辦法回退。因此可以在kickstart的ks配置文件中新增服務器SN的校驗&#xff0c;當校驗不通過的…

spring4第4課-ioc控制反轉-詳解如何注入參數

堅持住&#xff0c;第四天&#xff0c;繼續學習spring4.詳解如何注入參數 先總結&#xff0c;主要有如下6種&#xff1a; 1&#xff0c;基本類型值&#xff1b; 2&#xff0c;注入 bean&#xff1b; 3&#xff0c;內部 bean&#xff1b; 4&#xff0c;null 值&#xff1b; 5&…

cf2067A

原題鏈接&#xff1a;https://codeforces.com/contest/2067/problem/A 題目背景&#xff1a; 給定x,y&#xff0c;判讀是否存在 n 滿足S(n) x&#xff0c;S(n 1) y。定義 S(a) 等于 a 的十進制位數之和。 思路&#xff1a; 不難發現一般 n 和 n 1 的位數之和相差為 1&…

微信小程序獲取手機號

詳細代碼 <t-button size"large" theme"primary" variant"outline" data-type"hasCancelBtn" bind:tap"showDialog" block style"display: none;">開放能力按鈕 </t-button> <t-dialog id"t-…

AI重構SEO關鍵詞精準定位

內容概要 隨著AI技術深度滲透數字營銷領域&#xff0c;傳統SEO關鍵詞定位模式正經歷系統性重構。基于自然語言處理&#xff08;NLP&#xff09;的智能語義分析引擎&#xff0c;可突破傳統關鍵詞工具的局限性&#xff0c;通過解析長尾搜索詞中的隱含意圖與語境關聯&#xff0c;…

四足機器人環境監測系統相關問題

一、在設計四足機器人監測與跟蹤系統整體架構時&#xff0c;你主要考慮了哪些因素&#xff1f;為什么這樣設計以確保系統的高效性與穩定性&#xff1f; 在設計四足機器人監測與跟蹤系統整體架構時&#xff0c;主要考慮了傳感器兼容性與通信效率、多任務并發處理能力、實時數據…

uniapp 開發安卓app 微信授權獲取昵稱 頭像登錄

在manifest.json中配置appid 以及appsecret uni.login({provider: weixin,success: function (loginRes) {console.log(loginRes.authResult);// 獲取用戶信息uni.getUserInfo({provider: weixin,success: function (infoRes) {console.log(用戶昵稱為&#xff1a; infoRes.u…