Галоўная / Артыкулы

Продакшн-агенты на базе AI з FastAPI, LangGraph і чыстай архітэктуры.

Стварэнне агентаў AI з FastAPI і LangGraph па прынцыпах чыстай архітэктуры: граніцы портамі і шарамі, тыпаваны стан графа, сервісы, якія можна тэставаць, форма развяртання.

Выдавец: REACTAPP.TOP13 хв чытання3005 слоў

Крыніцы: How I Structure Production AI Agents with FastAPI, LangGraph and Clean Architecture

У гэтым керавану практычнаю праця перакладзець парадокс з сыр'ём да рабочай сістэмы для: «Як я структурую агентаў AI для прыметнай вырабоцтва з FastAPI, LangGraph і чыстай архітэктуры». Акцэнт ставяцца на практычныя крокі, чысткія пераконтаванні і код, які можна проста дадзець у рэпазітарый без неабяснення меты. Для адгледзення, перш чым зменяць код, неабходна візначыць вхідныя даны, адпаведальнага за крок і крытэрыя завершэння. Аперацыёныя працавікі должны магчымае перадзець крок з вядомай точкі контролю без неабяснення схованага стану. Конфігурацыю трэба залічыць пазначкай ад коду прыемленае. Файлы сераўіса, храненні секрэтных дадзенаў і флагі функцыяў должны знаходзіцца ў аднам месцы, якое працавікі можу аўдытуваты без чытання всей структуры.

@router.post("/suppliers")
async def create_supplier(request: SupplierRequest):
    policies = opensearch.search(
            index="supplier-policies",
            query=request.description,
        )
        response = bedrock.converse(
            modelId=MODEL_ID,
            messages=build_messages(request, policies),
        )
        supplier = Supplier(
            name=request.name,
            tax_id=request.tax_id,
        )
        db.add(supplier)
        db.commit()
        sqs.send_message(
            QueueUrl=SUPPLIER_QUEUE,
            MessageBody=serialize(supplier),
        )
        return {"status": "created"}

FastAPI — гэта інтэрфейс, а не сама прыемленае

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

@router.post("/suppliers")
async def create_supplier(
    request: CreateSupplierRequest,
    use_case: CreateSupplierUseCase = Depends(
        get_create_supplier_use_case
    ),
):
    command = CreateSupplierCommand(
        name=request.name,
        tax_id=request.tax_id,
        country=request.country,
    )

    result = await use_case.execute(command)
    return CreateSupplierResponse.from_result(result)
HTTP Request
     ↓
   FastAPI
     ↓
 Application
     ↓
   Domain
     ↓
    Ports
     ↓
  Adapters

Прыемліка вярбуецца з можнасцямі, а не з тэхналогіямі

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

class CreateSupplierUseCase:
    def __init__(
        self,
        repository: SupplierRepository,
        policy_service: SupplierPolicyService,
        event_publisher: EventPublisher,
    ):
        self.repository = repository
        self.policy_service = policy_service
        self.event_publisher = event_publisher
    async def execute(
        self,
        command: CreateSupplierCommand,
    ) -> Supplier:
        existing = await self.repository.find_by_tax_id(
            command.tax_id
        )
        if existing:
            raise SupplierAlreadyExists(command.tax_id)
        policy = await self.policy_service.evaluate(
            country=command.country
        )
        supplier = Supplier.create(
            name=command.name,
            tax_id=command.tax_id,
            country=command.country,
            requires_approval=policy.requires_approval,
        )
        await self.repository.add(supplier)
        await self.event_publisher.publish(
            SupplierCreated(supplier.id)
        )
        return supplier

Порты ствараюць межу

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

ph.

from typing import Protocol

class SupplierRepository(Protocol):
    async def find_by_tax_id(
        self,
        tax_id: str,
    ) -> Supplier | None:
        ...
    async def add(
        self,
        supplier: Supplier,
    ) -> None:
        ...

class PolicyRetriever(Protocol):
    async def retrieve(
        self,
        query: str,
    ) -> list[PolicyDocument]:
        ...

class LLMProvider(Protocol):
    async def reason(
        self,
        context: AgentContext,
    ) -> AgentDecision:
        ...

class EventPublisher(Protocol):
    async def publish(
        self,
        event: DomainEvent,
    ) -> None:
        ...
SupplierRepository
PolicyRetriever
LLMProvider
EventPublisher
PostgreSQL
Amazon OpenSearch
Amazon Bedrock
AWS SQS

Дзе належы Amazon Bedrock

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

class BedrockLLMProvider(LLMProvider):
    def __init__(self, client, model_id: str):
        self.client = client
        self.model_id = model_id
    async def reason(
        self,
        context: AgentContext,
    ) -> AgentDecision:
        response = self.client.converse(
            modelId=self.model_id,
            messages=build_messages(context),
        )
        return map_bedrock_response(response)
Application
     ↓
LLMProvider
     ↑
BedrockLLMProvider

Дзе належы RAG

Ёнколі трэба вялічы, дзе мае быць RAG, перш чым зменіць код, неабходна ўзначыць вхідныя даны, адпаведальнага за крок і крытэрыя завершэння. Аперацыі должны магчымае перадзеяць крок з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Лепш выбіраць маленькія, тэставаныя елементы замест абмежлівых скрыптав. Калі крок не выйшаў, прычына нехасабносты павінна вказываць на адзіну адпаведальнасць, а не на заплутаны ланцужок задач. Пасля першага пакета дадзеных трэба перагледзець прыкладны артыкул. Засобы тыпу Cypher дапамагаюць выявіць змены ў атрыбутах і відсутныя характэрыстыкі дарожэй, чым тэсты чату ад пачатку да канца.

FastAPI
   ↓
OpenSearch
   ↓
LLM
class OpenSearchPolicyRetriever(PolicyRetriever):
    def __init__(
        self,
        opensearch_client,
        embedding_provider,
    ):
        self.client = opensearch_client
        self.embedding_provider = embedding_provider
    async def retrieve(
        self,
        query: str,
    ) -> list[PolicyDocument]:
        vector = await self.embedding_provider.embed(query)
        results = self.client.search(
            index="supplier-policies",
            body=build_vector_query(vector),
        )
        return map_documents(results)

RAG дае кантэкст. Ён не прыймае рашэння.

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

Можна аўдытаваць, не чытаючы весь граф.

RAG
 ↓
LLM
 ↓
"Looks fine"
 ↓
Create Supplier
RAG
 ↓
Relevant Context
 ↓
Agent Reasoning
 ↓
Application
 ↓
Domain Rules
 ↓
Decision

Дзе мае знаходзіцца LangGraph

Шчодо таго, дзе мае знаходзіцца LangGraph, неабяжна пазначыць вхідныя даны, абоўязкі віконавца крока і крытэрыя завершэння пры зміне коду. Аперацыйныя працавнікі должны магчыма ўвайсці крок з вядомай точкі контролю, не спрабоўваючы здогадвацца пра схованы стан. Неабяжна задокументаваць як шлях успеху, так і шлях вярнення. Перапрыбуткі, людзкі контроль і обработка некорэктных паведамленняў ёсць часткай продукту, а не чымсь, што дадаецца пазней. Ствараюць мадэлі вузлаў і зв’язкаў для запітанняў, якія вы будзеце ставіць, а не для кожнага іменніка ў дакуменце. Рэдкія, тыпаваныя рэбры лепшыя за ўжоўтучныя, незрозумелы графы.

Understand Request
       ↓
Retrieve Policies
       ↓
Evaluate Information
       ↓
Need More Data?
   ↙          ↘
 Yes          No
  ↓            ↓
Ask User   Continue
               ↓
       Approval Required?
          ↙          ↘
        Yes           No
         ↓             ↓
   Human Approval   Continue
          ↘          ↙
        Request Action
graph = StateGraph(AgentState)
graph.add_node(
    "understand_intent",
    understand_intent,
)
graph.add_node(
    "retrieve_policies",
    retrieve_policies,
)
graph.add_node(
    "evaluate",
    evaluate_request,
)
graph.add_node(
    "human_approval",
    request_human_approval,
)
graph.add_node(
    "request_action",
    request_application_action,
)
graph.add_edge(
    "understand_intent",
    "retrieve_policies",
)
graph.add_edge(
    "retrieve_policies",
    "evaluate",
)
graph.add_conditional_edges(
    "evaluate",
    determine_next_step,
    {
        "approval": "human_approval",
        "execute": "request_action",
    },
)

LangGraph не павінен стаць новым монолітом

Ёнколі LangGraph не павярэцца новым моналітам, перад зменой коду неабходна ўзначыць вхідныя даны, адпаведальнага за крок і крытэрыя завершэння. Аперацыі должны магчымае перадзягаць крок з вядомай точкі контролю, не спрабоўваючы з’ясаваць захаваны стан. Лепш выбіраць маленькія, тэставаныя елементы замест большых скрыптов. Калі крок не выйшаў, прычына нехасабносты павінна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцужок задач. Ствараюце вузлы і зв’язкі для тых пытанняў, якія вы хочаце задаць, а не для кожнага іменніка ў дакуменце. Рэдкія, тыпаваныя рэбры лепшыя за ўжоўткнутыя, незрозумелыя графы.

def evaluate_node(state):
    if state.amount > 100_000:
        state.requires_approval = True
    if state.country == "BR":
        ...
    if state.supplier_type == "CRITICAL":
        ...
decision = supplier_policy.evaluate(
    supplier=supplier,
    context=context,
)
LangGraph → orchestrates
Domain → decides

Дзе падходзіць MCP

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

LLM
 ↓
PostgreSQL
LLM
 ↓
SAP
Agent
  ↓
MCP Tool
  ↓
Application API
  ↓
Use Case
  ↓
Domain
  ↓
Infrastructure
create_supplier
execute_sql

PostgreSQL таксама ўжо адаптар

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

class SupplierRepository(Protocol):
    async def add(
        self,
        supplier: Supplier,
    ) -> None:
        ...
class PostgresSupplierRepository(
    SupplierRepository
):
    def __init__(self, session):
        self.session = session
    async def add(
        self,
        supplier: Supplier,
    ) -> None:
        entity = SupplierModel.from_domain(
            supplier
        )
        self.session.add(entity)
FastAPI      → doesn't know PostgreSQL exists
Application  → doesn't know PostgreSQL existsDomain       → doesn't know PostgreSQL existsInfrastructure → does

SAP должна знаходзіцца за іншай межой

Для SAP, які знаходзяцца за іншай межаючай структурой, неабяжна ўзначыць даныя, адпаведальную за кожны крок і крытэрыі завершэння працы перад змянай коду. Аператары должны магчымаць перзапуск крока з вядомай точкі контролю, не падозрываючы прыхованы стан сістэмы. Лепш выбіраць маленькія, тэставаныя елементы замест большых скрыптов. Калі крок не выконваецца, прычына неудачы должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаную структуру працы. Ўжывайце обмежэнняі і індэксы пры масовай загрузцы даных. Унікальнасць бізнес-клучоў дапамагае ператвараць пазнейшыя злучэння даных у працоўнае адчыненне/змяну, а не у сітуацію дуплікацый.

CreateSupplierUseCase
        ↓
Persist State
        ↓
SupplierCreated
        ↓
AWS SQS
        ↓
Integration Worker
        ↓
SAP

Стварэнне архітэктуры

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

Перакладзіце всю дыяграму.

USER
                           │
                           ▼
                       FastAPI
                           │
                           ▼
                       LangGraph
                           │
              ┌────────────┼────────────┐
              │            │            │
              ▼            ▼            ▼
             RAG          LLM          MCP
              │            │            │
              ▼            ▼            │
         OpenSearch     Bedrock         │
                                        ▼
                                  Application
                                        │
                                        ▼
                                     Domain
                                        │
                              ┌─────────┴─────────┐
                              │                   │
                              ▼                   ▼
                         PostgreSQL            AWS SQS
                                                  │
                                                  ▼
                                               Worker
                                                  │
                                                  ▼
                                                 SAP

Два светы

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

PROBABILISTICLLM
RAG
Natural Language
Intent Understanding
Agent Reasoning
Tool Selection
DETERMINISTIC
Authorization
Business Rules
Transactions
Persistence
Idempotency
Integration
Auditability

Практычны тэст для архітэктуры

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

async def test_supplier_requires_approval():
    repository = FakeSupplierRepository()
    policies = FakePolicyService(
        requires_approval=True
    )
    events = FakeEventPublisher()
    use_case = CreateSupplierUseCase(
        repository=repository,
        policy_service=policies,
        event_publisher=events,
    )
    supplier = await use_case.execute(
        CreateSupplierCommand(
            name="ACME",
            tax_id="123",
            country="BR",
        )
    )
    assert supplier.requires_approval is True

Зміна модэлю должна быць нудной

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

Усю графіку.

LLMProvider
             ▲
             │
   ┌─────────┴─────────┐
   │                   │
BedrockProvider   AnotherProvider
FastAPI
Application
Domain
Business Rules

Чыстая архітэктура — гэта не структура папак

У разе, калі чыстая архітэктура — гэта не структура папак, перад змянайом код неабходна ўзначыць вхідныя даны, абавесцявальніка крока і крытэрыя завершэння. Аперацыі должны магчымае перадзягнуць крок з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Неабходна аддзекаваць як шлях успеху, так і шлях вярнення. Перапрыбуткі, людзкія контралі і обработка некорэктных паведамленняў ёсць часткай продукту, а не пасляднім дапрацоўкам. Мадэлюйце вузлы і зв’язкі для тых пытанняў, якія вы будзеце ставіць, а не для кожнага іменніка ў дасведчэнні. Разрозненыя, тыпаваныя рэбры лепшыя за ўжоўтучныя, загадковыя графікі.

src/
├── api/
├── application/
├── domain/
├── agents/
├── ports/
└── infrastructure/

Штучны інтэлект робіць гэтыя межы ўсё бол важлівымі

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

Архітэктура ў адной фразе

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

цэлага графіка.

Заключныя заўважэнні

У частцы «Заключныя заўважэнні» неабходна праказаць вхідныя даны, абавесця крока і крытэрыі завершэння пры перадзеяванні коду. Аператары должны магчымае перадзеяваць крок з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Неабходна задокументаваць як шлях успеху, так і шлях вярнення. Перапрыбуткі, людзкіе перакрыцця і обработка некорэктных паведамленняў ёсць часткай продукту, а не чымсь, што дадаецца пазней. Ўжывайце обмежэнні і індэксы пры масовай абрабоце. Унікальнасць па бізнес-клучох прыводзіць да таго, што пазнейшыя з’еднанні стаюць прыведамымі апдэйтамі, а не до сітуацый з дуплікатамі.

Prompt
  ↓
 LLM
  ↓
 Tool
  ↓
Database

Чэрніцкі ліст аператыўных дзеянняў