Галоўная / Артыкулы / Практычныя прытамулкі: Стварэнне агента падтрымкі LEPA з LangGraph

Практычныя прытамулкі: Стварэнне агента падтрымкі LEPA з LangGraph

Практычныя прыказкі: стварэнне агента падтрымкі LEPA з LangGraph — контракты, перакантрольванні та слоты для коду для команд, якія викорыстоўваюць гэты шаблон.

2082 слоў

Існавайце гэта як перапрацоўаны варыянт ідэй з документа “Building LEPA Support Agent with LangGraph” для аператараў: чыстыя этапы, арганізаваныя блакі коду і прыметкі з восстанавлення, якія застаюцца пасля перадачы задання. Этап “Адгледжэнне” найкраща працюе, калі яго розглядаць як меркаваную плошчу. Запісаце адна ідеальная транскрыпцыя, адзін прыклад неудачы і прыметкі з вярнення да пачатковага стану прычаму, перш чым расширваць масштабы. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісьць крок не выходзіце, прычына неудачы павінна вказваць на адную адпаведальнасць, а не на заплутаны ланцюг заданняў.

Калі саме трэба было, каб першы граф выканаў

Для тагу «What you wanted the stage» неабяжна прадзецьваваць інпуты, власніка крока і крэтыяры выходу пры змены коду. Аператары должны магчымаць перзапуск крока з вядомай точкі контролю, не падозрываючы схованы статус. Спрыяйце гэтам кроку як дагавору межа інпутамі і падтвердзенымы выходамі. Даўце назвы артыфактам, прадзецьвавайце крэтыяры успеху і адмовіцеся ад тыхоўскага частковага завершэння. Заставіце людзкую апраўду на тых этапах, дзе выкорыстоўваюцца грошы або зміняюцыся даныя праработкі. Кампайляванне на час не ўзроўнаваецца з завершанням бізнес-процэсу.

User message
     ↓
Notice who is speaking (teacher / admin / unknown)
     ↓
Classify the topic (grades, login, …)
     ↓
Too vague? Ask a clarifying question
     ↓
Otherwise continue toward docs + an answer

Наладжэнне проекту (задумана як нудная частка)

Для настаўлення проекту спачатку неабходна ўсвядомлена стадія роботы: трэба визначыць вхідныя даны, адпаведальнага за кожны крок і критэрыя завершэння пры перадзмене коду. Аператары должны магчыма было перзапускаць крок з вядомай точкі контролю, не падозрываючы прыхованы стан системы. Запісваць трэба час выконання і вартасць токеноў або запытав, палягаючы ўсё гэта рядом з функцыйнальнымі рынкамі. Візуабельнасць вартасцей з самага пачатку запобегае неспакойным рахункам, калі процес пераходзіць з дэмовай среды ў спакульную. Неабходна людская апрацоўка тых крокаў, якія выкорыстоўваюць грошы або зміняюць даны у працэсе виробніцтва. Працэс складання коду сам по сабе не гарантуе повнайасці бізнес-процэсаў.

PRJ-02/
├── app/
│   ├── state.py      # SupportState
│   ├── graph.py      # StateGraph wiring
│   ├── agents/       # intake, knowledge, support
│   ├── nodes/        # classify, ask_clarification
│   └── tools/        # search_knowledge (next article)
├── knowledge/        # LEPA support Markdown
├── api/              # FastAPI (later article)
└── tests/

Стан: об’ект, які пераходзіць через граф

Для стану об’екта на певным этапе неабяцкова ўзначыць вхідныя даны, адпаведальнага за крок і крэтыры завершэння пры змяне коду. Аперацыйныя працавнікі павінны магчымае перазапускаць крок з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Конфігурацыю трэба залічваць праза код аплікацыі. Файлы сераўнавання, храненні секрэтных данных і флагі функцияў павінны знаходзіцца ў адном месцы, якое аперацыйныя працавнікі можуць пераглядаць, не чытаючы весь ланцуг. Прызначайце людскія апраўленні для рэлей, якія витрачаюць грошы або зменяюць даны у працэйнай сістэме. Падключэння ў час компіляцыі не є прамаравам полнай адпаведнасці бізнесу. Для стану об’екта на певным этапе неабяцкова ўзначыць вхідныя даны, адпаведальнага за крок і крэтыры завершэння пры змяне коду. Аперацыйныя працавнікі павінны магчымае перазапускаць крок з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Валічыце маленькія, тэставальныя елементы пра велікія скрыпты. Калі крок не выйшоў, прычына неабяцкова паказваць на адну адпаведальнасць, а не на заплутаны ланцуг задач.

e.

messages                 # conversation turns (add_messages reducer)
user_role                # teacher / admin / unknown
issue_category           # grades, authentication, …
clarification_needed     # should we ask for more detail?
clarification_question   # what we ask
retrieved_documents      # doc snippets (later step)
final_answer             # what we return to the user
conversation_summary     # reserved for later — unused in v1
messages: Annotated[list, add_messages]
{"user_role": "teacher"}
{"issue_category": "grades", "clarification_needed": False}

Узлы: по адначоўкі на кожны

Калі працуеце з узламі, дзе кожны наступны этап выпрацоўвае адначоўку, спачатку запісайце угоду: неабходныя вхідныя даны, сигнал пра успех і тое, што выходзіць у разе частковай нявыполненасці. Такі список контролю дапамагае залічыць пазнейшыя змены ў кодзе. Спрыймайце гэты этап як угоду між вхіднымі данымі і перакананымі выходнымі рэзультатамі. Дайце назвы артыфактам, задаць критэрыя успеху і не падзеўляйцеся частковым завершэнням без паведамлення. Зробіце контрольную точку пасля дорогіх крокаў. Програма не должна занова ставіць плату за той самы вызыв LLM, калі аператар праказвае пазнейшы узел.

(state) → partial update

Прыем даных

Калі працюеце на стадыі приймання данных, спачатку запісайце угоду: неабяжлівыя даны, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список перакладзець пазнейшыя змены коду ў правільныя рамкі. Запісвайце часы выкарыстоўвання та кост токена або запыту праза функцыйнальныя рэзултаты. Відразувая візуабельнасць костаў запобегае неспакойным рахункам, калі процес пераходзіць з дэмаверсіі ў спяльныя среды. Зробіце перапаконтаванне пасля дорогіх крокаў. Система адновлення не должна зноў нараховваць косты за той самы вызыв LLM, калі аператар прабуе зноў запрацаваць пазнейшы вузел.

Класіфікацыя

Калі працюеце над стадзіяй Classify, спачатку запісайце контракт: неабяжлівыя даны, сігнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список пераконвае ў тым, што пазнейшыя змены коду будуць чыстымі. Зберагаеце настройкі за межамі коду прыемліка. Файлы сераўнавання, храненні секрэтных данных і флагі функцый належаць у аднам месца, якое аператары можаць пераглядаць без неабяжлівага чытання всей структуры. Стварайце контрольныя пункты пасля дорогіх крокаў. Функцыя вярнення не должна зноў выклікаць той самы календар LLM, калі аператар прабуе зноў запрацаваць з пазнейшым вузлам. Калі працюеце над стадзіяй Classify, спачатку запісайце контракт: неабяжлівыя даны, сігнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список пераконвае ў тым, што пазнейшыя змены коду будуць чыстымі. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі крок не выйшаў, прычына нявыпання должна вказываць на адну адпаведальнасць, а не на заплутаную лінію обробкі.

Запытайце адзначэння

Этап адкларацыі запиту працюе наяўней, калі яго спрыяваць як мерыемую паверхню. Зафіксавайце адны ідеальны прыклад, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштаб. Спрыяйце гэтам этапу як кантракту межа вхіднымі даннымі і паверыжанымі выходнымі рэзультатамі. Дайце назвы артыфактам, задаць критэрыя успеху і адмовіцеся ад тыхоўскага частковага завершэння. Зберагачыце стан графа ў простам і типаванам формате. Вярнутыя структуры маскуюць, який вузел запісаў канкрэтны поле, і спакшуюць возобнавленне роботы пасля перарываў.

Знанні + падтрымка

Этап падкісткі гэтых навыкаў працюе наякша, калі яго спрыяваць як вимерную плошчу. Запісаўце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану, перш чым расширваць сферу дзеяння. Запісвайце часы выканання і кост токеноў або запытаў па боку ад функцыйнаых рэзультатаў. Візуабельнасць костаў з самага пачатку запобегае неспакойным рахункам, калі процес пераходзіць з дэмаверсіі ў спяльныя сераўы. Храніце стан графа ў простам і типаваным формате. Вкладзеныя блокі маскуюць інфармацыю пра тое, який вузел запісаў кожны поле, і спакшваюць продажчык роботы пасля перарываў.

Грані: як адбываецца кантроль

Механізм керавання рухамі на сцэне працюе найкраща, калі яго розглядаць як вимерную паверхню. Запісаце адзін ідеальны прыклад, адзін прыклад неудачы і прыметкі па вярнэнне да пачатковага стану пры расшырэнні масштаба. Зберагачыце настройкі пазначэнныя за межамі коду прыемленае. Файлы сэраўнавання, хранільнікі секрэтных дадзеных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куды аператары можаць адбавляць аудыт без неабяжнага чытання всіх дадзеных. Зберагачыце стан графа ў простам і типаванам формате. Вярнутыя структуры дадзеных маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спакойваюць працу пасля перерываў.

Звычайныя рэшткі

Этап Normal edges працюе найкраща, калі яго розглядаць як вимерную паверхню. Зафіксавце адна «золатая» транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Дакументавайце як шлях успеху, так і шлях вярнэння. Перапрыбуткі, людзкія контрольныя пункты і обработка некоректных паведамленняў є частью продукту, а не наступным етапам дорабкі. Храніце стан графа у простам і типаваным формате. Вкладзеныя блокі маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спакоююць працу пасля перарываў.

graph.add_edge(START, "intake")
graph.add_edge("intake", "classify")
graph.add_edge("knowledge", "support")
graph.add_edge("support", END)
When this node finishes, always go there next.

Умовныя рэглі ўзьязку

Этап умоўна-залежных граней працюе найэфектывней, калі яго спрыяваць як мерыемую паверхню. Запісаце адна ідеальная версія, адзін прыклад неудачы і прыметку па адкату перш чым расширваць масштаб. Валіце малыя, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выходзіць, прычына неудачы павінна вказываць на адную адповядальнасць, а не на заплутаны ланцюг задач. Рэзультаты роботы графа трэба падтрымваць у простам і типаваным формате. Вкладзеныя структуры маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спакоююць продовжэнне роботы пасля перерываў.

def route_after_classify(state: SupportState) -> Literal["clarify", "continue"]:
    if state.get("clarification_needed"):
        return "clarify"
    return "continue"
graph.add_conditional_edges(
    "classify",
    route_after_classify,
    {
        "clarify": "ask_clarification",
        "continue": "knowledge",
    },
)
"help"  → clarify → ask_clarification → END
"How do I enter grades?" → continue → knowledge → support → END

Пачатак і канец

Этапы START і END работаюць наяўней, калі іх спрыяваць як мерыемую паверхню. Зафіксавайце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштаб. Спрыяйце гэтым этапам як кантракту межа вхіднымі даннымі і паверыжанымі выходнымі рэзультатамі. Дайце назвы артыфактам, задаць критэрыя успеху і не падзеўляйцеся частым, непূরным выкананням задач. Зберагаюце стан графа ў простам і типаваным формате. Вкладзеныя блокі маскуюць інфармацыю пра тое, який вузел запісаў кожны поле, і спакшуюць возз'еднанне пасля перерываў.

START = where the runtime begins
END   = where this run stops
START → intake → classify → …
…
ask_clarification → END
support → END

Полная топалогія (як ёй было створана)

Паўная топалогія як стадыя працюе найэфектывней, калі яе спрыяваць як вимерную паверхню. Запісаўце адна «золатая» транскрыпцыя, адин прыклад неудачы і прыметку па поверненню да пачатковага стану пры расшырэнні масштаба. Запісвайце часы выканання і кост токена або запиту паляглыя ўжо разам з функцыйнальнымі рэзультатамі. Відразлівае паказанне костаў з самага пачатку запобегае неспакойным рахункам, калі траекторыя пераходзіць з дэмаверсіі ў спакульнаныя сераўысы.

START
  → intake
  → classify
  → conditional
        ├─ clarify  → ask_clarification → END
        └─ continue → knowledge → support → END

Як запит праходзіць через граф

Прыцэпленне про тое, як запит пераходзіць па стадіях, працуе наўжоўды лепш, калі яго спрыяглядаць як вимерную структуру. Зафіксавайце адны ідеальны прыклад роботы, адзін прыклад неудачы і запіс пра вярнэнне да поперадньего стану, прычым расшырюючы сферу дзеяння. Зберагаўце настройкі праза код аплікацыі. Файлы сяродавішча, хранільнікі секрэтных дадзеных і пазначкі функцый должны знаходзіцца ў аднам месцы, куда аператары можуць адбавляць контроль без неабяжнага чытання всей структуры. Зберагаўце стан структуры у простам і типаваным формате. Вярстакованыя блокі дадзеных маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спакоююць продажчыку роботы пасля перарываў.

Чыстая запитанне

Этап чыстага запиту працюе найкраща, калі яго спрыяваць як мерыемую структуру. Запісаўце адна ідеальная версія рэспакт, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Дакументаваце як успішны, так і вярнучыся шляхы. Перапрыбуткі, людзкія контралі і обработка некоректных паведамленняў ёсць частью продукту, а не пасляднім дапрацоўкам. Храніце стан графа ў простым і типаваным формате. Вярнутыя блокі маскуюць, який вузел запісаў кожны поле, і спакшуюць продыржанне роботы пасля перарываў.

User: "Why aren't grades showing?"
        ↓
intake        → user_role = unknown (unless they said teacher/admin)
        ↓
classify      → issue_category = grades, clarification_needed = False
        ↓
route         → "continue"
        ↓
knowledge     → search docs (next article)
        ↓
support       → final_answer
        ↓
END

Нечысты запит

User: "help"
        ↓
intake
        ↓
classify      → unknown + clarification_needed = True
        ↓
route         → "clarify"
        ↓
ask_clarification → asks which LEPA area
        ↓
END

compile() і invoke(): момент выканання

return graph.compile(checkpointer=checkpointer)
from langchain_core.messages import HumanMessage
from app.graph import app_graph
result = app_graph.invoke(
    {"messages": [HumanMessage(content="How do I enter grades?")]}
)
print(result["final_answer"])

Што вы намеравана адклалі

Вывык

Супакі

Чэк-ліст для эксплуатацыі