Struktur proyek hexa#
Proyek hasil zul build hexa tersusun mengikuti arsitektur hexagonal: aturan bisnis di domain, alur kerja di application, teknologi di infrastructure, dan pintu masuk di interface.
Hampir setiap folder punya __init__.py berisi docstring tentang kegunaan folder itu, cara memakainya, dan contoh kode. Pohon di halaman ini tidak menampilkan file __init__.py, kecuali yang berisi kode.
Root proyek#
Pohon berikut menunjukkan isi root proyek bernama my-app:
my-app/
├── data/
│ └── .gitkeep
├── dockerfile/
│ └── Dockerfile
├── logs/
│ └── .gitkeep
├── notebooks/
│ └── .gitkeep
├── src/
├── test/
│ ├── conftest.py
│ └── test_chat_usecase.py
├── .env.example
├── .gitignore
├── pytest.ini
├── README.md
├── requirements.txt
└── requirements-dev.txt
| Path | Fungsi |
|---|---|
data/ |
Tempat dataset, data awal, dan fixture. Kosong di template. |
dockerfile/Dockerfile |
Membangun image aplikasi dari python:3.11-slim. Image meng-install requirements.txt, menyalin src/, dan menjalankan uvicorn di port 8000. |
logs/ |
Tempat file log. app.log dibuat saat aplikasi mulai. |
notebooks/ |
Tempat notebook eksperimen dan prototipe. Kosong di template. |
src/ |
Seluruh kode aplikasi. Rinciannya ada di Folder src. |
test/conftest.py |
Fixture scripted_model, yaitu pembuat LLM palsu untuk test. |
test/test_chat_usecase.py |
Empat test contoh untuk ChatUseCase. |
.env.example |
Contoh environment variable. Rinciannya ada di Referensi environment variable. |
.gitignore |
Daftar file yang tidak masuk git, termasuk .env dan file *.log. |
pytest.ini |
Memasukkan root proyek ke path impor dan menetapkan test/ sebagai folder test. |
README.md |
Ringkasan proyek. Judulnya berisi nama proyek. |
requirements.txt |
Dependency untuk menjalankan aplikasi. |
requirements-dev.txt |
Dependency aplikasi ditambah pytest dan httpx. |
File .gitkeep hanya ada supaya folder kosong ikut tersalin.
Folder src#
Pohon berikut menunjukkan empat layer dan satu folder helper di dalam src/:
| Folder | Isi | Boleh mengimpor |
|---|---|---|
domain/ |
Aturan bisnis: entity, state agent, exception, prompt. | Tidak ada layer lain |
application/ |
Alur kerja: use case dan agent. | domain |
infrastructure/ |
Adapter keluar: LLM, tool, memory, database. | domain, application |
interface/ |
Adapter masuk: HTTP, playground, Streamlit, CLI, Discord. | Semua layer |
utils/ |
Helper murni tanpa logika bisnis dan tanpa dependensi ke layer lain. Kosong di template. | Tidak ada layer lain |
Kode di proyek mengimpor dengan awalan src, sehingga aplikasi dan test dijalankan dari root proyek. Contoh baris impor:
Alasan di balik arah impor ini dijelaskan di Konsep: Perjalanan sebuah request.
Folder domain#
Pohon berikut menunjukkan isi src/domain/:
domain/
├── entities/
│ ├── agents/
│ │ └── react/
│ │ └── react.py
│ └── react.py
├── events/
├── exceptions/
│ └── __init__.py
├── repositories/
└── templates/
└── prompt/
├── human_in_the_loop/
│ └── human_in_the_loop_prompt_templates.py
├── react/
│ └── react_prompt_templates.py
└── subagents/
└── subagents_prompt_templates.py
| Path | Fungsi |
|---|---|
entities/ |
Objek inti bisnis. Satu file per entity. |
entities/agents/ |
State agent, yaitu bentuk data yang mengalir antar node. Satu subfolder per agent. |
entities/agents/react/react.py |
AgentState. State ini dipakai agent ReAct, human-in-the-loop, dan subagents. |
entities/react.py |
File cadangan bawaan template. Belum dipakai dan boleh dihapus. |
events/ |
Tempat domain event, yaitu kejadian penting di bisnis. Kosong di template. |
exceptions/__init__.py |
DomainError dan turunannya. Setiap turunan menjadi respons HTTP 400. |
repositories/ |
Tempat kontrak (kelas abstrak) untuk menyimpan dan mengambil data. Kosong di template. |
templates/prompt/react/react_prompt_templates.py |
REACT_SYSTEM_PROMPT. |
templates/prompt/human_in_the_loop/human_in_the_loop_prompt_templates.py |
HUMAN_IN_THE_LOOP_SYSTEM_PROMPT. |
templates/prompt/subagents/subagents_prompt_templates.py |
SUPERVISOR_SYSTEM_PROMPT, WEATHER_AGENT_SYSTEM_PROMPT, EMAIL_AGENT_SYSTEM_PROMPT. |
Folder application#
Pohon berikut menunjukkan isi src/application/:
application/
├── AI/
│ └── agents/
│ ├── react/
│ │ ├── react.py
│ │ └── nodes/
│ │ └── react_nodes.py
│ ├── human_in_the_loop/
│ │ ├── human_in_the_loop.py
│ │ └── nodes/
│ │ └── human_in_the_loop_nodes.py
│ └── subagents/
│ └── subagents.py
├── dto/
│ └── user.py
├── mappers/
│ └── user.py
├── prompts/
├── services/
└── usecases/
├── chat.py
└── reviewed_chat.py
| Path | Fungsi |
|---|---|
AI/agents/react/react.py |
build_react_agent, perakit graph agent ReAct. |
AI/agents/react/nodes/react_nodes.py |
make_llm_call, should_continue, STEPS_PER_TOOL_ROUND, STEP_LIMIT_MESSAGE. |
AI/agents/human_in_the_loop/human_in_the_loop.py |
build_human_in_the_loop_agent, perakit graph agent dengan langkah persetujuan. |
AI/agents/human_in_the_loop/nodes/human_in_the_loop_nodes.py |
Node human_review, node tool_node, dan pembuat payload review. |
AI/agents/subagents/subagents.py |
SubagentSpec, build_subagent_tool, build_supervisor_agent, MAX_SUBAGENT_STEPS. |
usecases/chat.py |
ChatUseCase dan MAX_AGENT_STEPS. |
usecases/reviewed_chat.py |
ReviewedChatUseCase, ChatTurn, dan validate_decisions. |
dto/user.py |
Contoh DTO Pydantic (UserDTO). Belum dipakai agent. |
mappers/user.py |
Contoh mapper entity ke DTO (UserMapper). Belum dipakai agent. |
prompts/ |
Tempat fungsi yang merakit prompt dari data saat runtime. Kosong di template. |
services/ |
Tempat koordinasi beberapa use case. Kosong di template. |
Setiap fungsi, kelas, dan konstanta di folder ini dijelaskan di Referensi API agent.
Folder infrastructure#
Pohon berikut menunjukkan isi src/infrastructure/:
infrastructure/
├── AI/
│ ├── llm/
│ │ └── openai.py
│ ├── memory/
│ │ └── checkpointer.py
│ └── tools/
│ ├── email_tool.py
│ └── weather_tool.py
├── connections/
├── database/
├── external/
└── logging_config.py
| Path | Fungsi |
|---|---|
AI/llm/openai.py |
get_llm_model, pembuat chat model untuk OpenAI atau endpoint yang kompatibel dengan OpenAI. |
AI/memory/checkpointer.py |
get_checkpointer, pembuat penyimpan percakapan (InMemorySaver). |
AI/tools/weather_tool.py |
Tool contoh get_weather yang membaca data. Isinya placeholder dengan jawaban tetap. |
AI/tools/email_tool.py |
Tool contoh send_email yang punya efek ke dunia luar. Isinya placeholder: email hanya dicatat ke log. |
connections/ |
Tempat koneksi yang dipakai bersama, misalnya pool database. Kosong di template. |
database/ |
Tempat implementasi repository. Kosong di template. |
external/ |
Tempat client API pihak ketiga. Kosong di template. |
logging_config.py |
setup_logging(log_level). Memasang log ke console dan ke logs/app.log dengan level bawaan INFO. |
Folder interface#
Pohon berikut menunjukkan isi src/interface/:
interface/
├── http/
│ ├── main.py
│ ├── controllers/
│ │ ├── chat_controller.py
│ │ ├── hitl_controller.py
│ │ ├── playground_controller.py
│ │ └── subagents_controller.py
│ └── routers/
│ ├── chat.py
│ ├── hitl.py
│ ├── playground.py
│ └── subagents.py
├── playground/
│ ├── features.py
│ ├── runner.py
│ └── settings.py
├── streamlit/
│ ├── main.py
│ ├── components/
│ └── pages/
│ ├── chat_with_search.py
│ ├── chat_with_user_feedback.py
│ ├── file_Q&A.py
│ ├── langchain_prompt_template.py
│ └── langchain_quickstart.py
├── cli/
└── discord/
http#
| Path | Fungsi |
|---|---|
http/main.py |
Membuat aplikasi FastAPI, memanggil setup_logging(), mendaftarkan router, memasang handler DomainError, dan menyediakan GET /health. Router playground dan aturan CORS hanya dipasang jika PLAYGROUND_ENABLED bernilai benar. |
http/routers/chat.py |
POST /chat. |
http/routers/hitl.py |
POST /hitl/chat dan POST /hitl/review. |
http/routers/subagents.py |
POST /subagents/chat. |
http/routers/playground.py |
GET /playground/features, POST /playground/messages, POST /playground/resume. |
http/controllers/chat_controller.py |
Model ChatRequest dan ChatResponse, perakit get_react_agent dan get_chat_usecase, dan handler chat. |
http/controllers/hitl_controller.py |
Model request dan respons review, konstanta TOOLS dan TOOLS_REQUIRING_APPROVAL, perakit get_human_in_the_loop_agent dan get_reviewed_chat_usecase, dan handler chat dan review. |
http/controllers/subagents_controller.py |
Konstanta SUBAGENTS, perakit get_supervisor_agent dan get_subagents_chat_usecase. |
http/controllers/playground_controller.py |
Model request dan respons playground, dan handler yang mengubah jejak langkah agent menjadi JSON. |
Endpoint dijelaskan di Referensi HTTP API dan Referensi Playground API.
playground#
| Path | Fungsi |
|---|---|
playground/features.py |
Feature, daftar FEATURES, dan find_feature. Daftar ini menentukan agent yang bisa dicoba di playground. |
playground/runner.py |
Menjalankan agent dan mencatat setiap langkahnya. Tidak bergantung pada HTTP. |
playground/settings.py |
playground_enabled() dan playground_origins(), yang membaca PLAYGROUND_ENABLED dan PLAYGROUND_ORIGINS. |
streamlit#
| Path | Fungsi |
|---|---|
streamlit/main.py |
Halaman utama: chatbot contoh yang memanggil OpenAI langsung, bukan agent proyek. API key diisi user di sidebar. |
streamlit/pages/chat_with_search.py |
Kerangka UI chat dengan pencarian web. Belum memanggil LLM. |
streamlit/pages/chat_with_user_feedback.py |
Kerangka UI chat dengan tombol feedback. Belum memanggil LLM. |
streamlit/pages/file_Q&A.py |
Kerangka UI tanya jawab atas file yang diunggah. Belum memanggil LLM. |
streamlit/pages/langchain_prompt_template.py |
Kerangka form satu pertanyaan. Fungsi generate_response masih kosong. |
streamlit/pages/langchain_quickstart.py |
Kerangka form satu pertanyaan. Fungsi generate_response masih kosong. |
streamlit/components/ |
Tempat potongan UI yang dipakai ulang. Kosong di template. |
Setiap file .py di streamlit/pages/ menjadi satu halaman di sidebar Streamlit.
cli dan discord#
| Path | Fungsi |
|---|---|
cli/ |
Tempat perintah command line yang memanggil use case. Kosong di template; docstring-nya berisi contoh. |
discord/ |
Tempat bot Discord yang memanggil use case. Kosong di template; docstring-nya berisi contoh. |
Folder test#
| Path | Fungsi |
|---|---|
test/conftest.py |
Kelas FakeToolCallingModel dan fixture scripted_model. Model palsu ini menjawab sesuai naskah, dan mencatat pesan yang diterimanya di received dan tool yang diberikan agent di bound_tools. |
test/test_chat_usecase.py |
Empat test contoh: jawaban langsung, pemanggilan tool, percakapan yang berlanjut, dan penolakan pesan kosong. |
Alasan test memakai model palsu dijelaskan di Konsep: Menguji tanpa LLM asli.
Lokasi untuk kode baru#
Tabel berikut memetakan jenis kode ke lokasinya:
| Yang ditambah | Lokasi | Panduan |
|---|---|---|
| Tool | src/infrastructure/AI/tools/, lalu didaftarkan di controller agent yang memakainya |
Menambah tool |
| Tool yang butuh persetujuan | TOOLS dan TOOLS_REQUIRING_APPROVAL di hitl_controller.py |
Mewajibkan persetujuan untuk sebuah tool |
| Subagent | SUBAGENTS di subagents_controller.py, prompt di domain/templates/prompt/subagents/ |
Menambah subagent |
| Node graph | src/application/AI/agents/NAMA/nodes/ |
Menambah node ke graph |
| Agent baru | src/application/AI/agents/NAMA/, state di domain/entities/agents/NAMA/, prompt di domain/templates/prompt/NAMA/ |
Tidak ada |
| System prompt | src/domain/templates/prompt/ |
Mengubah system prompt |
| Aksi bisnis | src/application/usecases/ |
Tidak ada |
| Entity atau aturan bisnis | src/domain/entities/ |
Tidak ada |
| Error bisnis | src/domain/exceptions/ |
Tidak ada |
| Endpoint | src/interface/http/routers/ dan controllers/, lalu didaftarkan di main.py |
Menambah endpoint |
| Fitur playground | FEATURES di src/interface/playground/features.py |
Mencoba fitur di playground |
| Provider LLM lain | src/infrastructure/AI/llm/ |
Mengatur model dan API key |
| Penyimpanan percakapan lain | src/infrastructure/AI/memory/ |
Menyimpan percakapan di database |
| Akses database | Kontrak di domain/repositories/, implementasi di infrastructure/database/ |
Tidak ada |
NAMA adalah nama agent yang kamu buat, misalnya rag.