2.2 LangChain基础知识.md.html 167 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243
  1. <!doctype html>
  2. <html lang="zh" class="no-js">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width,initial-scale=1">
  6. <link rel="prev" href="2.1%20Ollama%E5%A4%A7%E6%A8%A1%E5%9E%8B%E9%AB%98%E6%95%88%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7.html">
  7. <link rel="next" href="2.3%20%E5%90%91%E9%87%8F%E7%B4%A2%E5%BC%95%EF%BC%9AHNSW%E3%80%81IVF%E4%B8%8EIVF_PQ.html">
  8. <link rel="icon" href="../img/AI.jpg">
  9. <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.21">
  10. <title>2.2 LangChain基础知识.md - 企业知识库RAG智能问答项目V1.0</title>
  11. <link rel="stylesheet" href="../assets/stylesheets/main.2a3383ac.min.css">
  12. <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  13. <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&amp;display=fallback">
  14. <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
  15. <link rel="stylesheet" href="../stylesheets/extra.css">
  16. <script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
  17. </head>
  18. <body dir="ltr">
  19. <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
  20. <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
  21. <label class="md-overlay" for="__drawer"></label>
  22. <div data-md-component="skip">
  23. <a href="#_1" class="md-skip">
  24. 跳转至
  25. </a>
  26. </div>
  27. <div data-md-component="announce">
  28. </div>
  29. <header class="md-header md-header--shadow" data-md-component="header">
  30. <nav class="md-header__inner md-grid" aria-label="页眉">
  31. <a href="../index.html" title="企业知识库RAG智能问答项目V1.0" class="md-header__button md-logo" aria-label="企业知识库RAG智能问答项目V1.0" data-md-component="logo">
  32. <img src="../img/AI.jpg" alt="logo">
  33. </a>
  34. <label class="md-header__button md-icon" for="__drawer">
  35. <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"></path></svg>
  36. </label>
  37. <div class="md-header__title" data-md-component="header-title">
  38. <div class="md-header__ellipsis">
  39. <div class="md-header__topic">
  40. <span class="md-ellipsis">
  41. 企业知识库RAG智能问答项目V1.0
  42. </span>
  43. </div>
  44. <div class="md-header__topic" data-md-component="header-topic">
  45. <span class="md-ellipsis">
  46. 2.2 LangChain基础知识.md
  47. </span>
  48. </div>
  49. </div>
  50. </div>
  51. <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
  52. <label class="md-header__button md-icon" for="__search">
  53. <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path></svg>
  54. </label>
  55. <div class="md-search" data-md-component="search" role="dialog">
  56. <label class="md-search__overlay" for="__search"></label>
  57. <div class="md-search__inner" role="search">
  58. <form class="md-search__form" name="search">
  59. <input type="text" class="md-search__input" name="query" aria-label="搜索" placeholder="搜索" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
  60. <label class="md-search__icon md-icon" for="__search">
  61. <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path></svg>
  62. <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"></path></svg>
  63. </label>
  64. <nav class="md-search__options" aria-label="查找">
  65. <button type="reset" class="md-search__icon md-icon" title="清空当前内容" aria-label="清空当前内容" tabindex="-1">
  66. <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></svg>
  67. </button>
  68. </nav>
  69. </form>
  70. <div class="md-search__output">
  71. <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
  72. <div class="md-search-result" data-md-component="search-result">
  73. <div class="md-search-result__meta">
  74. 正在初始化搜索引擎
  75. </div>
  76. <ol class="md-search-result__list" role="presentation"></ol>
  77. </div>
  78. </div>
  79. </div>
  80. </div>
  81. </div>
  82. </nav>
  83. </header>
  84. <div class="md-container" data-md-component="container">
  85. <main class="md-main" data-md-component="main">
  86. <div class="md-main__inner md-grid">
  87. <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
  88. <div class="md-sidebar__scrollwrap">
  89. <div class="md-sidebar__inner">
  90. <nav class="md-nav md-nav--primary" aria-label="导航栏" data-md-level="0">
  91. <label class="md-nav__title" for="__drawer">
  92. <a href="../index.html" title="企业知识库RAG智能问答项目V1.0" class="md-nav__button md-logo" aria-label="企业知识库RAG智能问答项目V1.0" data-md-component="logo">
  93. <img src="../img/AI.jpg" alt="logo">
  94. </a>
  95. 企业知识库RAG智能问答项目V1.0
  96. </label>
  97. <ul class="md-nav__list" data-md-scrollfix>
  98. <li class="md-nav__item">
  99. <a href="../index.html" class="md-nav__link">
  100. <span class="md-ellipsis">
  101. 知识库内容
  102. </span>
  103. </a>
  104. </li>
  105. <li class="md-nav__item md-nav__item--nested">
  106. <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2">
  107. <label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
  108. <span class="md-ellipsis">
  109. ① 项目概述
  110. </span>
  111. <span class="md-nav__icon md-icon"></span>
  112. </label>
  113. <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
  114. <label class="md-nav__title" for="__nav_2">
  115. <span class="md-nav__icon md-icon"></span>
  116. ① 项目概述
  117. </label>
  118. <ul class="md-nav__list" data-md-scrollfix>
  119. <li class="md-nav__item">
  120. <a href="../%E2%91%A0%20%E9%A1%B9%E7%9B%AE%E6%A6%82%E8%BF%B0/1.1%20%E9%A1%B9%E7%9B%AE%E6%9E%B6%E6%9E%84.html" class="md-nav__link">
  121. <span class="md-ellipsis">
  122. 1.1 项目架构
  123. </span>
  124. </a>
  125. </li>
  126. <li class="md-nav__item">
  127. <a href="../%E2%91%A0%20%E9%A1%B9%E7%9B%AE%E6%A6%82%E8%BF%B0/1.2%20%E9%A1%B9%E7%9B%AE%E7%8E%AF%E5%A2%83%28window%29.html" class="md-nav__link">
  128. <span class="md-ellipsis">
  129. 1.2 项目环境(window)
  130. </span>
  131. </a>
  132. </li>
  133. <li class="md-nav__item">
  134. <a href="../%E2%91%A0%20%E9%A1%B9%E7%9B%AE%E6%A6%82%E8%BF%B0/1.3%20%E9%A1%B9%E7%9B%AE%E7%8E%AF%E5%A2%83%28mac%29.html" class="md-nav__link">
  135. <span class="md-ellipsis">
  136. 1.3 项目环境(mac)
  137. </span>
  138. </a>
  139. </li>
  140. </ul>
  141. </nav>
  142. </li>
  143. <li class="md-nav__item md-nav__item--active md-nav__item--nested">
  144. <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
  145. <label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
  146. <span class="md-ellipsis">
  147. ② 项目工具
  148. </span>
  149. <span class="md-nav__icon md-icon"></span>
  150. </label>
  151. <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
  152. <label class="md-nav__title" for="__nav_3">
  153. <span class="md-nav__icon md-icon"></span>
  154. ② 项目工具
  155. </label>
  156. <ul class="md-nav__list" data-md-scrollfix>
  157. <li class="md-nav__item">
  158. <a href="2.1%20Ollama%E5%A4%A7%E6%A8%A1%E5%9E%8B%E9%AB%98%E6%95%88%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7.html" class="md-nav__link">
  159. <span class="md-ellipsis">
  160. 2.1 Ollama大模型高效管理工具
  161. </span>
  162. </a>
  163. </li>
  164. <li class="md-nav__item md-nav__item--active">
  165. <a href="2.2%20LangChain%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.md.html" class="md-nav__link md-nav__link--active">
  166. <span class="md-ellipsis">
  167. 2.2 LangChain基础知识.md
  168. </span>
  169. </a>
  170. </li>
  171. <li class="md-nav__item">
  172. <a href="2.3%20%E5%90%91%E9%87%8F%E7%B4%A2%E5%BC%95%EF%BC%9AHNSW%E3%80%81IVF%E4%B8%8EIVF_PQ.html" class="md-nav__link">
  173. <span class="md-ellipsis">
  174. 2.3 向量索引:HNSW、IVF与IVF_PQ
  175. </span>
  176. </a>
  177. </li>
  178. <li class="md-nav__item">
  179. <a href="2.4%20Milvus%E5%90%91%E9%87%8F%E6%95%B0%E6%8D%AE%E5%BA%93.html" class="md-nav__link">
  180. <span class="md-ellipsis">
  181. 2.4 Milvus向量数据库
  182. </span>
  183. </a>
  184. </li>
  185. </ul>
  186. </nav>
  187. </li>
  188. <li class="md-nav__item md-nav__item--nested">
  189. <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4">
  190. <label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
  191. <span class="md-ellipsis">
  192. ③ 基于Mysql库的问答系统
  193. </span>
  194. <span class="md-nav__icon md-icon"></span>
  195. </label>
  196. <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
  197. <label class="md-nav__title" for="__nav_4">
  198. <span class="md-nav__icon md-icon"></span>
  199. ③ 基于Mysql库的问答系统
  200. </label>
  201. <ul class="md-nav__list" data-md-scrollfix>
  202. <li class="md-nav__item">
  203. <a href="../%E2%91%A2%20%E5%9F%BA%E4%BA%8EMysql%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/3.1%20Python%E6%97%A5%E5%BF%97%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BA%94%E7%94%A8.html" class="md-nav__link">
  204. <span class="md-ellipsis">
  205. 3.1 Python日志介绍与应用
  206. </span>
  207. </a>
  208. </li>
  209. <li class="md-nav__item">
  210. <a href="../%E2%91%A2%20%E5%9F%BA%E4%BA%8EMysql%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/3.2%20Redis%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AE%80%E4%BB%8B%E4%B8%8E%E4%BD%BF%E7%94%A8.html" class="md-nav__link">
  211. <span class="md-ellipsis">
  212. 3.2 Redis数据库简介与使用
  213. </span>
  214. </a>
  215. </li>
  216. <li class="md-nav__item">
  217. <a href="../%E2%91%A2%20%E5%9F%BA%E4%BA%8EMysql%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/3.3%20%E5%9F%BA%E4%BA%8EMysql%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%9E%E7%8E%B0%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F.html" class="md-nav__link">
  218. <span class="md-ellipsis">
  219. 3.3 基于Mysql数据库实现问答系统
  220. </span>
  221. </a>
  222. </li>
  223. <li class="md-nav__item">
  224. <a href="../%E2%91%A2%20%E5%9F%BA%E4%BA%8EMysql%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/3.4%20BM25%E7%AE%97%E6%B3%95%E7%AE%80%E4%BB%8B%E4%B8%8E%E5%BA%94%E7%94%A8.html" class="md-nav__link">
  225. <span class="md-ellipsis">
  226. 3.4 BM25算法简介与应用
  227. </span>
  228. </a>
  229. </li>
  230. </ul>
  231. </nav>
  232. </li>
  233. <li class="md-nav__item md-nav__item--nested">
  234. <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5">
  235. <label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
  236. <span class="md-ellipsis">
  237. ④ 基于Milvus库的问答系统
  238. </span>
  239. <span class="md-nav__icon md-icon"></span>
  240. </label>
  241. <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
  242. <label class="md-nav__title" for="__nav_5">
  243. <span class="md-nav__icon md-icon"></span>
  244. ④ 基于Milvus库的问答系统
  245. </label>
  246. <ul class="md-nav__list" data-md-scrollfix>
  247. <li class="md-nav__item">
  248. <a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/4.1%20%E6%95%B4%E4%BD%93%E6%9E%B6%E6%9E%84%E4%B8%8E%E5%B7%A5%E7%A8%8B%E6%B5%81%E7%A8%8B.html" class="md-nav__link">
  249. <span class="md-ellipsis">
  250. 4.1 整体架构与工程流程
  251. </span>
  252. </a>
  253. </li>
  254. <li class="md-nav__item">
  255. <a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/4.2%20%E5%9F%BA%E7%A1%80%E6%A8%A1%E5%9D%97.html" class="md-nav__link">
  256. <span class="md-ellipsis">
  257. 4.2 基础模块
  258. </span>
  259. </a>
  260. </li>
  261. <li class="md-nav__item">
  262. <a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/4.3%20%E6%96%87%E6%A1%A3%E5%A4%84%E7%90%86%E6%A8%A1%E5%9D%97.html" class="md-nav__link">
  263. <span class="md-ellipsis">
  264. 4.3 文档处理模块
  265. </span>
  266. </a>
  267. </li>
  268. <li class="md-nav__item">
  269. <a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/4.4%20%E5%90%91%E9%87%8F%E5%AD%98%E5%82%A8.html" class="md-nav__link">
  270. <span class="md-ellipsis">
  271. 4.4 向量存储
  272. </span>
  273. </a>
  274. </li>
  275. <li class="md-nav__item"><a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/4.5%20BERT%E5%9F%BA%E7%A1%80%E4%B8%8E%E4%BB%BB%E5%8A%A1%E5%BE%AE%E8%B0%83.html" class="md-nav__link"><span class="md-ellipsis">4.5 BERT基础与任务微调</span></a></li><li class="md-nav__item">
  276. <a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/4.6%20prompts%E8%AE%BE%E8%AE%A1%E4%B8%8Equery%E6%84%8F%E5%9B%BE%E8%AF%86%E5%88%AB.html" class="md-nav__link">
  277. <span class="md-ellipsis">
  278. 4.6 prompts设计与query意图识别
  279. </span>
  280. </a>
  281. </li>
  282. <li class="md-nav__item">
  283. <a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/4.7%20%E6%A3%80%E7%B4%A2%E7%AD%96%E7%95%A5%E4%B8%8ERAG%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1.html" class="md-nav__link">
  284. <span class="md-ellipsis">
  285. 4.7 检索策略与RAG系统设计
  286. </span>
  287. </a>
  288. </li>
  289. <li class="md-nav__item">
  290. <a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/4.8%20RAG%E7%B3%BB%E7%BB%9F%E8%BF%90%E8%A1%8C.html" class="md-nav__link">
  291. <span class="md-ellipsis">
  292. 4.8 RAG系统运行
  293. </span>
  294. </a>
  295. </li>
  296. <li class="md-nav__item">
  297. <a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/4.9%20%E6%96%87%E6%A1%A3%E8%A7%A3%E6%9E%90%E5%B7%A5%E5%85%B7%28%E6%89%A9%E5%B1%95%E8%B5%84%E6%96%99%29.html" class="md-nav__link">
  298. <span class="md-ellipsis">
  299. 4.9 文档解析工具(扩展资料)
  300. </span>
  301. </a>
  302. </li>
  303. <li class="md-nav__item">
  304. <a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/4.10%20RAG%E4%B8%AD%E7%9A%84Query%E6%94%B9%E5%86%99%28%E6%89%A9%E5%B1%95%E8%B5%84%E6%96%99%29.html" class="md-nav__link">
  305. <span class="md-ellipsis">
  306. 4.10 RAG中的Query改写(扩展资料)
  307. </span>
  308. </a>
  309. </li>
  310. <li class="md-nav__item">
  311. <a href="../%E2%91%A3%20%E5%9F%BA%E4%BA%8EMilvus%E5%BA%93%E7%9A%84%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F/%E6%95%B0%E6%8D%AE%E9%9B%86%E7%94%9F%E6%88%90%E4%B8%8E%E4%BC%98%E5%8C%96%28%E6%89%A9%E5%B1%95%E8%B5%84%E6%96%99%29.html" class="md-nav__link">
  312. <span class="md-ellipsis">
  313. 数据集生成与优化(扩展资料)
  314. </span>
  315. </a>
  316. </li>
  317. </ul>
  318. </nav>
  319. </li>
  320. <li class="md-nav__item md-nav__item--nested">
  321. <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6">
  322. <label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
  323. <span class="md-ellipsis">
  324. ⑤ RAG系统评估
  325. </span>
  326. <span class="md-nav__icon md-icon"></span>
  327. </label>
  328. <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
  329. <label class="md-nav__title" for="__nav_6">
  330. <span class="md-nav__icon md-icon"></span>
  331. ⑤ RAG系统评估
  332. </label>
  333. <ul class="md-nav__list" data-md-scrollfix>
  334. <li class="md-nav__item">
  335. <a href="../%E2%91%A4%20RAG%E7%B3%BB%E7%BB%9F%E8%AF%84%E4%BC%B0/5.1%20RAG%E7%B3%BB%E7%BB%9F%E8%AF%84%E4%BC%B0%E5%B7%A5%E5%85%B7.html" class="md-nav__link">
  336. <span class="md-ellipsis">
  337. 5.1 RAG系统评估工具
  338. </span>
  339. </a>
  340. </li>
  341. <li class="md-nav__item">
  342. <a href="../%E2%91%A4%20RAG%E7%B3%BB%E7%BB%9F%E8%AF%84%E4%BC%B0/5.2%20%E5%AE%9E%E7%8E%B0EnterpriseKB-RAG%E7%B3%BB%E7%BB%9F%E7%9A%84%E8%AF%84%E4%BC%B0.html" class="md-nav__link">
  343. <span class="md-ellipsis">
  344. 5.2 实现企业知识库RAG系统的评估
  345. </span>
  346. </a>
  347. </li>
  348. <li class="md-nav__item">
  349. <a href="../%E2%91%A4%20RAG%E7%B3%BB%E7%BB%9F%E8%AF%84%E4%BC%B0/5.3%20RAG%E8%AF%84%E4%BC%B0%E6%95%B0%E6%8D%AE%E9%9B%86%E7%9A%84%E6%9E%84%E9%80%A0%28%E6%89%A9%E5%B1%95%29.html" class="md-nav__link">
  350. <span class="md-ellipsis">
  351. 5.3 RAG评估数据集的构造(扩展)
  352. </span>
  353. </a>
  354. </li>
  355. </ul>
  356. </nav>
  357. </li>
  358. <li class="md-nav__item md-nav__item--nested">
  359. <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7">
  360. <label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
  361. <span class="md-ellipsis">
  362. ⑥ 融合Mysql的RAG系统
  363. </span>
  364. <span class="md-nav__icon md-icon"></span>
  365. </label>
  366. <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
  367. <label class="md-nav__title" for="__nav_7">
  368. <span class="md-nav__icon md-icon"></span>
  369. ⑥ 融合Mysql的RAG系统
  370. </label>
  371. <ul class="md-nav__list" data-md-scrollfix>
  372. <li class="md-nav__item">
  373. <a href="../%E2%91%A5%20%E8%9E%8D%E5%90%88Mysql%E7%9A%84RAG%E7%B3%BB%E7%BB%9F/6.1%20%E8%9E%8D%E5%90%88FQA%E5%92%8C%E7%9F%A5%E8%AF%86%E5%BA%93%E6%9F%A5%E8%AF%A2.html" class="md-nav__link">
  374. <span class="md-ellipsis">
  375. 6.1 融合FQA和知识库查询
  376. </span>
  377. </a>
  378. </li>
  379. <li class="md-nav__item">
  380. <a href="../%E2%91%A5%20%E8%9E%8D%E5%90%88Mysql%E7%9A%84RAG%E7%B3%BB%E7%BB%9F/6.2%20%E8%9E%8D%E5%90%88FAQ%20%E5%92%8C%E7%9F%A5%E8%AF%86%E5%BA%93%E6%9F%A5%E8%AF%A2%EF%BC%88%E4%BC%98%E5%8C%96%E7%89%88%EF%BC%89.html" class="md-nav__link">
  381. <span class="md-ellipsis">
  382. 6.2 融合FAQ 和知识库查询(优化版)
  383. </span>
  384. </a>
  385. </li>
  386. <li class="md-nav__item">
  387. <a href="../%E2%91%A5%20%E8%9E%8D%E5%90%88Mysql%E7%9A%84RAG%E7%B3%BB%E7%BB%9F/6.3%20%E5%9F%BA%E4%BA%8E%20FastAPI%20%E7%9A%84%20FAQ%20%E4%B8%8E%E7%9F%A5%E8%AF%86%E5%BA%93%E6%9F%A5%E8%AF%A2%E6%8E%A5%E5%8F%A3.html" class="md-nav__link">
  388. <span class="md-ellipsis">
  389. 6.3 基于 FastAPI 的 FAQ 与知识库查询接口
  390. </span>
  391. </a>
  392. </li>
  393. <li class="md-nav__item">
  394. <a href="../%E2%91%A5%20%E8%9E%8D%E5%90%88Mysql%E7%9A%84RAG%E7%B3%BB%E7%BB%9F/6.4%20FastAPI%E5%92%8CFlask%E7%9A%84%E5%8C%BA%E5%88%AB%E5%92%8C%E8%81%94%E7%B3%BB%28%E6%89%A9%E5%B1%95%E8%B5%84%E6%96%99%29.html" class="md-nav__link">
  395. <span class="md-ellipsis">
  396. 6.4 FastAPI和Flask的区别和联系(扩展资料)
  397. </span>
  398. </a>
  399. </li>
  400. </ul>
  401. </nav>
  402. </li>
  403. <li class="md-nav__item md-nav__item--nested">
  404. <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8">
  405. <label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="0">
  406. <span class="md-ellipsis">
  407. ⑦ 企业级生产环境部署
  408. </span>
  409. <span class="md-nav__icon md-icon"></span>
  410. </label>
  411. <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="false">
  412. <label class="md-nav__title" for="__nav_8">
  413. <span class="md-nav__icon md-icon"></span>
  414. ⑦ 企业级生产环境部署
  415. </label>
  416. <ul class="md-nav__list" data-md-scrollfix>
  417. <li class="md-nav__item">
  418. <a href="../%E2%91%A6%20%E4%BC%81%E4%B8%9A%E7%BA%A7%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/7.1%20Docker%E7%9A%84%E5%8E%9F%E7%90%86%E5%92%8C%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8.html" class="md-nav__link">
  419. <span class="md-ellipsis">
  420. 7.1 Docker的原理和基本使用
  421. </span>
  422. </a>
  423. </li>
  424. <li class="md-nav__item">
  425. <a href="../%E2%91%A6%20%E4%BC%81%E4%B8%9A%E7%BA%A7%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/7.2%20%E6%9C%8D%E5%8A%A1%E9%83%A8%E7%BD%B2.html" class="md-nav__link">
  426. <span class="md-ellipsis">
  427. 7.2 服务部署
  428. </span>
  429. </a>
  430. </li>
  431. </ul>
  432. </nav>
  433. </li>
  434. </ul>
  435. </nav>
  436. </div>
  437. </div>
  438. </div>
  439. <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
  440. <div class="md-sidebar__scrollwrap">
  441. <div class="md-sidebar__inner">
  442. <nav class="md-nav md-nav--secondary" aria-label="目录">
  443. <label class="md-nav__title" for="__toc">
  444. <span class="md-nav__icon md-icon"></span>
  445. 目录
  446. </label>
  447. <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
  448. <li class="md-nav__item">
  449. <a href="#_1" class="md-nav__link">
  450. <span class="md-ellipsis">
  451. 学习目标
  452. </span>
  453. </a>
  454. </li>
  455. <li class="md-nav__item">
  456. <a href="#_2" class="md-nav__link">
  457. <span class="md-ellipsis">
  458. 一、简述
  459. </span>
  460. </a>
  461. <nav class="md-nav" aria-label="一、简述">
  462. <ul class="md-nav__list">
  463. <li class="md-nav__item">
  464. <a href="#1-langchain" class="md-nav__link">
  465. <span class="md-ellipsis">
  466. 1 什么是LangChain
  467. </span>
  468. </a>
  469. </li>
  470. <li class="md-nav__item">
  471. <a href="#2" class="md-nav__link">
  472. <span class="md-ellipsis">
  473. 2 主要组件
  474. </span>
  475. </a>
  476. </li>
  477. <li class="md-nav__item">
  478. <a href="#3-langchain" class="md-nav__link">
  479. <span class="md-ellipsis">
  480. 3 LangChain核心包
  481. </span>
  482. </a>
  483. </li>
  484. <li class="md-nav__item">
  485. <a href="#4" class="md-nav__link">
  486. <span class="md-ellipsis">
  487. 4 环境准备
  488. </span>
  489. </a>
  490. </li>
  491. </ul>
  492. </nav>
  493. </li>
  494. <li class="md-nav__item">
  495. <a href="#models" class="md-nav__link">
  496. <span class="md-ellipsis">
  497. 二、Models
  498. </span>
  499. </a>
  500. <nav class="md-nav" aria-label="二、Models">
  501. <ul class="md-nav__list">
  502. <li class="md-nav__item">
  503. <a href="#1-llms" class="md-nav__link">
  504. <span class="md-ellipsis">
  505. 1 LLMs
  506. </span>
  507. </a>
  508. </li>
  509. <li class="md-nav__item">
  510. <a href="#2-chat-models" class="md-nav__link">
  511. <span class="md-ellipsis">
  512. 2 Chat Models
  513. </span>
  514. </a>
  515. </li>
  516. <li class="md-nav__item">
  517. <a href="#3-embeddings-models" class="md-nav__link">
  518. <span class="md-ellipsis">
  519. 3 Embeddings Models
  520. </span>
  521. </a>
  522. </li>
  523. </ul>
  524. </nav>
  525. </li>
  526. <li class="md-nav__item">
  527. <a href="#prompts" class="md-nav__link">
  528. <span class="md-ellipsis">
  529. 三、Prompts
  530. </span>
  531. </a>
  532. <nav class="md-nav" aria-label="三、Prompts">
  533. <ul class="md-nav__list">
  534. <li class="md-nav__item">
  535. <a href="#1-prompt" class="md-nav__link">
  536. <span class="md-ellipsis">
  537. 1 通用prompt
  538. </span>
  539. </a>
  540. </li>
  541. <li class="md-nav__item">
  542. <a href="#2-chatprompts" class="md-nav__link">
  543. <span class="md-ellipsis">
  544. 2 ChatPrompts
  545. </span>
  546. </a>
  547. </li>
  548. </ul>
  549. </nav>
  550. </li>
  551. <li class="md-nav__item">
  552. <a href="#chains" class="md-nav__link">
  553. <span class="md-ellipsis">
  554. 四、Chains
  555. </span>
  556. </a>
  557. </li>
  558. <li class="md-nav__item">
  559. <a href="#output_parsers" class="md-nav__link">
  560. <span class="md-ellipsis">
  561. 五、output_parsers
  562. </span>
  563. </a>
  564. <nav class="md-nav" aria-label="五、output_parsers">
  565. <ul class="md-nav__list">
  566. <li class="md-nav__item">
  567. <a href="#1" class="md-nav__link">
  568. <span class="md-ellipsis">
  569. 1 字符串解析器
  570. </span>
  571. </a>
  572. </li>
  573. <li class="md-nav__item">
  574. <a href="#2_1" class="md-nav__link">
  575. <span class="md-ellipsis">
  576. 2 列表解析器
  577. </span>
  578. </a>
  579. </li>
  580. <li class="md-nav__item">
  581. <a href="#3-json" class="md-nav__link">
  582. <span class="md-ellipsis">
  583. 3 JSON解析器
  584. </span>
  585. </a>
  586. </li>
  587. <li class="md-nav__item">
  588. <a href="#4-pydantic" class="md-nav__link">
  589. <span class="md-ellipsis">
  590. 4 Pydantic解析器
  591. </span>
  592. </a>
  593. </li>
  594. <li class="md-nav__item">
  595. <a href="#5" class="md-nav__link">
  596. <span class="md-ellipsis">
  597. 5 自定义解析器
  598. </span>
  599. </a>
  600. </li>
  601. </ul>
  602. </nav>
  603. </li>
  604. <li class="md-nav__item">
  605. <a href="#memory" class="md-nav__link">
  606. <span class="md-ellipsis">
  607. 六、Memory
  608. </span>
  609. </a>
  610. <nav class="md-nav" aria-label="六、Memory">
  611. <ul class="md-nav__list">
  612. <li class="md-nav__item">
  613. <a href="#1-short-term-memory" class="md-nav__link">
  614. <span class="md-ellipsis">
  615. 1 短期记忆(Short-term Memory)
  616. </span>
  617. </a>
  618. </li>
  619. <li class="md-nav__item">
  620. <a href="#2_2" class="md-nav__link">
  621. <span class="md-ellipsis">
  622. 2 长期记忆
  623. </span>
  624. </a>
  625. </li>
  626. </ul>
  627. </nav>
  628. </li>
  629. <li class="md-nav__item">
  630. <a href="#indexes" class="md-nav__link">
  631. <span class="md-ellipsis">
  632. 七、Indexes
  633. </span>
  634. </a>
  635. <nav class="md-nav" aria-label="七、Indexes">
  636. <ul class="md-nav__list">
  637. <li class="md-nav__item">
  638. <a href="#1_1" class="md-nav__link">
  639. <span class="md-ellipsis">
  640. 1 文档加载器
  641. </span>
  642. </a>
  643. </li>
  644. <li class="md-nav__item">
  645. <a href="#2_3" class="md-nav__link">
  646. <span class="md-ellipsis">
  647. 2 文档分割器
  648. </span>
  649. </a>
  650. </li>
  651. <li class="md-nav__item">
  652. <a href="#3-vectorstores" class="md-nav__link">
  653. <span class="md-ellipsis">
  654. 3 VectorStores
  655. </span>
  656. </a>
  657. </li>
  658. <li class="md-nav__item">
  659. <a href="#4_1" class="md-nav__link">
  660. <span class="md-ellipsis">
  661. 4 检索器
  662. </span>
  663. </a>
  664. <nav class="md-nav" aria-label="4 检索器">
  665. <ul class="md-nav__list">
  666. <li class="md-nav__item">
  667. <a href="#41-langchain" class="md-nav__link">
  668. <span class="md-ellipsis">
  669. 4.1 LangChain的检索器定义
  670. </span>
  671. </a>
  672. </li>
  673. <li class="md-nav__item">
  674. <a href="#42" class="md-nav__link">
  675. <span class="md-ellipsis">
  676. 4.2 检索器的工作原理
  677. </span>
  678. </a>
  679. </li>
  680. <li class="md-nav__item">
  681. <a href="#43" class="md-nav__link">
  682. <span class="md-ellipsis">
  683. 4.3 检索器类型
  684. </span>
  685. </a>
  686. </li>
  687. <li class="md-nav__item">
  688. <a href="#44" class="md-nav__link">
  689. <span class="md-ellipsis">
  690. 4.4 拓展
  691. </span>
  692. </a>
  693. </li>
  694. </ul>
  695. </nav>
  696. </li>
  697. </ul>
  698. </nav>
  699. </li>
  700. <li class="md-nav__item">
  701. <a href="#agents" class="md-nav__link">
  702. <span class="md-ellipsis">
  703. 八、Agents
  704. </span>
  705. </a>
  706. <nav class="md-nav" aria-label="八、Agents">
  707. <ul class="md-nav__list">
  708. <li class="md-nav__item">
  709. <a href="#1-agent" class="md-nav__link">
  710. <span class="md-ellipsis">
  711. 1 Agent 概念
  712. </span>
  713. </a>
  714. </li>
  715. <li class="md-nav__item">
  716. <a href="#2-agent" class="md-nav__link">
  717. <span class="md-ellipsis">
  718. 2 Agent关键组成部分
  719. </span>
  720. </a>
  721. </li>
  722. <li class="md-nav__item">
  723. <a href="#3-langchainagent" class="md-nav__link">
  724. <span class="md-ellipsis">
  725. 3 langchain实现Agent
  726. </span>
  727. </a>
  728. </li>
  729. </ul>
  730. </nav>
  731. </li>
  732. <li class="md-nav__item">
  733. <a href="#langchain" class="md-nav__link">
  734. <span class="md-ellipsis">
  735. 九、LangChain使用场景
  736. </span>
  737. </a>
  738. </li>
  739. <li class="md-nav__item">
  740. <a href="#_3" class="md-nav__link">
  741. <span class="md-ellipsis">
  742. 十、本节小结
  743. </span>
  744. </a>
  745. </li>
  746. <li class="md-nav__item">
  747. <a href="#_4" class="md-nav__link">
  748. <span class="md-ellipsis">
  749. 十一、本节作业
  750. </span>
  751. </a>
  752. <nav class="md-nav" aria-label="十一、本节作业">
  753. <ul class="md-nav__list">
  754. <li class="md-nav__item">
  755. <a href="#1-1" class="md-nav__link">
  756. <span class="md-ellipsis">
  757. 1 作业1
  758. </span>
  759. </a>
  760. </li>
  761. <li class="md-nav__item">
  762. <a href="#2-2" class="md-nav__link">
  763. <span class="md-ellipsis">
  764. 2 作业2
  765. </span>
  766. </a>
  767. </li>
  768. </ul>
  769. </nav>
  770. </li>
  771. </ul>
  772. </nav>
  773. </div>
  774. </div>
  775. </div>
  776. <div class="md-content" data-md-component="content">
  777. <article class="md-content__inner md-typeset">
  778. <h1>2.2 LangChain基础知识.md</h1>
  779. <h2 id="_1">学习目标<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
  780. <ul>
  781. <li>熟悉什么是LangChain及其作用</li>
  782. <li>熟悉LangChain中基本组件及使用</li>
  783. </ul>
  784. <h2 id="_2">一、简述<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
  785. <h3 id="1-langchain">1 什么是LangChain<a class="headerlink" href="#1-langchain" title="Permanent link">¶</a></h3>
  786. <p>LangChain由 Harrison Chase 创建于2022年10月,它是围绕LLMs(大语言模型)建立的一个框架,它的核心理念是为各种LLMs实现通用的接口,把LLMs相关的组件“链接”在一起,简化LLMs应用的开发难度,方便开发者快速地开发复杂的LLMs应用。</p>
  787. <blockquote>
  788. <p>LangChain 最初是于 2022 年 10 月开源的一个项目,在 GitHub 上获得大量关注之后迅速转变为一家初创公司。2017 年 Harrison Chase 还在哈佛上大学,如今已是硅谷的一家热门初创公司的 CEO,这对他来说是一次重大而迅速的跃迁。Insider 独家报道,人工智能初创公司 LangChain 在种子轮一周后,再次获得红杉领投的 2000 万至 2500 万美元融资,估值达到 2 亿美元。</p>
  789. </blockquote>
  790. <p><strong>LangChain官网</strong>:<a href="https://python.langchain.com/docs/introduction/">https://python.langchain.com/docs/introduction/</a></p>
  791. <p><strong>LangChain官网中文版</strong>:<a href="https://www.langchain.com.cn/">https://www.langchain.com.cn/</a></p>
  792. <p>LangChain 简化了 LLM 应用程序生命周期的每个阶段:</p>
  793. <ul>
  794. <li>开发:使用 LangChain 的开源组件和第三方集成构建应用程序。使用 LangGraph 构建具有一流流式和人机交互支持的状态智能体。</li>
  795. <li>生产化:使用 LangSmith 检查、监控和评估应用程序,方便持续优化和部署。</li>
  796. <li>部署:使用 LangGraph平台 将应用程序转变为可用于生产的 API 和助手。</li>
  797. </ul>
  798. <h3 id="2">2 主要组件<a class="headerlink" href="#2" title="Permanent link">¶</a></h3>
  799. <p><img alt="image-20250703152303288" src="assets/image-20250703152303288.png"></p>
  800. <ul>
  801. <li>Models:模型,各种类型的模型和模型集成,比如GPT-4</li>
  802. <li>Prompts:提示,包括提示管理、提示优化和提示序列化</li>
  803. <li>Chains:链,一系列对各种组件的调用</li>
  804. <li>Memory:记忆,用来保存和模型交互时的上下文状态</li>
  805. <li>Indexes:索引,用来结构化文档,以便和模型交互</li>
  806. <li>Agents:代理,决定模型采取哪些行动,执行并且观察流程,直到完成为止</li>
  807. </ul>
  808. <h3 id="3-langchain">3 LangChain核心包<a class="headerlink" href="#3-langchain" title="Permanent link">¶</a></h3>
  809. <ul>
  810. <li><strong>langchain-core</strong>:聊天模型和其他组件的基础抽象。</li>
  811. <li>
  812. <p><strong>集成包(例如 langchain-openai、langchain-anthropic 等)</strong>:重要的集成被拆分为轻量级的独立包,由 LangChain 团队和集成方共同维护。</p>
  813. </li>
  814. <li>
  815. <p><strong>langchain</strong>:包含链(chains)、智能体(agents)和检索策略,这些构成了应用的认知架构。</p>
  816. </li>
  817. <li>
  818. <p><strong>langchain-community</strong>:由社区维护的第三方集成。</p>
  819. </li>
  820. <li>
  821. <p><strong>langgraph</strong>:一个编排框架,用于将 LangChain 组件组合成可用于生产的应用,支持持久化、流式处理及其他关键特性。</p>
  822. </li>
  823. </ul>
  824. <h3 id="4">4 环境准备<a class="headerlink" href="#4" title="Permanent link">¶</a></h3>
  825. <p>本知识文档以LangChain+Qwen进行学习,需要提前安装</p>
  826. <blockquote>
  827. <p>pip install openai</p>
  828. <p>pip install langchain </p>
  829. <p>pip install modelscope</p>
  830. </blockquote>
  831. <p>借助阿里云-百炼平台(需要申请API Key 以及Secret Key):</p>
  832. <blockquote>
  833. <p><a href="https://bailian.console.aliyun.com/#/home">https://bailian.console.aliyun.com/#/home</a></p>
  834. </blockquote>
  835. <h2 id="models">二、Models<a class="headerlink" href="#models" title="Permanent link">¶</a></h2>
  836. <p>现在市面上的模型多如牛毛,各种各样的模型不断出现,LangChain模型组件提供了与各种模型的集成,并为所有模型提供一个精简的统一接口。</p>
  837. <p>LangChain目前支持三种类型的模型:LLMs、Chat Models(聊天模型)、Embeddings Models(嵌入模型)。</p>
  838. <ul>
  839. <li>LLMs:大语言模型接收文本字符作为输入,返回的也是文本字符。</li>
  840. <li>聊天模型:基于LLMs, 不同的是它接收聊天消(一种特定格式的数据)作为输入,返回的也是聊天消息。</li>
  841. <li>文本嵌入模型:文本嵌入模型接收文本作为输入, 返回的是浮点数列表。</li>
  842. </ul>
  843. <p><img alt="image-20250704171332127" src="assets/image-20250704171332127.png"></p>
  844. <p>LangChain支持的三类模型,它们的使用场景不同,输入和输出不同,开发者需要根据项目需要选择相应的模型。</p>
  845. <h3 id="1-llms">1 LLMs<a class="headerlink" href="#1-llms" title="Permanent link">¶</a></h3>
  846. <p>LLMs(大语言模型)使用场景最多,常用大模型的下载库:</p>
  847. <blockquote>
  848. <p><a href="https://huggingface.co/models">https://huggingface.co/models</a></p>
  849. <p><a href="https://modelscope.cn/models">https://modelscope.cn/models</a></p>
  850. </blockquote>
  851. <p>下面Qwen为例进行讲解。</p>
  852. <hr>
  853. <p>模型调用有2种方式:</p>
  854. <ul>
  855. <li>通过ChatOpenAI进行调用</li>
  856. </ul>
  857. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_openai</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatOpenAI</span>
  858. <span class="kn">import</span><span class="w"> </span><span class="nn">os</span>
  859. <span class="c1"># 实例化模型</span>
  860. <span class="n">model</span> <span class="o">=</span> <span class="n">ChatOpenAI</span><span class="p">(</span>
  861. <span class="n">base_url</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'base_url'</span><span class="p">,</span><span class="s1">'https://dashscope.aliyuncs.com/compatible-mode/v1'</span><span class="p">),</span>
  862. <span class="n">model</span><span class="o">=</span><span class="s1">'qwen-plus'</span><span class="p">,</span>
  863. <span class="n">openai_api_key</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'api_key'</span><span class="p">,</span><span class="s1">'sk-XXXXXX'</span><span class="p">),</span>
  864. <span class="n">max_tokens</span><span class="o">=</span><span class="mi">1000</span><span class="p">,</span>
  865. <span class="n">temperature</span><span class="o">=</span><span class="mi">0</span>
  866. <span class="p">)</span>
  867. <span class="c1"># 获取问答结果</span>
  868. <span class="n">result</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="s2">"帮我讲个笑话吧"</span><span class="p">)</span>
  869. <span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
  870. </code></pre></div>
  871. <ul>
  872. <li>通过Ollama进行调用 <a href="https://ollama.com/">Ollama支持模型</a></li>
  873. </ul>
  874. <div class="highlight"><pre><span></span><code><span class="c1"># from langchain_community.llms import Ollama # Langchain 0.x版本使用</span>
  875. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  876. <span class="c1"># 实例化模型</span>
  877. <span class="c1"># model = Ollama(model="qwen2.5:7b") # Langchain 0.x版本使用</span>
  878. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  879. <span class="c1"># 获取问答结果</span>
  880. <span class="n">result</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="s2">"请给我讲个笑话吧"</span><span class="p">)</span>
  881. <span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
  882. </code></pre></div>
  883. <h3 id="2-chat-models">2 Chat Models<a class="headerlink" href="#2-chat-models" title="Permanent link">¶</a></h3>
  884. <p>聊天模型,聊天消息包含下面几种类型,使用时需要按照约定传入合适的值:</p>
  885. <ul>
  886. <li>
  887. <p><strong>AIMessage</strong>: 就是 AI 输出的消息,可以是针对问题的回答.</p>
  888. </li>
  889. <li>
  890. <p><strong>HumanMessage</strong>: 人类消息就是用户信息,由人给出的信息发送给LLMs的提示信息,比如“实现一个快速排序方法”.</p>
  891. </li>
  892. <li>
  893. <p><strong>SystemMessage</strong>: 可以用于指定模型具体所处的环境和背景,如角色扮演等。你可以在这里给出具体的指示,比如“作为一个代码专家”,或者“返回json格式”.</p>
  894. </li>
  895. <li>
  896. <p><strong>ChatMessage</strong>: Chat 消息可以接受任意角色的参数,但是在大多数时间,我们应该使用上面的三种类型.</p>
  897. </li>
  898. </ul>
  899. <p>LangChain支持大量的chat 模型,可以通过官网查询:</p>
  900. <blockquote>
  901. <p><a href="https://python.langchain.com/docs/integrations/chat/">https://python.langchain.com/docs/integrations/chat/</a></p>
  902. </blockquote>
  903. <p>也可以通过langchain源码查看</p>
  904. <p><img alt="image-20250704174858064" src="assets/image-20250704174858064.png"></p>
  905. <ul>
  906. <li>SystemMessage+HumanMessage+AIMessage</li>
  907. </ul>
  908. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.messages</span><span class="w"> </span><span class="kn">import</span> <span class="n">HumanMessage</span><span class="p">,</span> <span class="n">SystemMessage</span><span class="p">,</span> <span class="n">AIMessage</span>
  909. <span class="c1"># from langchain_community.chat_models import ChatOllama # Langchain 0.x版本使用</span>
  910. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatOllama</span>
  911. <span class="c1"># 实例化模型</span>
  912. <span class="n">model</span> <span class="o">=</span> <span class="n">ChatOllama</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  913. <span class="c1"># 定义提示词</span>
  914. <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
  915. <span class="n">SystemMessage</span><span class="p">(</span><span class="n">content</span><span class="o">=</span><span class="s2">"现在你是一个著名的诗人"</span><span class="p">),</span>
  916. <span class="n">HumanMessage</span><span class="p">(</span><span class="n">content</span><span class="o">=</span><span class="s2">"给我写一首唐诗"</span><span class="p">)]</span>
  917. <span class="c1"># 获取问答结果</span>
  918. <span class="n">result</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
  919. <span class="c1"># print(result)</span>
  920. <span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
  921. </code></pre></div>
  922. <p><img src="assets/1762153476605.png" alt="image-20251004021532441" style="zoom:50%;"></p>
  923. <h3 id="3-embeddings-models">3 Embeddings Models<a class="headerlink" href="#3-embeddings-models" title="Permanent link">¶</a></h3>
  924. <p>Embeddings Models(嵌入模型)特点:将字符串作为输入,返回一个浮动数的列表。在NLP中,Embedding的作用就是将数据进行文本向量化。</p>
  925. <div align="center"><img src="assets/6-4.png" style="zoom:40%"><img></div>
  926. <p>Embeddings Models可以为文本创建向量映射,这样就能在向量空间里去考虑文本,执行诸如语义搜索之类的操作,比如说寻找相似的文本片段。</p>
  927. <blockquote>
  928. <p><a href="https://python.langchain.com/docs/integrations/text_embedding/">https://python.langchain.com/docs/integrations/text_embedding/</a></p>
  929. </blockquote>
  930. <hr>
  931. <p>不同的Embedding模型对多语言支持和文本类型有不同的特点:</p>
  932. <ul>
  933. <li><strong>多语言支持</strong>:<ul>
  934. <li><code>text-embedding-ada-002</code>:支持多种语言,但对中文等亚洲语言的支持相对较弱</li>
  935. <li><code>bge-large-zh</code>:对中文有很好的支持</li>
  936. <li><code>multilingual-e5-large</code>:对多语言都有较好的支持</li>
  937. <li>mxbai-embed-large:</li>
  938. </ul>
  939. </li>
  940. <li><strong>文本类型适用性</strong>:<ul>
  941. <li>代码文本:建议使用专门的代码Embedding模型,如 <code>CodeBERT</code></li>
  942. <li>通用文本:可以使用<code>text-embedding-ada-002</code>或 <code>bge-large-zh</code></li>
  943. <li>专业领域文本:建议使用该领域的专门模型</li>
  944. </ul>
  945. </li>
  946. </ul>
  947. <p>可以参考MTEB(大规模文本嵌入基准)排行榜以获取最新模型效果:<a href="https://huggingface.co/spaces/mteb/leaderboard">https://huggingface.co/spaces/mteb/leaderboard</a></p>
  948. <p>接下来以一个文本嵌入模型的例子进行说明:</p>
  949. <div class="highlight"><pre><span></span><code><span class="c1"># from langchain_community.embeddings import OllamaEmbeddings # Langchain 0.x版本使用</span>
  950. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaEmbeddings</span>
  951. <span class="c1"># 初始化Ollama嵌入模型,使用mxbai-embed-large模型,温度设置为0</span>
  952. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaEmbeddings</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"mxbai-embed-large"</span><span class="p">,</span> <span class="n">temperature</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
  953. <span class="c1"># 对单个查询文本进行嵌入编码</span>
  954. <span class="n">res1</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">embed_query</span><span class="p">(</span><span class="s1">'这是第一个测试文档'</span><span class="p">)</span>
  955. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'result1-&gt;</span><span class="si">{</span><span class="n">res1</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  956. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'result1的长度-&gt;</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">res1</span><span class="p">)</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  957. <span class="c1"># 对多个文档进行批量嵌入编码</span>
  958. <span class="n">res2</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">embed_documents</span><span class="p">([</span><span class="s1">'这是第一个测试文档'</span><span class="p">,</span> <span class="s1">'这是第二个测试文档'</span><span class="p">])</span>
  959. <span class="nb">print</span><span class="p">(</span><span class="n">res2</span><span class="p">)</span>
  960. </code></pre></div>
  961. <p>运行结果:</p>
  962. <p><img alt="1762164216432" src="assets/1762164216432.png"></p>
  963. <h2 id="prompts">三、Prompts<a class="headerlink" href="#prompts" title="Permanent link">¶</a></h2>
  964. <h3 id="1-prompt">1 通用prompt<a class="headerlink" href="#1-prompt" title="Permanent link">¶</a></h3>
  965. <p>Prompt是指当用户输入信息给模型时加入的提示,这个提示的形式可以是zero-shot或者few-shot等方式,目的是让模型理解更为复杂的业务场景以便更好的解决问题。</p>
  966. <p>提示模板:如果你有了一个起作用的提示,你可能想把它作为一个模板用于解决其他问题,LangChain就提供了PromptTemplates组件,它可以帮助你更方便的构建提示。</p>
  967. <ul>
  968. <li><strong>zero-shot提示方式</strong></li>
  969. </ul>
  970. <div class="highlight"><pre><span></span><code><span class="c1"># from langchain import PromptTemplate # Langchain 0.x版本使用</span>
  971. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">PromptTemplate</span>
  972. <span class="c1"># from langchain_community.llms import Ollama # Langchain 0.x版本使用</span>
  973. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  974. <span class="c1"># model = Ollama(model="qwen2.5:7b") # Langchain 0.x版本使用</span>
  975. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  976. <span class="c1"># 定义模板</span>
  977. <span class="n">template</span> <span class="o">=</span> <span class="s2">"我的邻居姓</span><span class="si">{lastname}</span><span class="s2">,他生了个儿子,给他儿子起个名字"</span>
  978. <span class="n">prompt</span> <span class="o">=</span> <span class="n">PromptTemplate</span><span class="p">(</span>
  979. <span class="n">input_variables</span><span class="o">=</span><span class="p">[</span><span class="s2">"lastname"</span><span class="p">],</span>
  980. <span class="n">template</span><span class="o">=</span><span class="n">template</span><span class="p">)</span>
  981. <span class="n">prompt_text</span> <span class="o">=</span> <span class="n">prompt</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">lastname</span><span class="o">=</span><span class="s2">"王"</span><span class="p">)</span>
  982. <span class="nb">print</span><span class="p">(</span><span class="n">prompt_text</span><span class="p">)</span>
  983. <span class="c1"># result: 我的邻居姓王,他生了个儿子,给他儿子起个名字</span>
  984. <span class="n">result</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="n">prompt_text</span><span class="p">)</span>
  985. <span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
  986. </code></pre></div>
  987. <p>运行结果:</p>
  988. <p><img alt="image-20251002154154332" src="assets/image-20251002154154332.png"></p>
  989. <ul>
  990. <li><strong>few-shot提示方式</strong></li>
  991. </ul>
  992. <div class="highlight"><pre><span></span><code><span class="c1"># from langchain import PromptTemplate, FewShotPromptTemplate # Langchain 0.x版本使用</span>
  993. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">PromptTemplate</span><span class="p">,</span> <span class="n">FewShotPromptTemplate</span>
  994. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  995. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  996. <span class="n">examples</span> <span class="o">=</span> <span class="p">[</span>
  997. <span class="p">{</span><span class="s2">"word"</span><span class="p">:</span> <span class="s2">"开心"</span><span class="p">,</span> <span class="s2">"antonym"</span><span class="p">:</span> <span class="s2">"难过"</span><span class="p">},</span>
  998. <span class="p">{</span><span class="s2">"word"</span><span class="p">:</span> <span class="s2">"高"</span><span class="p">,</span> <span class="s2">"antonym"</span><span class="p">:</span> <span class="s2">"矮"</span><span class="p">}]</span>
  999. <span class="n">example_template</span> <span class="o">=</span> <span class="s2">"""</span>
  1000. <span class="s2">单词: </span><span class="si">{word}</span>
  1001. <span class="s2">反义词: </span><span class="si">{antonym}</span><span class="se">\\</span><span class="s2">n</span>
  1002. <span class="s2">"""</span>
  1003. <span class="n">example_prompt</span> <span class="o">=</span> <span class="n">PromptTemplate</span><span class="p">(</span>
  1004. <span class="n">input_variables</span><span class="o">=</span><span class="p">[</span><span class="s2">"word"</span><span class="p">,</span> <span class="s2">"antonym"</span><span class="p">],</span>
  1005. <span class="n">template</span><span class="o">=</span><span class="n">example_template</span><span class="p">,</span>
  1006. <span class="p">)</span>
  1007. <span class="n">few_shot_prompt</span> <span class="o">=</span> <span class="n">FewShotPromptTemplate</span><span class="p">(</span>
  1008. <span class="n">examples</span><span class="o">=</span><span class="n">examples</span><span class="p">,</span>
  1009. <span class="n">example_prompt</span><span class="o">=</span><span class="n">example_prompt</span><span class="p">,</span>
  1010. <span class="n">prefix</span><span class="o">=</span><span class="s2">"给出每个单词的反义词"</span><span class="p">,</span>
  1011. <span class="n">suffix</span><span class="o">=</span><span class="s2">"单词: </span><span class="si">{input}</span><span class="se">\\</span><span class="s2">n反义词:"</span><span class="p">,</span>
  1012. <span class="n">input_variables</span><span class="o">=</span><span class="p">[</span><span class="s2">"input"</span><span class="p">],</span>
  1013. <span class="n">example_separator</span><span class="o">=</span><span class="s2">"</span><span class="se">\\</span><span class="s2">n"</span><span class="p">,</span>
  1014. <span class="p">)</span>
  1015. <span class="n">prompt_text</span> <span class="o">=</span> <span class="n">few_shot_prompt</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">input</span><span class="o">=</span><span class="s2">"粗"</span><span class="p">)</span>
  1016. <span class="nb">print</span><span class="p">(</span><span class="n">model</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="n">prompt_text</span><span class="p">))</span>
  1017. <span class="c1"># 细</span>
  1018. </code></pre></div>
  1019. <p>运行结果:</p>
  1020. <p><img src="assets/image-20251002152859092.png" alt="image-20251002152859092" style="zoom:67%;"></p>
  1021. <h3 id="2-chatprompts">2 ChatPrompts<a class="headerlink" href="#2-chatprompts" title="Permanent link">¶</a></h3>
  1022. <p>适合交互式对话应用,如聊天机器人、智能客服等,这些应用需要处理用户和LLM之间的多轮对话。</p>
  1023. <blockquote>
  1024. <p>ChatPromptTemplate</p>
  1025. <p>SystemMessagePromptTemplate</p>
  1026. <p>HumanMessagePromptTemplate</p>
  1027. <p>history=[("system","......"),('human',"......"),("ai","......")]</p>
  1028. </blockquote>
  1029. <ul>
  1030. <li><strong>直接提问</strong></li>
  1031. </ul>
  1032. <p>提示模板就是把一些常见的提示整理成模板,用户只需要修改模板中特定的词语,就能快速准确地告诉模型自己的需求。我们看个例子:</p>
  1033. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatPromptTemplate</span>
  1034. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1035. <span class="c1"># 实例化模型</span>
  1036. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1037. <span class="c1"># 定义提示词模版</span>
  1038. <span class="n">template_str</span> <span class="o">=</span> <span class="s2">"帮我讲个关于</span><span class="si">{name}</span><span class="s2">笑话吧"</span>
  1039. <span class="n">prompt_template</span> <span class="o">=</span> <span class="n">ChatPromptTemplate</span><span class="o">.</span><span class="n">from_template</span><span class="p">(</span><span class="n">template_str</span><span class="p">)</span>
  1040. <span class="n">prompt</span> <span class="o">=</span> <span class="n">prompt_template</span><span class="o">.</span><span class="n">format_messages</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">"气球"</span><span class="p">)</span>
  1041. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'prompt--&gt;</span><span class="si">{</span><span class="n">prompt</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1042. <span class="c1"># 调用模型</span>
  1043. <span class="n">result</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="n">prompt</span><span class="p">)</span>
  1044. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'result--&gt;</span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1045. </code></pre></div>
  1046. <p>运行结果:</p>
  1047. <p><img src="assets/image-20251002153543943.png" alt="image-20251002153543943" style="zoom:67%;"></p>
  1048. <ul>
  1049. <li><strong>zero-shot提示方式</strong></li>
  1050. </ul>
  1051. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatPromptTemplate</span><span class="p">,</span> <span class="n">HumanMessagePromptTemplate</span>
  1052. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.messages</span><span class="w"> </span><span class="kn">import</span> <span class="n">SystemMessage</span>
  1053. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1054. <span class="c1"># 实例化模型</span>
  1055. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1056. <span class="c1"># 系统信息</span>
  1057. <span class="n">system_prompt</span> <span class="o">=</span> <span class="n">SystemMessage</span><span class="p">(</span><span class="s2">"你是取名专家。"</span><span class="p">)</span>
  1058. <span class="c1"># 用户信息模版</span>
  1059. <span class="n">human_str</span> <span class="o">=</span> <span class="s2">"我的邻居姓</span><span class="si">{lastname}</span><span class="s2">,他生了个儿子,给他儿子起个名字。"</span>
  1060. <span class="n">human_template</span> <span class="o">=</span> <span class="n">HumanMessagePromptTemplate</span><span class="o">.</span><span class="n">from_template</span><span class="p">(</span><span class="n">human_str</span><span class="p">)</span>
  1061. <span class="c1"># 组装</span>
  1062. <span class="n">chat_template</span> <span class="o">=</span> <span class="n">ChatPromptTemplate</span><span class="o">.</span><span class="n">from_messages</span><span class="p">([</span><span class="n">system_prompt</span><span class="p">,</span> <span class="n">human_template</span><span class="p">])</span>
  1063. <span class="c1"># 生成最终的提示词</span>
  1064. <span class="n">prompt</span> <span class="o">=</span> <span class="n">chat_template</span><span class="o">.</span><span class="n">format_messages</span><span class="p">(</span><span class="n">lastname</span><span class="o">=</span><span class="s2">"王"</span><span class="p">)</span>
  1065. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'prompt--&gt;</span><span class="si">{</span><span class="n">prompt</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1066. <span class="c1"># 调用模型</span>
  1067. <span class="n">result</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="n">prompt</span><span class="p">)</span> <span class="c1"># 返回结果出了content外,还有元数据信息</span>
  1068. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'result--&gt;</span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1069. </code></pre></div>
  1070. <p>运行结果:</p>
  1071. <p><img alt="image-20251002200159523" src="assets/image-20251002200159523.png"></p>
  1072. <ul>
  1073. <li><strong>few-shot提示方式</strong></li>
  1074. </ul>
  1075. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatPromptTemplate</span><span class="p">,</span> <span class="n">MessagesPlaceholder</span>
  1076. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1077. <span class="c1"># 实例化模型</span>
  1078. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1079. <span class="c1"># 创建 prompt 模版</span>
  1080. <span class="n">prompt_template</span> <span class="o">=</span> <span class="n">ChatPromptTemplate</span><span class="o">.</span><span class="n">from_messages</span><span class="p">(</span>
  1081. <span class="p">[</span>
  1082. <span class="p">(</span><span class="s2">"system"</span><span class="p">,</span> <span class="s2">"给出每个单词的反义词"</span><span class="p">),</span>
  1083. <span class="n">MessagesPlaceholder</span><span class="p">(</span><span class="s2">"history"</span><span class="p">),</span>
  1084. <span class="p">(</span><span class="s2">"human"</span><span class="p">,</span> <span class="s2">"</span><span class="si">{question}</span><span class="s2">"</span><span class="p">)</span>
  1085. <span class="p">]</span>
  1086. <span class="p">)</span>
  1087. <span class="c1"># 创建 few-shot prompt</span>
  1088. <span class="c1"># history = [</span>
  1089. <span class="c1"># HumanMessage(content="开心"),</span>
  1090. <span class="c1"># AIMessage(content="难过"),</span>
  1091. <span class="c1"># HumanMessage(content="高"),</span>
  1092. <span class="c1"># AIMessage(content="矮")</span>
  1093. <span class="c1"># ]</span>
  1094. <span class="n">history</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"human"</span><span class="p">,</span> <span class="s2">"开心"</span><span class="p">),</span> <span class="p">(</span><span class="s2">"ai"</span><span class="p">,</span> <span class="s2">"难过"</span><span class="p">),(</span><span class="s2">"human"</span><span class="p">,</span> <span class="s2">"高"</span><span class="p">),</span> <span class="p">(</span><span class="s2">"ai"</span><span class="p">,</span> <span class="s2">"矮"</span><span class="p">)]</span>
  1095. <span class="n">prompt</span> <span class="o">=</span> <span class="n">prompt_template</span><span class="o">.</span><span class="n">format_messages</span><span class="p">(</span><span class="n">history</span><span class="o">=</span><span class="n">history</span><span class="p">,</span> <span class="n">question</span><span class="o">=</span><span class="s2">"富有"</span><span class="p">)</span>
  1096. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"prompt--&gt;</span><span class="si">{</span><span class="n">prompt</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
  1097. <span class="c1"># 调用模型</span>
  1098. <span class="n">result</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="n">prompt</span><span class="p">)</span>
  1099. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'result--&gt;</span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1100. </code></pre></div>
  1101. <p>运行结果:</p>
  1102. <p><img alt="image-20251002205814344" src="assets/image-20251002205814344.png"></p>
  1103. <h2 id="chains">四、Chains<a class="headerlink" href="#chains" title="Permanent link">¶</a></h2>
  1104. <p>在LangChain中,Chains描述了将LLM与其他组件结合起来完成一个应用程序的过程。
  1105. 针对上一小节的提示模版例子,zero-shot里面,我们可以用链来连接提示模版组件和模型,进而可以实现代码的更改,主要使用LCEL方法。</p>
  1106. <p>LCEL(Lang Chain Expression Language) 是一种声明式的方法,用于轻松组合链条。</p>
  1107. <p>LCEL的基本语法规则是使用<code>|</code>符号将不同的组件连接起来,形成一个链式结构。<code>|</code>符号类似于Unix的管道操作符,它将一个组件的输出作为下一个组件的输入,从而实现数据的传递和处理。</p>
  1108. <p>上一个组件的输出作为下一个组件的输入,输出和输入的类型必须保持一致,否则不能连接。</p>
  1109. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain</span><span class="w"> </span><span class="kn">import</span> <span class="n">PromptTemplate</span>
  1110. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">PromptTemplate</span>
  1111. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1112. <span class="c1"># 定义模板</span>
  1113. <span class="n">template</span> <span class="o">=</span> <span class="s2">"我的邻居姓</span><span class="si">{lastname}</span><span class="s2">,他生了个儿子,给他儿子起个名字"</span>
  1114. <span class="n">prompt</span> <span class="o">=</span> <span class="n">PromptTemplate</span><span class="p">(</span>
  1115. <span class="n">input_variables</span><span class="o">=</span><span class="p">[</span><span class="s2">"lastname"</span><span class="p">],</span>
  1116. <span class="n">template</span><span class="o">=</span><span class="n">template</span><span class="p">)</span>
  1117. <span class="c1"># 实例化模型</span>
  1118. <span class="n">llm</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1119. <span class="n">chain</span> <span class="o">=</span> <span class="n">prompt</span> <span class="o">|</span> <span class="n">llm</span>
  1120. <span class="c1"># 执行链</span>
  1121. <span class="nb">print</span><span class="p">(</span><span class="n">chain</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="s2">"王"</span><span class="p">))</span>
  1122. </code></pre></div>
  1123. <p>如果你想将第一个模型输出的结果,直接作为第二个模型的输入,直接使用管道符, 代码如下:</p>
  1124. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">PromptTemplate</span>
  1125. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1126. <span class="c1"># 创建第一条链</span>
  1127. <span class="n">template</span> <span class="o">=</span> <span class="s2">"我的邻居姓</span><span class="si">{lastname}</span><span class="s2">,他生了个儿子,给他儿子起个名字"</span>
  1128. <span class="n">first_prompt</span> <span class="o">=</span> <span class="n">PromptTemplate</span><span class="p">(</span>
  1129. <span class="n">input_variables</span><span class="o">=</span><span class="p">[</span><span class="s2">"lastname"</span><span class="p">],</span>
  1130. <span class="n">template</span><span class="o">=</span><span class="n">template</span><span class="p">,)</span>
  1131. <span class="c1"># 实例化模型</span>
  1132. <span class="n">llm</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1133. <span class="n">first_chain</span> <span class="o">=</span> <span class="n">first_prompt</span> <span class="o">|</span> <span class="n">llm</span>
  1134. <span class="c1"># 创建第二条链</span>
  1135. <span class="n">second_prompt</span> <span class="o">=</span> <span class="n">PromptTemplate</span><span class="p">(</span>
  1136. <span class="n">input_variables</span><span class="o">=</span><span class="p">[</span><span class="s2">"child_name"</span><span class="p">],</span>
  1137. <span class="n">template</span><span class="o">=</span><span class="s2">"邻居的儿子名字叫</span><span class="si">{child_name}</span><span class="s2">,给他起一个小名"</span><span class="p">)</span>
  1138. <span class="n">second_chain</span> <span class="o">=</span> <span class="n">second_prompt</span> <span class="o">|</span> <span class="n">llm</span>
  1139. <span class="c1"># 链接两条链</span>
  1140. <span class="n">overall_chain</span> <span class="o">=</span> <span class="n">first_chain</span> <span class="o">|</span> <span class="n">second_chain</span>
  1141. <span class="nb">print</span><span class="p">(</span><span class="n">overall_chain</span><span class="p">)</span>
  1142. <span class="nb">print</span><span class="p">(</span><span class="s1">'*'</span><span class="o">*</span><span class="mi">80</span><span class="p">)</span>
  1143. <span class="c1"># 执行链,只需要传入第一个参数</span>
  1144. <span class="n">catchphrase</span> <span class="o">=</span> <span class="n">overall_chain</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="s2">"王"</span><span class="p">)</span>
  1145. <span class="nb">print</span><span class="p">(</span><span class="n">catchphrase</span><span class="p">)</span>
  1146. </code></pre></div>
  1147. <p>运行结果:</p>
  1148. <p><img alt="image-20251002212834547" src="assets/image-20251002212834547.png"></p>
  1149. <p><img alt="image-20251002212930745" src="assets/image-20251002212930745.png"></p>
  1150. <h2 id="output_parsers">五、output_parsers<a class="headerlink" href="#output_parsers" title="Permanent link">¶</a></h2>
  1151. <p>LLM 的输出是自然语言文本,但在应用开发中,我们经常需要将这些文本转换为结构化的数据格式,如列表、字典或对象。LangChain 输出解析器负责获取 LLM 的输出并将其转换为更合适的格式。</p>
  1152. <p>部分解析器如下:</p>
  1153. <table>
  1154. <thead>
  1155. <tr>
  1156. <th>解析器名称</th>
  1157. <th>核心功能</th>
  1158. <th>输出的 Python 类型</th>
  1159. <th>工业级应用场景</th>
  1160. </tr>
  1161. </thead>
  1162. <tbody>
  1163. <tr>
  1164. <td>StrOutputParser</td>
  1165. <td>默认解析器。将 LLM 的输出直接解析为字符串。</td>
  1166. <td>str</td>
  1167. <td>只需要原始回答时(如问答任务、对话场景)</td>
  1168. </tr>
  1169. <tr>
  1170. <td>CommaSeparatedListParser</td>
  1171. <td>将 LLM 输出的、用逗号分隔的文本解析为列表。</td>
  1172. <td>list[str]</td>
  1173. <td>列表/枚举型输出</td>
  1174. </tr>
  1175. <tr>
  1176. <td>JsonOutputParser</td>
  1177. <td>极其常用。将 LLM 输出的 JSON 字符串解析为 Python 字典。</td>
  1178. <td>dict</td>
  1179. <td>结构化 JSON 输出</td>
  1180. </tr>
  1181. <tr>
  1182. <td>PydanticOutputParser</td>
  1183. <td>极其常用。将 LLM 输出解析为预先定义的 Pydantic 对象,提供类型安全和数据验证。</td>
  1184. <td>自定义的 pydantic.BaseModel 对象</td>
  1185. <td>输出需要严格结构化(JSON-like)数据时</td>
  1186. </tr>
  1187. <tr>
  1188. <td>DatetimeOutputParser</td>
  1189. <td>从文本中智能地解析出日期和时间信息。</td>
  1190. <td>datetime.datetime</td>
  1191. <td>需要时间格式时</td>
  1192. </tr>
  1193. </tbody>
  1194. </table>
  1195. <h3 id="1">1 字符串解析器<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
  1196. <p>StrOutputParser,最简单的解析器,用于提取模型返回的原始文本:</p>
  1197. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.output_parsers</span><span class="w"> </span><span class="kn">import</span> <span class="n">StrOutputParser</span>
  1198. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatPromptTemplate</span>
  1199. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1200. <span class="c1"># 实例化模型</span>
  1201. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1202. <span class="c1"># 创建简单链</span>
  1203. <span class="n">prompt</span> <span class="o">=</span> <span class="n">ChatPromptTemplate</span><span class="o">.</span><span class="n">from_template</span><span class="p">(</span><span class="s2">"解释</span><span class="si">{topic}</span><span class="s2">是什么?回答控制20字以内"</span><span class="p">)</span>
  1204. <span class="n">chain1</span> <span class="o">=</span> <span class="n">prompt</span> <span class="o">|</span> <span class="n">model</span>
  1205. <span class="n">result1</span> <span class="o">=</span> <span class="n">chain1</span><span class="o">.</span><span class="n">invoke</span><span class="p">({</span><span class="s2">"topic"</span><span class="p">:</span> <span class="s2">"ai"</span><span class="p">})</span>
  1206. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"result1--&gt;</span><span class="si">{</span><span class="n">result1</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
  1207. <span class="c1"># 添加字符串解析器</span>
  1208. <span class="n">parser</span> <span class="o">=</span> <span class="n">StrOutputParser</span><span class="p">()</span>
  1209. <span class="n">chain2</span> <span class="o">=</span> <span class="n">prompt</span> <span class="o">|</span> <span class="n">model</span> <span class="o">|</span> <span class="n">parser</span>
  1210. <span class="n">result2</span> <span class="o">=</span> <span class="n">chain2</span><span class="o">.</span><span class="n">invoke</span><span class="p">({</span><span class="s2">"topic"</span><span class="p">:</span> <span class="s2">"ai"</span><span class="p">})</span>
  1211. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"result2--&gt;</span><span class="si">{</span><span class="n">result2</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
  1212. </code></pre></div>
  1213. <p>运行结果:</p>
  1214. <p><img alt="image-20251002230930266" src="assets/image-20251002230930266.png"></p>
  1215. <h3 id="2_1">2 列表解析器<a class="headerlink" href="#2_1" title="Permanent link">¶</a></h3>
  1216. <p>CommaSeparatedListOutputParser,将逗号分隔的文本转换为Python列表:</p>
  1217. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.output_parsers</span><span class="w"> </span><span class="kn">import</span> <span class="n">CommaSeparatedListOutputParser</span>
  1218. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatPromptTemplate</span>
  1219. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1220. <span class="c1"># 实例化模型</span>
  1221. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1222. <span class="c1"># 创建列表解析器</span>
  1223. <span class="n">parser</span> <span class="o">=</span> <span class="n">CommaSeparatedListOutputParser</span><span class="p">()</span>
  1224. <span class="c1"># 创建带格式说明的提示模板</span>
  1225. <span class="n">format_instructions</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">get_format_instructions</span><span class="p">()</span>
  1226. <span class="n">prompt</span> <span class="o">=</span> <span class="n">ChatPromptTemplate</span><span class="o">.</span><span class="n">from_template</span><span class="p">(</span>
  1227. <span class="s2">"用中文列出</span><span class="si">{topic}</span><span class="s2">的五个最重要特点。</span><span class="se">\n</span><span class="si">{format_instructions}</span><span class="s2">"</span>
  1228. <span class="p">)</span>
  1229. <span class="c1"># 组合组件</span>
  1230. <span class="n">chain</span> <span class="o">=</span> <span class="n">prompt</span> <span class="o">|</span> <span class="n">model</span> <span class="o">|</span> <span class="n">parser</span>
  1231. <span class="c1"># 调用链</span>
  1232. <span class="n">result</span> <span class="o">=</span> <span class="n">chain</span><span class="o">.</span><span class="n">invoke</span><span class="p">({</span>
  1233. <span class="s2">"topic"</span><span class="p">:</span> <span class="s2">"大模型"</span><span class="p">,</span>
  1234. <span class="s2">"format_instructions"</span><span class="p">:</span> <span class="n">format_instructions</span>
  1235. <span class="p">})</span>
  1236. <span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
  1237. </code></pre></div>
  1238. <p>运行结果:</p>
  1239. <p><img src="assets/image-20251002231200108.png" alt="image-20251002231200108" style="zoom: 67%;"></p>
  1240. <h3 id="3-json">3 JSON解析器<a class="headerlink" href="#3-json" title="Permanent link">¶</a></h3>
  1241. <p>JsonOutputParser,将JSON格式文本转换为Python字典或列表:</p>
  1242. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.output_parsers</span><span class="w"> </span><span class="kn">import</span> <span class="n">JsonOutputParser</span>
  1243. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatPromptTemplate</span>
  1244. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1245. <span class="c1"># 实例化模型</span>
  1246. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1247. <span class="c1"># 创建JSON解析器</span>
  1248. <span class="n">json_parser</span> <span class="o">=</span> <span class="n">JsonOutputParser</span><span class="p">()</span>
  1249. <span class="c1"># 创建带格式说明的提示模板</span>
  1250. <span class="n">json_format_instructions</span> <span class="o">=</span> <span class="n">json_parser</span><span class="o">.</span><span class="n">get_format_instructions</span><span class="p">()</span>
  1251. <span class="n">json_prompt</span> <span class="o">=</span> <span class="n">ChatPromptTemplate</span><span class="o">.</span><span class="n">from_template</span><span class="p">(</span>
  1252. <span class="s2">"生成一个包含</span><span class="si">{person}</span><span class="s2">基本信息的JSON。应包括姓名、职业、年龄和技能列表, 不要包含任何注释或额外说明。</span><span class="se">\n</span><span class="si">{format_instructions}</span><span class="s2">"</span>
  1253. <span class="p">)</span>
  1254. <span class="c1"># 组合组件</span>
  1255. <span class="n">json_chain</span> <span class="o">=</span> <span class="n">json_prompt</span> <span class="o">|</span> <span class="n">model</span> <span class="o">|</span> <span class="n">json_parser</span>
  1256. <span class="c1"># 调用链</span>
  1257. <span class="n">result</span> <span class="o">=</span> <span class="n">json_chain</span><span class="o">.</span><span class="n">invoke</span><span class="p">({</span>
  1258. <span class="s2">"person"</span><span class="p">:</span> <span class="s2">"雷军"</span><span class="p">,</span>
  1259. <span class="s2">"format_instructions"</span><span class="p">:</span> <span class="n">json_format_instructions</span>
  1260. <span class="p">})</span>
  1261. <span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
  1262. </code></pre></div>
  1263. <p>运行结果:</p>
  1264. <p><img alt="image-20251003000254030" src="assets/image-20251003000254030.png"></p>
  1265. <h3 id="4-pydantic">4 Pydantic解析器<a class="headerlink" href="#4-pydantic" title="Permanent link">¶</a></h3>
  1266. <p>PydanticOutputParser,使用Pydantic模型定义输出结构:</p>
  1267. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatPromptTemplate</span>
  1268. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.output_parsers</span><span class="w"> </span><span class="kn">import</span> <span class="n">PydanticOutputParser</span>
  1269. <span class="kn">from</span><span class="w"> </span><span class="nn">pydantic</span><span class="w"> </span><span class="kn">import</span> <span class="n">BaseModel</span><span class="p">,</span> <span class="n">Field</span>
  1270. <span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">List</span>
  1271. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1272. <span class="c1"># 实例化模型</span>
  1273. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1274. <span class="c1"># 定义Pydantic模型</span>
  1275. <span class="k">class</span><span class="w"> </span><span class="nc">Movie</span><span class="p">(</span><span class="n">BaseModel</span><span class="p">):</span>
  1276. <span class="n">title</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="n">Field</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">"电影标题"</span><span class="p">)</span>
  1277. <span class="n">director</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="n">Field</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">"导演姓名"</span><span class="p">)</span>
  1278. <span class="n">year</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="n">Field</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">"上映年份"</span><span class="p">)</span>
  1279. <span class="n">genre</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="n">Field</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">"电影类型"</span><span class="p">)</span>
  1280. <span class="n">rating</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="n">Field</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">"评分(1-10)"</span><span class="p">)</span>
  1281. <span class="c1"># 创建Pydantic解析器</span>
  1282. <span class="n">pydantic_parser</span> <span class="o">=</span> <span class="n">PydanticOutputParser</span><span class="p">(</span><span class="n">pydantic_object</span><span class="o">=</span><span class="n">Movie</span><span class="p">)</span>
  1283. <span class="c1"># 创建带格式说明的提示模板</span>
  1284. <span class="n">format_instructions</span> <span class="o">=</span> <span class="n">pydantic_parser</span><span class="o">.</span><span class="n">get_format_instructions</span><span class="p">()</span>
  1285. <span class="n">pydantic_prompt</span> <span class="o">=</span> <span class="n">ChatPromptTemplate</span><span class="o">.</span><span class="n">from_template</span><span class="p">(</span>
  1286. <span class="s2">"生成一部</span><span class="si">{genre}</span><span class="s2">电影的信息。</span><span class="se">\n</span><span class="si">{format_instructions}</span><span class="s2">"</span>
  1287. <span class="p">)</span>
  1288. <span class="c1"># 组合组件</span>
  1289. <span class="n">pydantic_chain</span> <span class="o">=</span> <span class="n">pydantic_prompt</span> <span class="o">|</span> <span class="n">model</span> <span class="o">|</span> <span class="n">pydantic_parser</span>
  1290. <span class="c1"># 调用链</span>
  1291. <span class="n">movie_data</span> <span class="o">=</span> <span class="n">pydantic_chain</span><span class="o">.</span><span class="n">invoke</span><span class="p">({</span>
  1292. <span class="s2">"genre"</span><span class="p">:</span> <span class="s2">"科幻"</span><span class="p">,</span>
  1293. <span class="s2">"format_instructions"</span><span class="p">:</span> <span class="n">format_instructions</span>
  1294. <span class="p">})</span>
  1295. <span class="nb">print</span><span class="p">(</span><span class="n">movie_data</span><span class="p">)</span>
  1296. </code></pre></div>
  1297. <p>运行结果:</p>
  1298. <p><img alt="image-20251003000720225" src="assets/image-20251003000720225.png"></p>
  1299. <h3 id="5">5 自定义解析器<a class="headerlink" href="#5" title="Permanent link">¶</a></h3>
  1300. <p>创建自定义输出解析器</p>
  1301. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.output_parsers</span><span class="w"> </span><span class="kn">import</span> <span class="n">BaseOutputParser</span>
  1302. <span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Dict</span><span class="p">,</span> <span class="n">Any</span>
  1303. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.prompts</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatPromptTemplate</span>
  1304. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1305. <span class="c1"># 实例化模型</span>
  1306. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1307. <span class="k">class</span><span class="w"> </span><span class="nc">CustomKeyValueParser</span><span class="p">(</span><span class="n">BaseOutputParser</span><span class="p">[</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]]):</span>
  1308. <span class="w"> </span><span class="sd">"""解析形如'key: value'的文本"""</span>
  1309. <span class="k">def</span><span class="w"> </span><span class="nf">parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]:</span>
  1310. <span class="w"> </span><span class="sd">"""从文本中解析键值对"""</span>
  1311. <span class="n">result</span> <span class="o">=</span> <span class="p">{}</span>
  1312. <span class="n">lines</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span>
  1313. <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">lines</span><span class="p">:</span>
  1314. <span class="k">if</span> <span class="s1">':'</span> <span class="ow">in</span> <span class="n">line</span><span class="p">:</span>
  1315. <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">':'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
  1316. <span class="n">result</span><span class="p">[</span><span class="n">key</span><span class="o">.</span><span class="n">strip</span><span class="p">()]</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
  1317. <span class="k">return</span> <span class="n">result</span>
  1318. <span class="k">def</span><span class="w"> </span><span class="nf">get_format_instructions</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
  1319. <span class="w"> </span><span class="sd">"""提供格式指导给模型"""</span>
  1320. <span class="k">return</span> <span class="s2">"""请以'键: 值'的格式返回信息,每行一个键值对。</span>
  1321. <span class="s2"> 例如:</span>
  1322. <span class="s2"> 名称: 爱因斯坦</span>
  1323. <span class="s2"> 职业: 物理学家</span>
  1324. <span class="s2"> 贡献: 相对论"""</span>
  1325. <span class="c1"># 使用自定义解析器</span>
  1326. <span class="n">custom_parser</span> <span class="o">=</span> <span class="n">CustomKeyValueParser</span><span class="p">()</span>
  1327. <span class="n">custom_prompt</span> <span class="o">=</span> <span class="n">ChatPromptTemplate</span><span class="o">.</span><span class="n">from_template</span><span class="p">(</span>
  1328. <span class="s2">"提供关于</span><span class="si">{person}</span><span class="s2">的基本信息。</span><span class="se">\n</span><span class="si">{format_instructions}</span><span class="s2">"</span>
  1329. <span class="p">)</span>
  1330. <span class="c1"># 组合组件</span>
  1331. <span class="n">custom_chain</span> <span class="o">=</span> <span class="n">custom_prompt</span> <span class="o">|</span> <span class="n">model</span> <span class="o">|</span> <span class="n">custom_parser</span>
  1332. <span class="c1"># 调用模型</span>
  1333. <span class="n">result</span> <span class="o">=</span> <span class="n">custom_chain</span><span class="o">.</span><span class="n">invoke</span><span class="p">({</span>
  1334. <span class="s2">"person"</span><span class="p">:</span> <span class="s2">"屠呦呦"</span><span class="p">,</span>
  1335. <span class="s2">"format_instructions"</span><span class="p">:</span> <span class="n">custom_parser</span><span class="o">.</span><span class="n">get_format_instructions</span><span class="p">()</span>
  1336. <span class="p">})</span>
  1337. <span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
  1338. </code></pre></div>
  1339. <p>运行结果:</p>
  1340. <p><img alt="image-20251003001007923" src="assets/image-20251003001007923.png"></p>
  1341. <h2 id="memory">六、Memory<a class="headerlink" href="#memory" title="Permanent link">¶</a></h2>
  1342. <p>大模型本身不具备上下文的概念,它并不保存上次交互的内容,ChatGPT之所以能够和人正常沟通对话,因为它进行了一层封装,将历史记录回传给了模型。</p>
  1343. <p>因此 LangChain 也提供了Memory组件, Memory分为两种类型: <strong>短期记忆和长期记忆</strong> 。短期记忆一般指单一会话时传递数据,长期记忆则是处理多个会话时获取和更新信息。</p>
  1344. <ul>
  1345. <li>使用 <strong>ChatMessageHistory</strong> 手动添加上下文</li>
  1346. </ul>
  1347. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_community.chat_message_histories</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatMessageHistory</span>
  1348. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.messages</span><span class="w"> </span><span class="kn">import</span> <span class="n">messages_to_dict</span><span class="p">,</span> <span class="n">messages_from_dict</span>
  1349. <span class="kn">import</span><span class="w"> </span><span class="nn">json</span>
  1350. <span class="c1"># 1.创建一个ChatMessageHistory对象,用来存储对话信息</span>
  1351. <span class="n">history</span> <span class="o">=</span> <span class="n">ChatMessageHistory</span><span class="p">()</span>
  1352. <span class="c1"># 添加用户消息</span>
  1353. <span class="n">history</span><span class="o">.</span><span class="n">add_user_message</span><span class="p">(</span><span class="s2">"在吗?"</span><span class="p">)</span>
  1354. <span class="c1"># 添加大模型消息</span>
  1355. <span class="n">history</span><span class="o">.</span><span class="n">add_ai_message</span><span class="p">(</span><span class="s2">"在"</span><span class="p">)</span>
  1356. <span class="c1"># 打印所有消息</span>
  1357. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'history.messages--&gt;</span><span class="si">{</span><span class="n">history</span><span class="o">.</span><span class="n">messages</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1358. <span class="c1"># 2.可以将history.messages中的信息保存到字典中,然后保存到数据库或者文件中,方便后续读取</span>
  1359. <span class="c1"># 2.1 messages_to_dict()方法将history.messages中的信息转换成字典</span>
  1360. <span class="n">dicts</span> <span class="o">=</span> <span class="n">messages_to_dict</span><span class="p">(</span><span class="n">history</span><span class="o">.</span><span class="n">messages</span><span class="p">)</span>
  1361. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'dicts--&gt;</span><span class="si">{</span><span class="n">dicts</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1362. <span class="c1"># 2.2 这里将dicts保存到文件中</span>
  1363. <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'history.json'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">'utf-8'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
  1364. <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">dicts</span><span class="p">,</span> <span class="n">indent</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">ensure_ascii</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span>
  1365. <span class="c1"># 3.从文件中读取出字典,然后将字典转换成消息</span>
  1366. <span class="c1"># 3.1 读取文件</span>
  1367. <span class="n">messages</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s1">'history.json'</span><span class="p">,</span> <span class="s1">'r'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">'utf-8'</span><span class="p">))</span>
  1368. <span class="c1"># 3.2 然后将字典转换成消息</span>
  1369. <span class="n">chat_messages</span> <span class="o">=</span> <span class="n">messages_from_dict</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
  1370. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'chat_messages--&gt;</span><span class="si">{</span><span class="n">chat_messages</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1371. </code></pre></div>
  1372. <p>运行结果:</p>
  1373. <p><img alt="image-20251003001546687" src="assets/image-20251003001546687.png"></p>
  1374. <p>LangChain v1.0 版本对 Memory(记忆) 组件进行了深度优化与工程化重构,使其不仅支持多轮对话上下文管理,更成为构建生产级智能体(Agent)不可或缺的核心能力之一。在 LangChain 从“实验性框架”迈向“企业级平台”的关键转型中,Memory 模块被赋予了更清晰的职责边界、更灵活的策略机制以及更强的可扩展性,从而支撑复杂任务场景下的长期记忆、状态追踪与个性化交互。</p>
  1375. <h3 id="1-short-term-memory">1 短期记忆(Short-term Memory)<a class="headerlink" href="#1-short-term-memory" title="Permanent link">¶</a></h3>
  1376. <p>短期记忆的本质是线程级状态管理]。在 LangGraph 中:</p>
  1377. <blockquote>
  1378. <p>短期记忆 = Agent 状态(State) + 检查点持久化(Checkpointer) + 线程标识(thread_id)。</p>
  1379. </blockquote>
  1380. <p><strong>(1)状态(State)</strong></p>
  1381. <p>通常是一个包含 messages 字段的字典或 Pydantic 模型(如 MessagesState 或自定义 CustomState),用于存储当前会话的所有消息、中间变量、工具调用结果等。</p>
  1382. <p><strong>(2)检查点器(Checkpointer)</strong></p>
  1383. <p>负责将状态序列化并持久化到内存、SQLite、PostgreSQL 等后端。每次状态变更(如新增一条消息)都会触发一次检查点保存。</p>
  1384. <p><strong>(3)会话ID(thread_id)</strong></p>
  1385. <p>作为会话的唯一标识符,确保不同用户或不同对话之间的状态完全隔离。即使多个用户并发交互,也不会发生记忆混淆。</p>
  1386. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain.agents</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_agent</span>
  1387. <span class="kn">from</span><span class="w"> </span><span class="nn">langgraph.checkpoint.memory</span><span class="w"> </span><span class="kn">import</span> <span class="n">InMemorySaver</span>
  1388. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain.messages</span><span class="w"> </span><span class="kn">import</span> <span class="n">HumanMessage</span>
  1389. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaLLM</span>
  1390. <span class="kn">import</span><span class="w"> </span><span class="nn">time</span>
  1391. <span class="c1"># 初始化大模型,这里使用的是 Qwen 的聊天模型</span>
  1392. <span class="n">model</span> <span class="o">=</span> <span class="n">OllamaLLM</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"qwen2.5:7b"</span><span class="p">)</span>
  1393. <span class="c1"># 创建内存保存器 (Checkpointer)</span>
  1394. <span class="c1"># 这是 LangGraph 的核心概念之一,用于在对话过程中保存和恢复状态(记忆)</span>
  1395. <span class="n">checkpointer</span> <span class="o">=</span> <span class="n">InMemorySaver</span><span class="p">()</span>
  1396. <span class="c1"># 定义 Agent 的配置</span>
  1397. <span class="c1"># "thread_id" (线程ID) 非常关键:它相当于对话的 ID,用于区分不同的会话记忆</span>
  1398. <span class="c1"># 使用时间戳作为 ID,确保每次运行脚本时的线程 ID 不同(但在同一次运行中复用)</span>
  1399. <span class="n">timestamp</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
  1400. <span class="n">config</span> <span class="o">=</span> <span class="p">{</span>
  1401. <span class="s2">"configurable"</span><span class="p">:</span> <span class="p">{</span><span class="s2">"thread_id"</span><span class="p">:</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="nb">int</span><span class="p">(</span><span class="n">timestamp</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span><span class="p">}</span>
  1402. <span class="p">}</span>
  1403. <span class="c1"># 创建 Agent 实例</span>
  1404. <span class="c1"># model: 指定使用的底层大模型</span>
  1405. <span class="c1"># tools: 工具列表,这里为空,表示 Agent 只能进行对话,不能调用外部工具(如搜索、计算器等)</span>
  1406. <span class="c1"># checkpointer: 传入上面的内存保存器,赋予 Agent 记忆能力</span>
  1407. <span class="c1"># system_prompt: 设定 Agent 的角色和行为模式</span>
  1408. <span class="n">agent</span> <span class="o">=</span> <span class="n">create_agent</span><span class="p">(</span>
  1409. <span class="n">model</span><span class="o">=</span><span class="n">model</span><span class="p">,</span>
  1410. <span class="n">tools</span><span class="o">=</span><span class="p">[],</span>
  1411. <span class="n">checkpointer</span><span class="o">=</span><span class="n">checkpointer</span><span class="p">,</span>
  1412. <span class="n">system_prompt</span><span class="o">=</span><span class="s2">"你是一个翻译官,擅长中英互译。"</span>
  1413. <span class="p">)</span>
  1414. <span class="c1"># 第一轮对话输入</span>
  1415. <span class="n">input_1</span> <span class="o">=</span> <span class="p">{</span>
  1416. <span class="s2">"messages"</span><span class="p">:</span> <span class="p">[</span><span class="n">HumanMessage</span><span class="p">(</span><span class="s2">"你好,我叫小呆。"</span><span class="p">)]</span>
  1417. <span class="p">}</span>
  1418. <span class="c1"># 调用 Agent (Response A)</span>
  1419. <span class="c1"># 使用 config,这意味着这次对话会记录在 thread_id 对应的内存中</span>
  1420. <span class="c1"># Agent 会记住 "我叫小呆" 这个信息</span>
  1421. <span class="n">response_a</span> <span class="o">=</span> <span class="n">agent</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span>
  1422. <span class="nb">input</span><span class="o">=</span><span class="n">input_1</span><span class="p">,</span>
  1423. <span class="n">config</span><span class="o">=</span><span class="n">config</span>
  1424. <span class="p">)</span>
  1425. <span class="c1"># 第二轮对话输入(测试是否记得之前的信息)</span>
  1426. <span class="n">input_2</span> <span class="o">=</span> <span class="p">{</span>
  1427. <span class="s2">"messages"</span><span class="p">:</span> <span class="p">[</span><span class="n">HumanMessage</span><span class="p">(</span><span class="s2">"你好,我叫什么?"</span><span class="p">)]</span>
  1428. <span class="p">}</span>
  1429. <span class="c1"># 定义一个新的配置 (config_2),使用完全不同的 thread_id</span>
  1430. <span class="c1"># 这代表开启了一个全新的、独立的对话会话</span>
  1431. <span class="n">config_2</span> <span class="o">=</span> <span class="p">{</span>
  1432. <span class="s2">"configurable"</span><span class="p">:</span> <span class="p">{</span><span class="s2">"thread_id"</span><span class="p">:</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="nb">int</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())</span><span class="si">}</span><span class="s2">"</span><span class="p">}</span> <span class="c1"># 这里生成了一个新的时间戳 ID</span>
  1433. <span class="p">}</span>
  1434. <span class="c1"># 调用 Agent (Response B)</span>
  1435. <span class="c1"># 使用新的 config_2,Agent 看不到 config_1 中的历史记录</span>
  1436. <span class="c1"># 因此,Agent 应该不知道用户叫 "小呆",因为它处于一个新的 "线程" 中</span>
  1437. <span class="n">response_b</span> <span class="o">=</span> <span class="n">agent</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span>
  1438. <span class="nb">input</span><span class="o">=</span><span class="n">input_2</span><span class="p">,</span>
  1439. <span class="n">config</span><span class="o">=</span><span class="n">config_2</span>
  1440. <span class="p">)</span>
  1441. <span class="c1"># 调用 Agent (Response C)</span>
  1442. <span class="c1"># 再次使用最初的 config</span>
  1443. <span class="c1"># 这会恢复到第一个会话的记忆中</span>
  1444. <span class="c1"># Agent 应该能回想起用户叫 "小呆",因为它共享同一个 thread_id</span>
  1445. <span class="n">response_c</span> <span class="o">=</span> <span class="n">agent</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span>
  1446. <span class="nb">input</span><span class="o">=</span><span class="n">input_2</span><span class="p">,</span>
  1447. <span class="n">config</span><span class="o">=</span><span class="n">config</span>
  1448. <span class="p">)</span>
  1449. <span class="c1"># 输出结果进行对比</span>
  1450. <span class="nb">print</span><span class="p">(</span><span class="s2">"Response A (第一次对话):"</span><span class="p">)</span>
  1451. <span class="nb">print</span><span class="p">(</span><span class="n">response_a</span><span class="p">)</span>
  1452. <span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">Response B (新线程,无记忆):"</span><span class="p">)</span>
  1453. <span class="nb">print</span><span class="p">(</span><span class="n">response_b</span><span class="p">)</span>
  1454. <span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">Response C (回到原线程,有记忆):"</span><span class="p">)</span>
  1455. <span class="nb">print</span><span class="p">(</span><span class="n">response_c</span><span class="p">)</span>
  1456. </code></pre></div>
  1457. <p><strong>代码运行逻辑:</strong></p>
  1458. <ul>
  1459. <li><strong>checkpointer (记忆核心)</strong>:这是 LangGraph 区别于传统简单 API 调用的关键。它允许 Agent 在多次 invoke 调用之间保存状态。</li>
  1460. <li><strong>thread_id (记忆索引)</strong>:你可以把 thread_id 想象成数据库中的主键。</li>
  1461. <li>Response A:向 ID 为 100 的记录里写入了名字。</li>
  1462. <li>Response B:向 ID 为 200 的新记录提问,因为 200 是空的,所以 Agent 不知道名字。</li>
  1463. <li>Response C:又回到 ID 为 100 的记录提问,Agent 读取了历史记录,所以知道名字。</li>
  1464. <li><strong>System Prompt</strong>:虽然输入是在对话,但因为设定了 “你是一个翻译官”,Agent 可能会试图在回答的同时进行翻译,或者在回复格式上符合翻译官的身份。</li>
  1465. </ul>
  1466. <h3 id="2_2">2 长期记忆<a class="headerlink" href="#2_2" title="Permanent link">¶</a></h3>
  1467. <p>对于需要长期运行和可靠记忆的应用,推荐使用数据库进行持久化。详见后面阶段LangGraph部分。</p>
  1468. <h2 id="indexes">七、Indexes<a class="headerlink" href="#indexes" title="Permanent link">¶</a></h2>
  1469. <p>Indexes组件的目的是让LangChain具备处理文档处理的能力,包括:文档加载、检索等。注意,这里的文档不局限于txt、pdf等文本类内容,还涵盖email、区块链、视频等内容。</p>
  1470. <p>Indexes组件主要包含类型:</p>
  1471. <ul>
  1472. <li>文档加载器</li>
  1473. <li>文本分割器</li>
  1474. <li>VectorStores</li>
  1475. <li>检索器</li>
  1476. </ul>
  1477. <h3 id="1_1">1 文档加载器<a class="headerlink" href="#1_1" title="Permanent link">¶</a></h3>
  1478. <blockquote>
  1479. <p><a href="https://python.langchain.com/v0.2/docs/introduction/">https://python.langchain.com/v0.2/docs/introduction/</a></p>
  1480. </blockquote>
  1481. <p>文档加载器主要基于<code>Unstructured</code> 包,<code>Unstructured</code> 是一个python包,可以把各种类型的文件转换成文本。文档加载器使用起来很简单,只需要引入相应的loader工具。</p>
  1482. <p>LangChain支持的文档加载器 (部分):</p>
  1483. <p><img alt="image-20250705100227413" src="assets/image-20250705100227413.png"></p>
  1484. <p>示例代码:</p>
  1485. <blockquote>
  1486. <p>需要安装的包:</p>
  1487. <p>pip install unstructured</p>
  1488. <p>pip install langchain-unstructured</p>
  1489. </blockquote>
  1490. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_unstructured</span><span class="w"> </span><span class="kn">import</span> <span class="n">UnstructuredLoader</span>
  1491. <span class="c1"># 创建 UnstructuredLoader 对象</span>
  1492. <span class="n">loader</span> <span class="o">=</span> <span class="n">UnstructuredLoader</span><span class="p">(</span><span class="s1">'./data/衣服属性.txt'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">'utf8'</span><span class="p">)</span>
  1493. <span class="n">docs</span> <span class="o">=</span> <span class="n">loader</span><span class="o">.</span><span class="n">load</span><span class="p">()</span>
  1494. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'docs--&gt;</span><span class="si">{</span><span class="n">docs</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1495. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'len--&gt;</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">docs</span><span class="p">)</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1496. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'第一行数据--&gt;</span><span class="si">{</span><span class="n">docs</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">page_content</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1497. <span class="nb">print</span><span class="p">(</span><span class="s1">'*'</span> <span class="o">*</span> <span class="mi">100</span><span class="p">)</span>
  1498. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_community.document_loaders</span><span class="w"> </span><span class="kn">import</span> <span class="n">TextLoader</span>
  1499. <span class="c1"># 创建 TextLoader 对象</span>
  1500. <span class="n">loader</span> <span class="o">=</span> <span class="n">TextLoader</span><span class="p">(</span><span class="s1">'./data/衣服属性.txt'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">'utf8'</span><span class="p">)</span>
  1501. <span class="n">docs</span> <span class="o">=</span> <span class="n">loader</span><span class="o">.</span><span class="n">load</span><span class="p">()</span>
  1502. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'docs--&gt;</span><span class="si">{</span><span class="n">docs</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1503. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'len--&gt;</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">docs</span><span class="p">)</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1504. <span class="nb">print</span><span class="p">(</span><span class="s1">'第一行数据--&gt;</span><span class="si">{}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">docs</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">page_content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]))</span>
  1505. </code></pre></div>
  1506. <p>运行结果:</p>
  1507. <p><img alt="image-20251003010445727" src="assets/image-20251003010445727.png"></p>
  1508. <h3 id="2_3">2 文档分割器<a class="headerlink" href="#2_3" title="Permanent link">¶</a></h3>
  1509. <p>由于模型对输入的字符长度有限制,我们在碰到很长的文本时,需要把文本分割成多个小的文本片段。</p>
  1510. <p>文本分割最简单的方式是按照字符长度进行分割,但是这会带来很多问题,比如说如果文本是一段代码,一个函数被分割到两段之后就成了没有意义的字符,所以整体的原则是把语义相关的文本片段放在一起。</p>
  1511. <p>LangChain中最基本的文本分割器是<code>CharacterTextSplitter</code> ,它按照指定的分隔符(默认“\n\n”)进行分割,并且考虑文本片段的最大长度。我们看个例子:</p>
  1512. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.documents</span><span class="w"> </span><span class="kn">import</span> <span class="n">Document</span>
  1513. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_text_splitters</span><span class="w"> </span><span class="kn">import</span> <span class="n">CharacterTextSplitter</span>
  1514. <span class="c1"># 创建分词器 separator参数指的是分割的分隔符,chunk_size指的是分割出来的每个块的大小,chunk_overlap指的是每个块之间重叠的大小</span>
  1515. <span class="n">text_splitter</span> <span class="o">=</span> <span class="n">CharacterTextSplitter</span><span class="p">(</span><span class="n">separator</span><span class="o">=</span><span class="s2">" "</span><span class="p">,</span> <span class="n">chunk_size</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">chunk_overlap</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
  1516. <span class="c1"># 一句话分割</span>
  1517. <span class="n">result1</span> <span class="o">=</span> <span class="n">text_splitter</span><span class="o">.</span><span class="n">split_text</span><span class="p">(</span><span class="s2">"a b c d e f"</span><span class="p">)</span>
  1518. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'result1---&gt;</span><span class="si">{</span><span class="n">result1</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1519. <span class="c1"># 多句话分割</span>
  1520. <span class="n">result2</span> <span class="o">=</span> <span class="n">text_splitter</span><span class="o">.</span><span class="n">create_documents</span><span class="p">([</span><span class="s2">"a b c d e f"</span><span class="p">,</span> <span class="s2">"e f g h"</span><span class="p">])</span>
  1521. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'result2---&gt;</span><span class="si">{</span><span class="n">result2</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1522. <span class="c1"># 多句话分割</span>
  1523. <span class="n">result3</span> <span class="o">=</span> <span class="n">text_splitter</span><span class="o">.</span><span class="n">split_documents</span><span class="p">([</span><span class="n">Document</span><span class="p">(</span><span class="n">page_content</span><span class="o">=</span><span class="s2">"a b c d e f"</span><span class="p">,</span> <span class="n">metadata</span><span class="o">=</span><span class="p">{</span><span class="s2">"id"</span><span class="p">:</span> <span class="s2">"1"</span><span class="p">})])</span>
  1524. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'result3---&gt;</span><span class="si">{</span><span class="n">result3</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1525. </code></pre></div>
  1526. <p>运行结果:</p>
  1527. <p><img alt="image-20251003011030583" src="assets/image-20251003011030583.png"></p>
  1528. <hr>
  1529. <p>除了CharacterTextSplitter分割器,LangChain还支持其他文档分割器 (部分):</p>
  1530. <table>
  1531. <thead>
  1532. <tr>
  1533. <th>分割器名称</th>
  1534. <th>功能描述</th>
  1535. <th>类型</th>
  1536. <th>工业场景应用</th>
  1537. </tr>
  1538. </thead>
  1539. <tbody>
  1540. <tr>
  1541. <td>CharacterTextSplitter</td>
  1542. <td>简单按指定分隔符(如换行、逗号)直接分割。</td>
  1543. <td>基础字符解析</td>
  1544. <td>简单字符串或 CSV 数据处理,如传感器数据日志。</td>
  1545. </tr>
  1546. <tr>
  1547. <td>RecursiveCharacterTextSplitter</td>
  1548. <td>递归按字符分割,先尝试自然边界(如段落、句子),太大则继续细分。</td>
  1549. <td>通用字符解析</td>
  1550. <td>通用文本处理,如日志、报告、PDF 文档分割,便于 RAG 检索。</td>
  1551. </tr>
  1552. <tr>
  1553. <td>TokenTextSplitter</td>
  1554. <td>按 token(词元)分割,支持 LLM token 计数。</td>
  1555. <td>Token 基于解析</td>
  1556. <td>LLM 输入优化,如处理 API 响应或长查询,控制 token 限制。</td>
  1557. </tr>
  1558. <tr>
  1559. <td>SentenceTextSplitter</td>
  1560. <td>按句子边界分割,使用 NLP 识别句子(包括标点)。</td>
  1561. <td>语义解析</td>
  1562. <td>自然语言文本,如文章或对话分析,保持句子完整。</td>
  1563. </tr>
  1564. <tr>
  1565. <td>SpacyTextSplitter</td>
  1566. <td>使用 SpaCy NLP 库按句子或实体分割(需安装 SpaCy)。</td>
  1567. <td>语义解析</td>
  1568. <td>高级 NLP 场景,如实体提取或生物医学文本。</td>
  1569. </tr>
  1570. <tr>
  1571. <td>NLTKTextSplitter</td>
  1572. <td>使用 NLTK 库按句子或词分割(需安装 NLTK)。</td>
  1573. <td>语义解析</td>
  1574. <td>文本研究或分析,如时间序列数据描述。</td>
  1575. </tr>
  1576. <tr>
  1577. <td>MarkdownHeaderTextSplitter</td>
  1578. <td>按 Markdown 结构(如标题、列表)智能分割。</td>
  1579. <td>结构化解析</td>
  1580. <td>Markdown 文档分割,保留语义结构,用于知识库构建。</td>
  1581. </tr>
  1582. <tr>
  1583. <td>HTMLSplitter</td>
  1584. <td>按 HTML 标签(如 、)分割网页内容。</td>
  1585. <td>结构化解析</td>
  1586. <td>网页数据爬取,如在线技术文档或新闻提取。</td>
  1587. </tr>
  1588. <tr>
  1589. <td>LatexTextSplitter</td>
  1590. <td>按 LaTeX 结构(如章节、公式)分割。</td>
  1591. <td>结构化解析</td>
  1592. <td>学术论文或数学文档处理。</td>
  1593. </tr>
  1594. <tr>
  1595. <td>PythonCodeTextSplitter</td>
  1596. <td>按 Python 代码结构(如函数、类)分割。</td>
  1597. <td>代码解析</td>
  1598. <td>源代码文件分析,如脚本调试或代码库管理。</td>
  1599. </tr>
  1600. </tbody>
  1601. </table>
  1602. <p>下面就几个重要的分割器进行讲解。</p>
  1603. <ul>
  1604. <li>递归字符文本分割器(RecursiveCharacterTextSplitter)</li>
  1605. </ul>
  1606. <blockquote>
  1607. <p>递归字符文本分割器是一种更智能的分割方法,它尝试在特定分隔符处分割文本,以保持更好的语义完整性。 特点:</p>
  1608. <ul>
  1609. <li>尝试在自然断点处分割文本</li>
  1610. <li>比简单的字符分割更能保持语义完整性</li>
  1611. <li>适用于结构化程度较高的文本,如 Markdown、HTML 等</li>
  1612. </ul>
  1613. <p>运行流程:</p>
  1614. <ul>
  1615. <li>首先尝试使用第一个分隔符(如 "\n\n")分割文本</li>
  1616. <li>如果分割后的块仍然过大,则使用下一个分隔符继续分割</li>
  1617. <li>重复此过程,直到达到指定的 chunk_size 或用完所有分隔符</li>
  1618. </ul>
  1619. <p>示例代码</p>
  1620. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_text_splitters</span><span class="w"> </span><span class="kn">import</span> <span class="n">RecursiveCharacterTextSplitter</span>
  1621. <span class="n">text_splitter</span> <span class="o">=</span> <span class="n">RecursiveCharacterTextSplitter</span><span class="p">(</span>
  1622. <span class="n">chunk_size</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span> <span class="c1"># 每个块最多 100 个字符</span>
  1623. <span class="n">chunk_overlap</span><span class="o">=</span><span class="mi">6</span><span class="p">,</span> <span class="c1"># 相邻分块会共享 20 个字符</span>
  1624. <span class="n">length_function</span><span class="o">=</span><span class="nb">len</span><span class="p">,</span> <span class="c1"># 用字符数来衡量长度</span>
  1625. <span class="n">separators</span><span class="o">=</span><span class="p">[</span><span class="s2">"</span><span class="se">\n\n</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="s2">" "</span><span class="p">,</span> <span class="s2">""</span><span class="p">]</span> <span class="c1"># 会优先尝试按 \n\n 分段,如果太长,再按 \n → 空格 → 逐字符切分。</span>
  1626. <span class="p">)</span>
  1627. <span class="n">text</span> <span class="o">=</span> <span class="s2">"""</span>
  1628. <span class="s2">人工智能正在快速发展,尤其是大语言模型的应用,正在改变人类的工作方式。</span>
  1629. <span class="s2">它们可以帮助人们进行写作、代码生成、甚至是科研探索。</span>
  1630. <span class="s2">相比之下,新能源的发展同样重要。</span>
  1631. <span class="s2">电动车和太阳能正在逐渐替代传统能源,减少碳排放,对全球环境保护至关重要。</span>
  1632. <span class="s2">"""</span>
  1633. <span class="n">docs</span> <span class="o">=</span> <span class="n">text_splitter</span><span class="o">.</span><span class="n">split_text</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
  1634. <span class="nb">print</span><span class="p">(</span><span class="n">docs</span><span class="p">)</span>
  1635. </code></pre></div>
  1636. <p>运行结果</p>
  1637. <p><img alt="1768393012466" src="assets/1768393012466.png"></p>
  1638. </blockquote>
  1639. <ul>
  1640. <li>语义文档分割器(SemanticChunker)</li>
  1641. </ul>
  1642. <blockquote>
  1643. <p>语义文档分割器使用语义理解来分割文本,这是一种更高级的分割方法。 特点:</p>
  1644. <ul>
  1645. <li>基于语义相似性分割文本</li>
  1646. <li>能够更好地保持语义完整性</li>
  1647. <li>计算成本较高,处理大量文本时可能效率较低</li>
  1648. <li>适用于需要高度语义理解的场景</li>
  1649. </ul>
  1650. <p>示例代码</p>
  1651. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_experimental.text_splitter</span><span class="w"> </span><span class="kn">import</span> <span class="n">SemanticChunker</span>
  1652. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaEmbeddings</span>
  1653. <span class="n">embed</span> <span class="o">=</span> <span class="n">OllamaEmbeddings</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"mxbai-embed-large"</span><span class="p">)</span>
  1654. <span class="n">text_splitter</span> <span class="o">=</span> <span class="n">SemanticChunker</span><span class="p">(</span>
  1655. <span class="n">embeddings</span><span class="o">=</span><span class="n">embed</span><span class="p">,</span>
  1656. <span class="n">breakpoint_threshold_type</span><span class="o">=</span><span class="s1">'percentile'</span><span class="p">,</span>
  1657. <span class="c1"># 更低的百分位会更“积极”地切分(数值越小 =&gt; 切得越多)</span>
  1658. <span class="n">breakpoint_threshold_amount</span><span class="o">=</span><span class="mf">70.0</span><span class="p">,</span>
  1659. <span class="c1"># 句子拆分正则为同时识别中/英文终结符</span>
  1660. <span class="n">sentence_split_regex</span><span class="o">=</span><span class="sa">r</span><span class="s1">'(?&lt;=[。!?.!?])\s*'</span><span class="p">,</span>
  1661. <span class="c1"># 每个切分后片段(chunk)至少要有多少个字符</span>
  1662. <span class="n">min_chunk_size</span><span class="o">=</span><span class="mi">10</span>
  1663. <span class="p">)</span>
  1664. <span class="n">text</span> <span class="o">=</span> <span class="s2">"""</span>
  1665. <span class="s2">人工智能正在快速发展,尤其是大语言模型的应用,正在改变人类的工作方式。</span>
  1666. <span class="s2">它们可以帮助人们进行写作、代码生成、甚至是科研探索。</span>
  1667. <span class="s2">相比之下,新能源的发展同样重要。</span>
  1668. <span class="s2">电动车和太阳能正在逐渐替代传统能源,减少碳排放,对全球环境保护至关重要。</span>
  1669. <span class="s2">"""</span>
  1670. <span class="n">docs</span> <span class="o">=</span> <span class="n">text_splitter</span><span class="o">.</span><span class="n">split_text</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
  1671. <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">d</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">docs</span><span class="p">):</span>
  1672. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"------ Chunk </span><span class="si">{</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="si">}</span><span class="s2"> ------"</span><span class="p">)</span>
  1673. <span class="nb">print</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span>
  1674. <span class="nb">print</span><span class="p">()</span>
  1675. </code></pre></div>
  1676. <p>运行结果</p>
  1677. <p><img alt="image-20251003095433705" src="assets/image-20251003095433705.png"></p>
  1678. </blockquote>
  1679. <ul>
  1680. <li>MarkdownHeaderTextSplitter(Markdown文档切割器)</li>
  1681. </ul>
  1682. <blockquote>
  1683. <p>适用于Markdown文档,按照标题进行拆分</p>
  1684. <p>示例代码</p>
  1685. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_text_splitters</span><span class="w"> </span><span class="kn">import</span> <span class="n">MarkdownHeaderTextSplitter</span>
  1686. <span class="n">headers_to_split_on</span> <span class="o">=</span> <span class="p">[</span>
  1687. <span class="p">(</span><span class="s2">"#"</span><span class="p">,</span> <span class="s2">"Header 1"</span><span class="p">),</span>
  1688. <span class="p">(</span><span class="s2">"##"</span><span class="p">,</span> <span class="s2">"Header 2"</span><span class="p">),</span>
  1689. <span class="p">(</span><span class="s2">"###"</span><span class="p">,</span> <span class="s2">"Header 3"</span><span class="p">),</span>
  1690. <span class="p">]</span>
  1691. <span class="n">markdown_splitter</span> <span class="o">=</span> <span class="n">MarkdownHeaderTextSplitter</span><span class="p">(</span><span class="n">headers_to_split_on</span><span class="o">=</span><span class="n">headers_to_split_on</span><span class="p">)</span>
  1692. <span class="n">markdown_text</span> <span class="o">=</span> <span class="s2">"# Header 1</span><span class="se">\n</span><span class="s2">Some text</span><span class="se">\n</span><span class="s2">## Header 2</span><span class="se">\n</span><span class="s2">More text</span><span class="se">\n</span><span class="s2">### Header 3</span><span class="se">\n</span><span class="s2">Even more text"</span>
  1693. <span class="n">docs</span> <span class="o">=</span> <span class="n">markdown_splitter</span><span class="o">.</span><span class="n">split_text</span><span class="p">(</span><span class="n">markdown_text</span><span class="p">)</span>
  1694. <span class="nb">print</span><span class="p">(</span><span class="n">docs</span><span class="p">)</span>
  1695. </code></pre></div>
  1696. <p>运行结果</p>
  1697. <p><img alt="image-20251003100510115" src="assets/image-20251003100510115.png"></p>
  1698. </blockquote>
  1699. <p>其他拓展知识可以参考:<a href="https://blog.csdn.net/qq_28540861/article/details/149161419">https://blog.csdn.net/qq_28540861/article/details/149161419</a></p>
  1700. <h3 id="3-vectorstores">3 VectorStores<a class="headerlink" href="#3-vectorstores" title="Permanent link">¶</a></h3>
  1701. <p>VectorStores是一种特殊类型的数据库,它的作用是存储由嵌入创建的向量,提供相似查询等功能。</p>
  1702. <p>LangChain支持的VectorStore有<a href="https://python.langchain.com/docs/integrations/vectorstores/">https://python.langchain.com/docs/integrations/vectorstores/</a>,常见的如下:</p>
  1703. <p><img alt="image-20250705114738060" src="assets/image-20250705114738060.png"></p>
  1704. <blockquote>
  1705. <p>我们使用其中一个<code>Chroma</code> 组件作为例子:</p>
  1706. <p>pip install chromadb</p>
  1707. <p>pip install langchain-chroma</p>
  1708. </blockquote>
  1709. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_text_splitters</span><span class="w"> </span><span class="kn">import</span> <span class="n">CharacterTextSplitter</span>
  1710. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_chroma</span><span class="w"> </span><span class="kn">import</span> <span class="n">Chroma</span>
  1711. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_community.document_loaders</span><span class="w"> </span><span class="kn">import</span> <span class="n">TextLoader</span>
  1712. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaEmbeddings</span>
  1713. <span class="c1"># 1.加载文档</span>
  1714. <span class="c1"># 创建 TextLoader 对象</span>
  1715. <span class="n">loader</span> <span class="o">=</span> <span class="n">TextLoader</span><span class="p">(</span><span class="s1">'./data/pku.txt'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">'utf-8'</span><span class="p">)</span>
  1716. <span class="c1"># 加载文档</span>
  1717. <span class="n">docs</span> <span class="o">=</span> <span class="n">loader</span><span class="o">.</span><span class="n">load</span><span class="p">()</span>
  1718. <span class="c1"># print(f'docs--&gt;{docs}')</span>
  1719. <span class="c1"># 2.将文档进行分块</span>
  1720. <span class="c1"># 创建 CharacterTextSplitter 对象</span>
  1721. <span class="n">text_splitter</span> <span class="o">=</span> <span class="n">CharacterTextSplitter</span><span class="p">(</span><span class="n">separator</span><span class="o">=</span><span class="s2">"</span><span class="se">\n\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">chunk_size</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span> <span class="n">chunk_overlap</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span>
  1722. <span class="c1"># 分块</span>
  1723. <span class="n">split_docs</span> <span class="o">=</span> <span class="n">text_splitter</span><span class="o">.</span><span class="n">split_documents</span><span class="p">(</span><span class="n">docs</span><span class="p">)</span>
  1724. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'split_docs--&gt;</span><span class="si">{</span><span class="n">split_docs</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1725. <span class="c1"># 3.将分割后的文档存储到向量数据库中</span>
  1726. <span class="c1"># 加载embedding模型</span>
  1727. <span class="n">embedding</span> <span class="o">=</span> <span class="n">OllamaEmbeddings</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"mxbai-embed-large"</span><span class="p">)</span>
  1728. <span class="c1"># 创建向量数据库,需要指定 存储的文档和向量模型名称以及持久化目录</span>
  1729. <span class="n">chromadaDB</span> <span class="o">=</span> <span class="n">Chroma</span><span class="o">.</span><span class="n">from_documents</span><span class="p">(</span><span class="n">documents</span><span class="o">=</span><span class="n">split_docs</span><span class="p">,</span>
  1730. <span class="n">embedding</span><span class="o">=</span><span class="n">embedding</span><span class="p">,</span>
  1731. <span class="n">persist_directory</span><span class="o">=</span><span class="s1">'./chroma_db'</span><span class="p">)</span>
  1732. <span class="c1"># 假如你的向量数据库已经存在,那么可以直接加载</span>
  1733. <span class="c1"># chromadaDB = Chroma(persist_directory='./chroma_db', embedding_function=embedding)</span>
  1734. <span class="c1"># 4.使用向量数据库进行查询</span>
  1735. <span class="n">query</span> <span class="o">=</span> <span class="s2">"1937年北京大学发生了什么?"</span>
  1736. <span class="n">result</span> <span class="o">=</span> <span class="n">chromadaDB</span><span class="o">.</span><span class="n">similarity_search</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">k</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
  1737. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'result--&gt;</span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1738. </code></pre></div>
  1739. <p>运行结果:</p>
  1740. <p><img alt="image-20251003101141993" src="assets/image-20251003101141993.png"></p>
  1741. <h3 id="4_1">4 检索器<a class="headerlink" href="#4_1" title="Permanent link">¶</a></h3>
  1742. <h4 id="41-langchain">4.1 LangChain的检索器定义<a class="headerlink" href="#41-langchain" title="Permanent link">¶</a></h4>
  1743. <p>检索器是 LangChain 中负责信息检索的模块,通常与 索引(Indexes) 模块(如向量存储、嵌入模型)结合使用。它的核心功能是:</p>
  1744. <ul>
  1745. <li>输入:接收用户查询(通常是文本)。</li>
  1746. <li>处理:根据查询从数据源中检索相关内容。</li>
  1747. <li>输出:返回一组相关文档或文本片段(通常是 Document 对象列表)。</li>
  1748. </ul>
  1749. <p>检索器在以下场景中扮演关键角色:</p>
  1750. <ul>
  1751. <li>问答系统:从文档或知识库中检索答案的上下文。</li>
  1752. <li>语义搜索:根据查询的语义返回相关结果。</li>
  1753. <li>上下文增强:为语言模型提供外部知识,解决其知识局限。</li>
  1754. </ul>
  1755. <h4 id="42">4.2 检索器的工作原理<a class="headerlink" href="#42" title="Permanent link">¶</a></h4>
  1756. <p>检索器通常与 向量存储(Vector Stores) 配合,通过嵌入模型(Embedding Models)将查询和文档转为向量,基于相似性进行检索。工作流程可以分为以下步骤:</p>
  1757. <ul>
  1758. <li>查询嵌入:将用户查询通过嵌入模型(如 OpenAIEmbeddings)转为向量表示</li>
  1759. <li>相似性搜索:在向量存储中查找与查询向量最相似的文档向量。</li>
  1760. <li>文档返回:返回匹配的文档(包含内容、元数据等)。</li>
  1761. <li>后处理(可选):对检索结果进行排序、过滤或重新排名。</li>
  1762. </ul>
  1763. <p>检索器的核心依赖:</p>
  1764. <ul>
  1765. <li>嵌入模型:将文本转为向量(如 OpenAIEmbeddings, HuggingFaceEmbeddings)。</li>
  1766. <li>向量存储:存储文档向量(如 Chroma、FAISS、Pinecone)。</li>
  1767. <li>相似性度量:如余弦相似度、欧几里得距离</li>
  1768. </ul>
  1769. <h4 id="43">4.3 检索器类型<a class="headerlink" href="#43" title="Permanent link">¶</a></h4>
  1770. <p>langchain支持很多检索器<a href="https://python.langchain.com/docs/integrations/retrievers/">https://python.langchain.com/docs/integrations/retrievers/</a>,部分如下:</p>
  1771. <p><img alt="image-20250705114709874" src="assets/image-20250705114709874-17594578225791.png"></p>
  1772. <p>此处我们讲解VectorStoreRetriever。</p>
  1773. <p>在 LangChain 中,as_retriever() 方法的 search_type 参数决定了向量检索的具体算法和行为。</p>
  1774. <div class="highlight"><pre><span></span><code><span class="n">retriever</span> <span class="o">=</span> <span class="n">vector_store</span><span class="o">.</span><span class="n">as_retriever</span><span class="p">(</span>
  1775. <span class="n">search_type</span><span class="o">=</span><span class="s2">"similarity"</span><span class="p">,</span> <span class="c1"># 可选 "similarity"|"mmr"|"similarity_score_threshold"</span>
  1776. <span class="n">search_kwargs</span><span class="o">=</span><span class="p">{</span>
  1777. <span class="s2">"k"</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span> <span class="c1"># 返回结果数量</span>
  1778. <span class="s2">"score_threshold"</span><span class="p">:</span> <span class="mf">0.7</span><span class="p">,</span> <span class="c1"># 仅当search_type="similarity_score_threshold"时有效,低于阈值的都丢弃。</span>
  1779. <span class="s2">"filter"</span><span class="p">:</span> <span class="p">{</span><span class="s2">"source"</span><span class="p">:</span> <span class="s2">"重要文档.pdf"</span><span class="p">},</span> <span class="c1"># 元数据过滤,只会检索满足条件的文档。</span>
  1780. <span class="s2">"lambda_mult"</span><span class="p">:</span> <span class="mf">0.25</span> <span class="c1"># 仅MMR搜索有效(控制多样性):接近 0 则更强调和查询的相关性;接近 1 则更强调结果之间的差异性</span>
  1781. <span class="p">}</span>
  1782. <span class="p">)</span>
  1783. </code></pre></div>
  1784. <p>以下是三种搜索类型的对比:</p>
  1785. <p><img alt="image-20250714160215042" src="assets/image-20250714160215042-17594581318012.png"></p>
  1786. <p>示例代码:</p>
  1787. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_chroma</span><span class="w"> </span><span class="kn">import</span> <span class="n">Chroma</span>
  1788. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_ollama</span><span class="w"> </span><span class="kn">import</span> <span class="n">OllamaEmbeddings</span>
  1789. <span class="n">embedding</span> <span class="o">=</span> <span class="n">OllamaEmbeddings</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="s2">"mxbai-embed-large"</span><span class="p">)</span>
  1790. <span class="c1"># 向量数据库已经存在,那么可以直接加载</span>
  1791. <span class="n">chromadaDB</span> <span class="o">=</span> <span class="n">Chroma</span><span class="p">(</span><span class="n">persist_directory</span><span class="o">=</span><span class="s1">'./chroma_db'</span><span class="p">,</span> <span class="n">embedding_function</span><span class="o">=</span><span class="n">embedding</span><span class="p">)</span>
  1792. <span class="c1"># 使用向量数据库进行查询</span>
  1793. <span class="n">query</span> <span class="o">=</span> <span class="s2">"1937年北京大学发生了什么?"</span>
  1794. <span class="c1"># result = chromadaDB.similarity_search(query, k=2)</span>
  1795. <span class="c1"># 使用 as_retriever 方法返回 Retriever 对象,然后调用 invoke 方法进行查询</span>
  1796. <span class="n">retriever</span> <span class="o">=</span> <span class="n">chromadaDB</span><span class="o">.</span><span class="n">as_retriever</span><span class="p">(</span><span class="n">search_kwargs</span><span class="o">=</span><span class="p">{</span><span class="s2">"k"</span><span class="p">:</span><span class="mi">2</span><span class="p">})</span>
  1797. <span class="n">result</span> <span class="o">=</span> <span class="n">retriever</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="n">query</span><span class="p">)</span>
  1798. <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'result--&gt;</span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
  1799. </code></pre></div>
  1800. <p>运行结果:</p>
  1801. <p><img alt="image-20251003102843558" src="assets/image-20251003102843558.png"></p>
  1802. <p><strong>拓展:</strong></p>
  1803. <p><code>vectordb.as_retriever()</code> 和 <code>vectordb.similarity_search()</code> 都是用于从向量数据库中检索相关文档的方法,它们有什么异同:</p>
  1804. <ul>
  1805. <li>
  1806. <p>相同</p>
  1807. <ul>
  1808. <li>核心功能:两者都基于向量相似度(如余弦相似度)从向量数据库中检索与查询最相关的文档。</li>
  1809. <li>底层技术:通常使用相同的嵌入模型和相似度计算方式(如 FAISS、Chroma、Pinecone 等)。</li>
  1810. </ul>
  1811. </li>
  1812. <li>
  1813. <p>不同</p>
  1814. <p><img alt="image-20250705114109276" src="assets/image-20250705114109276.png"></p>
  1815. </li>
  1816. </ul>
  1817. <h4 id="44">4.4 拓展<a class="headerlink" href="#44" title="Permanent link">¶</a></h4>
  1818. <p>其他几种常用的检索器介绍如下。</p>
  1819. <ul>
  1820. <li>TFIDFRetriever</li>
  1821. </ul>
  1822. <blockquote>
  1823. <p>功能:基于 TF-IDF(词频-逆文档频率)的检索器。 </p>
  1824. <p>特点:</p>
  1825. <ul>
  1826. <li>使用 TF-IDF 向量表示文档和查询。</li>
  1827. <li>适合快速构建原型。</li>
  1828. <li>不支持语义搜索。</li>
  1829. </ul>
  1830. <p>适用场景:</p>
  1831. <ul>
  1832. <li>文本搜索</li>
  1833. <li>关键词提取</li>
  1834. </ul>
  1835. <p><strong>补充:理解 TF 和 IDF</strong></p>
  1836. <p>为了理解后面的 BM25,可以先把 TF-IDF 拆成两个部分来看:</p>
  1837. <ul>
  1838. <li><strong>TF(Term Frequency,词频)</strong>:回答“这个词在当前文档中出现得多不多?”</li>
  1839. <li><strong>IDF(Inverse Document Frequency,逆文档频率)</strong>:回答“这个词在整个知识库中是否稀有?”</li>
  1840. </ul>
  1841. <p>常见公式如下:</p>
  1842. <div class="highlight"><pre><span></span><code>TF(t,d) = 词 t 在文档 d 中出现次数 / 文档 d 总词数
  1843. IDF(t) = log(N / df(t))
  1844. </code></pre></div>
  1845. <ul>
  1846. <li><code>N</code>:知识库文档总数。</li>
  1847. <li><code>df(t)</code>:包含词 <code>t</code> 的文档数量。</li>
  1848. </ul>
  1849. <p>一个词越普遍,<code>df(t)</code> 越大,IDF 越小;一个词越稀有,<code>df(t)</code> 越小,IDF 越大。</p>
  1850. <p>例如,知识库有 10 篇文档。当前 100 词的文章中,“asyncio”出现 4 次,整个知识库只有 2 篇包含它:</p>
  1851. <div class="highlight"><pre><span></span><code>TF = 4 / 100 = 0.04
  1852. IDF = ln(10 / 2) = ln(5) ≈ 1.609
  1853. TF-IDF = 0.04 × 1.609 ≈ 0.064
  1854. </code></pre></div>
  1855. <p>如果“使用”出现在全部 10 篇文档中,则 <code>IDF = ln(10 / 10) = 0</code>。即使它在某篇文章里出现很多次,最终 TF-IDF 权重也会很低,因为它缺乏区分主题的能力。</p>
  1856. <p>所以,TF-IDF 的核心思想是:<strong>一个词在当前文档中越常见,并且在整个知识库中越稀有,它越能代表当前文档的主题。</strong> BM25 正是在这个思想上继续加入了长度归一化和词频饱和控制。</p>
  1857. <p>示例代码:</p>
  1858. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_community.retrievers</span><span class="w"> </span><span class="kn">import</span> <span class="n">TFIDFRetriever</span>
  1859. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.documents</span><span class="w"> </span><span class="kn">import</span> <span class="n">Document</span>
  1860. <span class="n">docs</span> <span class="o">=</span> <span class="p">[</span>
  1861. <span class="n">Document</span><span class="p">(</span><span class="n">page_content</span><span class="o">=</span><span class="s2">"量子计算是一种基于量子力学的计算范式。"</span><span class="p">),</span>
  1862. <span class="n">Document</span><span class="p">(</span><span class="n">page_content</span><span class="o">=</span><span class="s2">"人工智能是模拟人类智能的技术。"</span><span class="p">)</span>
  1863. <span class="p">]</span>
  1864. <span class="n">retriever</span> <span class="o">=</span> <span class="n">TFIDFRetriever</span><span class="o">.</span><span class="n">from_documents</span><span class="p">(</span><span class="n">docs</span><span class="p">)</span>
  1865. <span class="n">retriever</span><span class="o">.</span><span class="n">k</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># 返回 1 个结果</span>
  1866. <span class="n">results</span> <span class="o">=</span> <span class="n">retriever</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="s2">"量子计算"</span><span class="p">)</span>
  1867. <span class="nb">print</span><span class="p">(</span><span class="n">results</span><span class="p">)</span>
  1868. </code></pre></div>
  1869. <p>运行结果:</p>
  1870. <p><img src="assets/image-20251003104151768.png" alt="image-20251003104151768" style="zoom:80%;"></p>
  1871. </blockquote>
  1872. <ul>
  1873. <li>BM25Retriever</li>
  1874. </ul>
  1875. <blockquote>
  1876. <p>BM25算法:BM25 是对 TF-IDF 的改进版本,在 TF-IDF 基础上做了归一化(防止长文档优势)与饱和控制(防止词频无限增长)。</p>
  1877. <p><img src="assets/image-20251003105157106.png" alt="image-20251003105157106" style="zoom: 60%;"></p>
  1878. <p><img src="assets/image-20251006090343544.png" alt="image-20251006090343544" style="zoom:67%;"></p>
  1879. <p>功能:基于 BM25 算法的关键词检索器,适合基于词频的搜索。</p>
  1880. <p>特点:</p>
  1881. <ul>
  1882. <li>不依赖嵌入模型,使用词频和逆文档频率(TF-IDF)计算相关性。</li>
  1883. <li>适合关键词匹配场景,计算成本低。</li>
  1884. <li>不支持语义搜索,效果依赖文本的字面匹配。</li>
  1885. </ul>
  1886. <p>适用场景:</p>
  1887. <ul>
  1888. <li>传统搜索场景。</li>
  1889. <li>关键词驱动的问答。</li>
  1890. </ul>
  1891. <p>环境依赖:</p>
  1892. <p>pip install rank_bm25</p>
  1893. <p>示例代码:</p>
  1894. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_community.retrievers</span><span class="w"> </span><span class="kn">import</span> <span class="n">BM25Retriever</span>
  1895. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.documents</span><span class="w"> </span><span class="kn">import</span> <span class="n">Document</span>
  1896. <span class="n">docs</span> <span class="o">=</span> <span class="p">[</span>
  1897. <span class="n">Document</span><span class="p">(</span><span class="n">page_content</span><span class="o">=</span><span class="s2">"量子计算是一种基于量子力学的计算范式。"</span><span class="p">),</span>
  1898. <span class="n">Document</span><span class="p">(</span><span class="n">page_content</span><span class="o">=</span><span class="s2">"人工智能是模拟人类智能的技术。"</span><span class="p">)</span>
  1899. <span class="p">]</span>
  1900. <span class="n">retriever</span> <span class="o">=</span> <span class="n">BM25Retriever</span><span class="o">.</span><span class="n">from_documents</span><span class="p">(</span><span class="n">docs</span><span class="p">)</span>
  1901. <span class="n">retriever</span><span class="o">.</span><span class="n">k</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># 返回 1 个结果</span>
  1902. <span class="n">results</span> <span class="o">=</span> <span class="n">retriever</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="s2">"量子计算"</span><span class="p">)</span>
  1903. <span class="nb">print</span><span class="p">(</span><span class="n">results</span><span class="p">)</span>
  1904. </code></pre></div>
  1905. <p>运行结果:</p>
  1906. <p><img src="assets/image-20251003104151768.png" alt="image-20251003104151768" style="zoom:80%;"></p>
  1907. </blockquote>
  1908. <ul>
  1909. <li>MultiQueryRetriever</li>
  1910. </ul>
  1911. <blockquote>
  1912. <p>功能:它借助 LLM 自动生成多个语义等价的改写查询,把用户的问题扩展成多个角度,然后对每个改写进行检索,最后合并结果,以提高召回率。 </p>
  1913. <p>特点:</p>
  1914. <ul>
  1915. <li>使用语言模型生成查询的多种表达方式</li>
  1916. <li>从向量存储中检索所有变体的结果并合并</li>
  1917. <li>提高召回率,适合复杂查询</li>
  1918. </ul>
  1919. <p>适用场景:</p>
  1920. <ul>
  1921. <li>查询表达不明确或需要覆盖多种语义</li>
  1922. <li>提高检索的全面性
  1923. </li>
  1924. </ul>
  1925. </blockquote>
  1926. <ul>
  1927. <li>EnsembleRetriever</li>
  1928. </ul>
  1929. <blockquote>
  1930. <p>功能:结合多种检索器(如 BM25 和向量存储),融合结果。</p>
  1931. <p>特点:</p>
  1932. <ul>
  1933. <li>结合关键词搜索和语义搜索的优点</li>
  1934. <li>支持加权融合,调整不同检索器的权重</li>
  1935. <li>提高召回率和精准度</li>
  1936. </ul>
  1937. <p>适用场景:</p>
  1938. <ul>
  1939. <li>需要综合关键词和语义的搜索</li>
  1940. <li>复杂查询场景
  1941. </li>
  1942. </ul>
  1943. </blockquote>
  1944. <ul>
  1945. <li>ContextualCompressionRetriever</li>
  1946. </ul>
  1947. <blockquote>
  1948. <p>功能:对检索结果进行压缩,提取最相关的内容 </p>
  1949. <p>特点:</p>
  1950. <ul>
  1951. <li>使用语言模型对检索到的文档进行重新排序或精炼</li>
  1952. <li>减少无关内容,提高结果质量</li>
  1953. <li>增加计算开销,但提升精准度</li>
  1954. </ul>
  1955. <p>适用场景:</p>
  1956. <ul>
  1957. <li>文档内容冗长,需要提取关键信息</li>
  1958. <li>提高问答系统的答案质量
  1959. </li>
  1960. </ul>
  1961. </blockquote>
  1962. <ul>
  1963. <li>Custom Retriever</li>
  1964. </ul>
  1965. <blockquote>
  1966. <p>功能:开发者可以自定义检索逻辑,适配特定数据源或算法 </p>
  1967. <p>特点:</p>
  1968. <ul>
  1969. <li>继承 BaseRetriever 类,实现 get_relevant_documents 方法</li>
  1970. <li>支持任意数据源(如数据库、API)</li>
  1971. </ul>
  1972. <p>适用场景:</p>
  1973. <ul>
  1974. <li>特定领域的数据源(如内部数据库)</li>
  1975. <li>自定义检索算法
  1976. </li>
  1977. </ul>
  1978. </blockquote>
  1979. <h2 id="agents">八、Agents<a class="headerlink" href="#agents" title="Permanent link">¶</a></h2>
  1980. <h3 id="1-agent">1 Agent 概念<a class="headerlink" href="#1-agent" title="Permanent link">¶</a></h3>
  1981. <p>Agent(智能体)是一种能够感知环境、进行决策和执行动作的智能实体。不同于传统的人工智能,Agent 具备通过主动思考、调用工具去逐步完成给定目标的能力。</p>
  1982. <p>为什么要调用工具?</p>
  1983. <ul>
  1984. <li>因为大模型虽然非常强大,但是也具备一定的局限性,比如不能回答实时信息、处理数学逻辑问题仍然非常的初级等等。因此,可以借助第三方工具来辅助大模型的应用。</li>
  1985. </ul>
  1986. <p>从大模型的角度来看,<strong>Agent其实就是基于大模型的语义理解和推理能力,让大模型拥有解决复杂问题时的任务规划能力,并调用外部工具来执行各种任务,利用向量数据库保留“记忆”的一个智能体</strong>。</p>
  1987. <blockquote>
  1988. <p>Agent = 大模型 + 任务规划(Planning) + 使用外部工具执行任务(Tools&amp;Action) + 记忆(Memory)</p>
  1989. <p>把Agent比作一个人的话,<strong>他应该有大脑(语义理解、存储记忆、推理规划、专业知识)、五官(接收文本、视觉输入、听觉输入等)、四肢(使用工具完成各种具体任务)等主要部件</strong></p>
  1990. </blockquote>
  1991. <hr>
  1992. <p><strong>工作流程概述:</strong></p>
  1993. <ul>
  1994. <li>用户提出任务。</li>
  1995. <li>Agent 启动: 将用户输入与预设的“提示词模板”结合,并结合当前的“上下文”和“变量”,形成一个完整的输入发送给大模型。</li>
  1996. <li>大模型思考与决策 (循环):<ul>
  1997. <li>大模型接收输入后,根据其内置的逻辑和提示词的指导,进行“思考”。</li>
  1998. <li>它会判断完成当前任务是需要继续使用工具来获取更多信息/执行操作,还是已经可以直接生成最终答案。</li>
  1999. <li>如果需要工具: 大模型会根据任务需求和对工具的描述,选择合适的工具,并生成执行该工具所需的输入参数。这些参数通常会从上下文或变量中提取。</li>
  2000. <li>工具执行: 选定的工具被调用,执行其功能。</li>
  2001. <li>结果反馈: 工具执行的结果会返回给 Agent,并被用来更新“上下文”和“变量”。</li>
  2002. <li>循环: Agent 将更新后的“上下文”、“变量”以及工具执行结果再次反馈给大模型,大模型继续进行新一轮的“思考-行动”循环,直到任务完成。</li>
  2003. <li>如果直接回答: 当大模型判断任务已完成,或无需额外工具即可回答时,它会生成最终的答案。</li>
  2004. </ul>
  2005. </li>
  2006. <li>用户输出: 最终答案被呈现给用户。</li>
  2007. </ul>
  2008. <h3 id="2-agent">2 Agent关键组成部分<a class="headerlink" href="#2-agent" title="Permanent link">¶</a></h3>
  2009. <p><img alt="image-20250705115745718" src="assets/image-20250705115745718.png"></p>
  2010. <ul>
  2011. <li>
  2012. <p>任务规划(Planning)</p>
  2013. <p>Agent需要提前将一项复杂任务拆解为多个更小、更易于处理的子任务,从而实现对复杂任务的高效处理</p>
  2014. </li>
  2015. <li>
  2016. <p>长短期记忆(Memory)</p>
  2017. <p>聊天上下文,长期保留和回忆信息</p>
  2018. </li>
  2019. <li>
  2020. <p>工具&amp;执行(Tools&amp;Action)</p>
  2021. <p>根据拆分好的子任务,调用外部提供好的专业API解决专业问题,完成一个个具体的子任务,并把处理结果返回给大模型</p>
  2022. </li>
  2023. </ul>
  2024. <h3 id="3-langchainagent">3 langchain实现Agent<a class="headerlink" href="#3-langchainagent" title="Permanent link">¶</a></h3>
  2025. <p>LangChain 提供了不同类型的代理(主要罗列一下三种):</p>
  2026. <ul>
  2027. <li>
  2028. <p><strong>Zero-shot ReAct Description</strong></p>
  2029. <ul>
  2030. <li>
  2031. <p>基于 <strong>ReAct 框架</strong>(推理 + 行动),仅依赖工具的 <strong>描述</strong> 来决定调用哪个工具。</p>
  2032. </li>
  2033. <li>
  2034. <p>特点:无需额外示例(zero-shot),但 <strong>不具备记忆能力</strong>,每次推理都独立进行。</p>
  2035. </li>
  2036. <li>
  2037. <p>使用场景:简单任务,工具选择完全靠工具描述即可。</p>
  2038. </li>
  2039. </ul>
  2040. </li>
  2041. <li>
  2042. <p><strong>Structured Chat Zero-shot ReAct Description</strong></p>
  2043. <ul>
  2044. <li>
  2045. <p>同样基于 <strong>ReAct 框架</strong>,但可以处理 <strong>结构化输入</strong>,即支持带多个参数的工具(类似函数调用)。</p>
  2046. </li>
  2047. <li>
  2048. <p>特点:不仅能像第一种代理那样根据描述选择工具,还能正确组织并传递复杂参数。</p>
  2049. </li>
  2050. <li>
  2051. <p>使用场景:调用接口类工具、需要多参数输入的任务。</p>
  2052. </li>
  2053. </ul>
  2054. </li>
  2055. <li>
  2056. <p><strong>Conversational ReAct Description</strong></p>
  2057. <ul>
  2058. <li>
  2059. <p>在 ReAct 框架基础上,增强了 <strong>对话记忆能力</strong>。</p>
  2060. </li>
  2061. <li>
  2062. <p>特点:能根据上下文对话历史来做出工具选择和回应,更适合持续性对话场景。</p>
  2063. </li>
  2064. <li>
  2065. <p>使用场景:多轮对话,用户可能引用之前的内容或需要长期上下文跟踪。</p>
  2066. </li>
  2067. </ul>
  2068. </li>
  2069. </ul>
  2070. <hr>
  2071. <p>LangChain 中集成了很多工具,可以通过下面的方式进行查询:</p>
  2072. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_community.agent_toolkits.load_tools</span><span class="w"> </span><span class="kn">import</span> <span class="n">get_all_tool_names</span>
  2073. <span class="n">results</span> <span class="o">=</span> <span class="n">get_all_tool_names</span><span class="p">()</span>
  2074. <span class="nb">print</span><span class="p">(</span><span class="n">results</span><span class="p">)</span>
  2075. </code></pre></div>
  2076. <p>运行结果:</p>
  2077. <div class="highlight"><pre><span></span><code>['sleep', 'wolfram-alpha', 'google-search', 'google-search-results-json', 'searx-search-results-json', 'bing-search', 'metaphor-search', 'ddg-search', 'google-books', 'google-lens', 'google-serper', 'google-scholar', 'google-finance', 'google-trends', 'google-jobs', 'google-serper-results-json', 'searchapi', 'searchapi-results-json', 'serpapi', 'dalle-image-generator', 'twilio', 'searx-search', 'merriam-webster', 'wikipedia', 'arxiv', 'golden-query', 'pubmed', 'human', 'awslambda', 'stackexchange', 'sceneXplain', 'graphql', 'openweathermap-api', 'dataforseo-api-search', 'dataforseo-api-search-json', 'eleven_labs_text2speech', 'google_cloud_texttospeech', 'read_file', 'reddit_search', 'news-api', 'tmdb-api', 'podcast-api', 'memorize', 'llm-math', 'open-meteo-api', 'requests', 'requests_get', 'requests_post', 'requests_patch', 'requests_put', 'requests_delete', 'terminal']
  2078. </code></pre></div>
  2079. <hr>
  2080. <p>接下来,通过一个示例来学习Agent的基本使用。</p>
  2081. <ul>
  2082. <li>问题1:计算一下300的25%是多少?</li>
  2083. <li>问题2:请帮我介绍一下故宫</li>
  2084. </ul>
  2085. <p>示例代码:</p>
  2086. <blockquote>
  2087. <p>需要提前安装 wikipedia</p>
  2088. <p>pip install wikipedia</p>
  2089. </blockquote>
  2090. <div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">langchain_core.messages</span><span class="w"> </span><span class="kn">import</span> <span class="n">HumanMessage</span>
  2091. <span class="kn">from</span><span class="w"> </span><span class="nn">langgraph.checkpoint.memory</span><span class="w"> </span><span class="kn">import</span> <span class="n">MemorySaver</span>
  2092. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain.agents</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_agent</span>
  2093. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_community.agent_toolkits.load_tools</span><span class="w"> </span><span class="kn">import</span> <span class="n">load_tools</span>
  2094. <span class="kn">from</span><span class="w"> </span><span class="nn">langchain_openai</span><span class="w"> </span><span class="kn">import</span> <span class="n">ChatOpenAI</span>
  2095. <span class="kn">import</span><span class="w"> </span><span class="nn">os</span>
  2096. <span class="c1"># 实例化模型</span>
  2097. <span class="n">model</span> <span class="o">=</span> <span class="n">ChatOpenAI</span><span class="p">(</span>
  2098. <span class="n">base_url</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'base_url'</span><span class="p">,</span><span class="s1">'https://dashscope.aliyuncs.com/compatible-mode/v1'</span><span class="p">),</span>
  2099. <span class="n">model</span><span class="o">=</span><span class="s1">'qwen-plus'</span><span class="p">,</span>
  2100. <span class="n">openai_api_key</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'api_key'</span><span class="p">,</span><span class="s1">'sk-XXXXXXXX'</span><span class="p">),</span>
  2101. <span class="n">max_tokens</span><span class="o">=</span><span class="mi">1000</span><span class="p">,</span>
  2102. <span class="n">temperature</span><span class="o">=</span><span class="mi">0</span>
  2103. <span class="p">)</span>
  2104. <span class="c1"># Create the agent</span>
  2105. <span class="n">memory</span> <span class="o">=</span> <span class="n">MemorySaver</span><span class="p">()</span>
  2106. <span class="n">tools</span> <span class="o">=</span> <span class="n">load_tools</span><span class="p">([</span><span class="s1">'wikipedia'</span><span class="p">,</span> <span class="s1">'llm-math'</span><span class="p">],</span> <span class="n">llm</span><span class="o">=</span><span class="n">model</span><span class="p">)</span>
  2107. <span class="n">agent_executor</span> <span class="o">=</span> <span class="n">create_agent</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">tools</span><span class="p">,</span> <span class="n">checkpointer</span><span class="o">=</span><span class="n">memory</span><span class="p">)</span>
  2108. <span class="c1"># Use the agent</span>
  2109. <span class="n">config</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"configurable"</span><span class="p">:</span> <span class="p">{</span><span class="s2">"thread_id"</span><span class="p">:</span> <span class="s2">"abc123"</span><span class="p">}}</span>
  2110. <span class="k">for</span> <span class="n">chunk</span> <span class="ow">in</span> <span class="n">agent_executor</span><span class="o">.</span><span class="n">stream</span><span class="p">(</span>
  2111. <span class="p">{</span><span class="s2">"messages"</span><span class="p">:</span> <span class="p">[</span><span class="n">HumanMessage</span><span class="p">(</span><span class="n">content</span><span class="o">=</span><span class="s2">"计算一下300的25%是多少?"</span><span class="p">)]},</span> <span class="n">config</span>
  2112. <span class="p">):</span>
  2113. <span class="nb">print</span><span class="p">(</span><span class="n">chunk</span><span class="p">)</span>
  2114. <span class="nb">print</span><span class="p">(</span><span class="s2">"----"</span><span class="p">)</span>
  2115. <span class="c1"># for chunk in agent_executor.stream(</span>
  2116. <span class="c1"># {"messages": [HumanMessage(content="大熊猫是哪个国家的国宝?")]}, config</span>
  2117. <span class="c1"># ):</span>
  2118. <span class="c1"># print(chunk)</span>
  2119. <span class="c1"># print("----")</span>
  2120. </code></pre></div>
  2121. <p>运行结果:</p>
  2122. <p><img alt="1768397211211" src="assets/1768397211211.png"></p>
  2123. <blockquote>
  2124. <p>参考官网 <a href="https://python.langchain.com/docs/how_to/custom_tools/">https://python.langchain.com/docs/how_to/custom_tools/</a></p>
  2125. </blockquote>
  2126. <h2 id="langchain">九、LangChain使用场景<a class="headerlink" href="#langchain" title="Permanent link">¶</a></h2>
  2127. <ul>
  2128. <li>个人助手</li>
  2129. <li>基于文档的问答系统</li>
  2130. <li>聊天机器人</li>
  2131. <li>Tabular数据查询</li>
  2132. <li>API交互</li>
  2133. <li>信息提取</li>
  2134. <li>文档总结</li>
  2135. </ul>
  2136. <h2 id="_3">十、本节小结<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
  2137. <p>本章主要介绍了LangChain的基本组件及使用方式。</p>
  2138. <h2 id="_4">十一、本节作业<a class="headerlink" href="#_4" title="Permanent link">¶</a></h2>
  2139. <h3 id="1-1">1 作业1<a class="headerlink" href="#1-1" title="Permanent link">¶</a></h3>
  2140. <ul>
  2141. <li>题目1:什么是LangChain?请解释其核心组件和设计思想。</li>
  2142. <li>题目2:解释LangChain中的链(Chain)概念,并介绍主要的链类型。</li>
  2143. <li>题目3:解释LangChain中的Prompts概念,并介绍主要类型。</li>
  2144. <li>题目4:实现LangChain中的output_parsers的具体使用方式</li>
  2145. </ul>
  2146. <h3 id="2-2">2 作业2<a class="headerlink" href="#2-2" title="Permanent link">¶</a></h3>
  2147. <ul>
  2148. <li>题目1:什么是Memory组件?请解释LangChain中不同类型的记忆机制。</li>
  2149. <li>题目2:解释LangChain中的提示工程及其最佳实践。</li>
  2150. <li>题目3:LangChain的Document Loaders?请介绍其功能和主要类型。</li>
  2151. <li>题目4 :什么是LangChain的代理(Agent)?请说明其工作原理和应用。</li>
  2152. </ul>
  2153. </article>
  2154. </div>
  2155. <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
  2156. </div>
  2157. </main>
  2158. <footer class="md-footer">
  2159. <div class="md-footer-meta md-typeset">
  2160. <div class="md-footer-meta__inner md-grid">
  2161. <div class="md-copyright">
  2162. <div class="md-copyright__highlight">
  2163. © EnterpriseKB-RAG 2026. Internal knowledge base demo site.
  2164. </div>
  2165. Made with
  2166. <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
  2167. Material for MkDocs
  2168. </a>
  2169. </div>
  2170. </div>
  2171. </div>
  2172. </footer>
  2173. </div>
  2174. <div class="md-dialog" data-md-component="dialog">
  2175. <div class="md-dialog__inner md-typeset"></div>
  2176. </div>
  2177. <script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "\u5df2\u590d\u5236", "clipboard.copy": "\u590d\u5236", "search.result.more.one": "\u5728\u8be5\u9875\u4e0a\u8fd8\u6709 1 \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.more.other": "\u5728\u8be5\u9875\u4e0a\u8fd8\u6709 # \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.none": "\u6ca1\u6709\u627e\u5230\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.one": "\u627e\u5230 1 \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.other": "# \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.placeholder": "\u952e\u5165\u4ee5\u5f00\u59cb\u641c\u7d22", "search.result.term.missing": "\u7f3a\u5c11", "select.version": "\u9009\u62e9\u5f53\u524d\u7248\u672c"}, "version": null}</script>
  2178. <script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
  2179. <script src="../javascripts/extra.js"></script>
  2180. <script src="../javascripts/mathjax.js"></script>
  2181. <!-- <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>-->
  2182. <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
  2183. </body>
  2184. </html>