lionagi 0.7.7__tar.gz → 0.7.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lionagi-0.7.7 → lionagi-0.7.8}/PKG-INFO +1 -1
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/utils.py +4 -1
- lionagi-0.7.8/lionagi/version.py +1 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/pyproject.toml +1 -1
- lionagi-0.7.7/cookbooks/ch10_e2e_project.md +0 -521
- lionagi-0.7.7/cookbooks/ch11_performance.md +0 -509
- lionagi-0.7.7/cookbooks/ch12_graph.md +0 -583
- lionagi-0.7.7/cookbooks/ch3_internal_tools.md +0 -450
- lionagi-0.7.7/cookbooks/ch4_structured_forms.md +0 -674
- lionagi-0.7.7/cookbooks/ch5_react.md +0 -693
- lionagi-0.7.7/cookbooks/ch6_multi_branch.md +0 -806
- lionagi-0.7.7/cookbooks/ch7_multi_agent.md +0 -741
- lionagi-0.7.7/cookbooks/ch8_rate_limiting.md +0 -585
- lionagi-0.7.7/cookbooks/ch9_data_adapter.md +0 -581
- lionagi-0.7.7/lionagi/version.py +0 -1
- {lionagi-0.7.7 → lionagi-0.7.8}/.env.example +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/.github/FUNDING.yml +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/.github/dependabot.yml +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/.github/workflows/ci.yml +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/.github/workflows/codeql.yml +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/.github/workflows/docs.yml +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/.github/workflows/release.yml +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/.gitignore +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/.pre-commit-config.yaml +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/CODE_OF_CONDUCT.md +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/CONTRIBUTING.md +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/LICENSE +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/README.md +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/cookbooks/ch01_get_started.md +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/cookbooks/ch02_concepts.md +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/dev_tools/count_code_base_lines.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/Makefile +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/_static/custom.css +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/_templates/layout.html +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/conf.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/index.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/action.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/adapter.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/branch.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/branch_operations.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/concepts.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/element_id.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/event.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/form.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/graph.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/index.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/instruct.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/lib_file.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/lib_nested.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/lib_package.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/lib_schema.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/lib_validate.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/log.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/mail.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/message.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/models.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/operative_step.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/pile.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/processor.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/progression.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/service.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/session.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/modules/utils.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/tutorials/get_started.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/tutorials/get_started_pt2.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/tutorials/get_started_pt3.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/docs/tutorials/index.rst +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/_class_registry.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/_errors.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/_types.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/file/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/file/chunk.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/file/file_ops.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/file/params.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/file/process.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/file/save.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/nested/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/nested/flatten.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/nested/nfilter.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/nested/nget.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/nested/ninsert.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/nested/nmerge.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/nested/npop.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/nested/nset.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/nested/unflatten.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/nested/utils.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/package/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/package/imports.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/package/management.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/package/params.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/package/system.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/parse.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/schema/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/schema/as_readable.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/schema/extract_code_block.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/schema/extract_docstring.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/schema/function_to_schema.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/schema/json_schema.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/token_transform/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/token_transform/llmlingua.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/token_transform/perplexity.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/token_transform/synthlang.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/validate/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/validate/common_field_validators.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/validate/fuzzy_match_keys.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/validate/fuzzy_validate_mapping.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/validate/string_similarity.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/libs/validate/validate_boolean.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/ReAct/ReAct.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/ReAct/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/ReAct/utils.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/_act/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/_act/act.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/brainstorm/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/brainstorm/brainstorm.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/brainstorm/prompt.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/chat/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/chat/chat.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/communicate/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/communicate/communicate.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/instruct/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/instruct/instruct.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/interpret/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/interpret/interpret.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/manager.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/operate/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/operate/operate.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/parse/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/parse/parse.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/plan/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/plan/plan.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/plan/prompt.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/select/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/select/select.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/select/utils.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/translate/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/translate/translate.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/types.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operations/utils.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/action/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/action/function_calling.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/action/manager.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/action/request_response_model.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/action/tool.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/action/utils.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/forms/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/forms/base.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/forms/form.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/forms/report.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/forms/utils.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/instruct/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/instruct/base.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/instruct/instruct.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/instruct/instruct_collection.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/instruct/node.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/instruct/prompts.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/instruct/reason.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/manager.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/models/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/models/field_model.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/models/model_params.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/models/note.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/models/operable_model.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/models/schema_model.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/operative.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/step.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/strategies/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/strategies/base.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/strategies/concurrent.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/strategies/concurrent_chunk.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/strategies/concurrent_sequential_chunk.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/strategies/params.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/strategies/sequential.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/strategies/sequential_chunk.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/strategies/sequential_concurrent_chunk.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/strategies/utils.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/operatives/types.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/_concepts.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/adapters/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/adapters/adapter.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/adapters/json_adapter.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/adapters/pandas_/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/adapters/pandas_/csv_adapter.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/adapters/pandas_/excel_adapter.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/adapters/pandas_/pd_dataframe_adapter.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/adapters/pandas_/pd_series_adapter.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/adapters/types.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/generic/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/generic/element.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/generic/event.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/generic/log.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/generic/pile.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/generic/processor.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/generic/progression.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/graph/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/graph/edge.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/graph/graph.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/graph/node.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/mail/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/mail/exchange.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/mail/mail.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/mail/mailbox.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/mail/manager.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/mail/package.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/action_request.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/action_response.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/assistant_response.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/base.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/instruction.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/manager.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/message.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/system.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/templates/README.md +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/templates/action_request.jinja2 +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/templates/action_response.jinja2 +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/templates/assistant_response.jinja2 +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/templates/instruction_message.jinja2 +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/templates/system_message.jinja2 +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/messages/templates/tool_schemas.jinja2 +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/protocols/types.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/endpoints/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/endpoints/base.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/endpoints/chat_completion.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/endpoints/match_endpoint.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/endpoints/rate_limited_processor.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/endpoints/token_calculator.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/imodel.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/manager.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/anthropic_/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/anthropic_/messages.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/exa_/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/exa_/models.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/exa_/search.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/exa_/types.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/groq_/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/groq_/chat_completions.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/openai_/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/openai_/chat_completions.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/openrouter_/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/openrouter_/chat_completions.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/perplexity_/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/perplexity_/chat_completions.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/providers/types.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/service/types.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/session/__init__.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/session/branch.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/session/session.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/lionagi/settings.py +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/prompts/doc_style.md +0 -0
- {lionagi-0.7.7 → lionagi-0.7.8}/uv.lock +0 -0
@@ -2357,7 +2357,10 @@ def breakdown_pydantic_annotation(
|
|
2357
2357
|
|
2358
2358
|
|
2359
2359
|
def _is_pydantic_model(x: Any) -> bool:
|
2360
|
-
|
2360
|
+
try:
|
2361
|
+
return isclass(x) and issubclass(x, BaseModel)
|
2362
|
+
except TypeError:
|
2363
|
+
return False
|
2361
2364
|
|
2362
2365
|
|
2363
2366
|
def run_package_manager_command(
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.7.8"
|
@@ -1,521 +0,0 @@
|
|
1
|
-
# LionAGI Cookbook
|
2
|
-
|
3
|
-
## Chapter 10: Building a Research Assistant
|
4
|
-
|
5
|
-
In previous chapters, you learned individual components. Now we'll combine them into a complete end-to-end project: a research assistant that:
|
6
|
-
- Gathers research data
|
7
|
-
- Analyzes information
|
8
|
-
- Generates reports
|
9
|
-
- Handles multiple users
|
10
|
-
|
11
|
-
### Prerequisites
|
12
|
-
- Completed [Chapter 9](ch9_data_adapter.md)
|
13
|
-
- Understanding of previous chapters
|
14
|
-
- Basic Python knowledge
|
15
|
-
|
16
|
-
## System Architecture
|
17
|
-
|
18
|
-
### Core Components
|
19
|
-
```mermaid
|
20
|
-
graph TD
|
21
|
-
A[Research System] --> B[Research Agent]
|
22
|
-
A --> C[Analysis Agent]
|
23
|
-
A --> D[Writing Agent]
|
24
|
-
E[Features] --> F[Rate Limiting]
|
25
|
-
E --> G[Data Export]
|
26
|
-
E --> H[Multi-User]
|
27
|
-
I[Tools] --> J[Web Search]
|
28
|
-
I --> K[Data Processing]
|
29
|
-
I --> L[Report Generation]
|
30
|
-
```
|
31
|
-
|
32
|
-
### Basic Setup
|
33
|
-
```python
|
34
|
-
from lionagi import (
|
35
|
-
Branch, Model, Session,
|
36
|
-
RateLimitedAPIExecutor,
|
37
|
-
JsonFileAdapter, CSVFileAdapter,
|
38
|
-
types
|
39
|
-
)
|
40
|
-
from datetime import datetime
|
41
|
-
from pathlib import Path
|
42
|
-
from typing import List, Dict, Any
|
43
|
-
import json
|
44
|
-
|
45
|
-
class ResearchSystem:
|
46
|
-
"""End-to-end research system."""
|
47
|
-
def __init__(
|
48
|
-
self,
|
49
|
-
name: str = "Research",
|
50
|
-
save_dir: str = "research",
|
51
|
-
requests_per_minute: int = 60
|
52
|
-
):
|
53
|
-
# Create session
|
54
|
-
self.session = Session()
|
55
|
-
|
56
|
-
# Create executor
|
57
|
-
self.executor = RateLimitedAPIExecutor(
|
58
|
-
queue_capacity=1000,
|
59
|
-
capacity_refresh_time=60,
|
60
|
-
limit_requests=requests_per_minute
|
61
|
-
)
|
62
|
-
|
63
|
-
# Create model
|
64
|
-
self.model = Model(
|
65
|
-
provider="openai",
|
66
|
-
model="gpt-4",
|
67
|
-
temperature=0.7,
|
68
|
-
executor=self.executor
|
69
|
-
)
|
70
|
-
|
71
|
-
# Create agents
|
72
|
-
self.researcher = self.session.new_branch(
|
73
|
-
name="Researcher",
|
74
|
-
system="""You are a research expert.
|
75
|
-
Gather information effectively.
|
76
|
-
Analyze data thoroughly.
|
77
|
-
Find key insights."""
|
78
|
-
)
|
79
|
-
|
80
|
-
self.analyst = self.session.new_branch(
|
81
|
-
name="Analyst",
|
82
|
-
system="""You are a data analyst.
|
83
|
-
Process information carefully.
|
84
|
-
Identify patterns.
|
85
|
-
Draw conclusions."""
|
86
|
-
)
|
87
|
-
|
88
|
-
self.writer = self.session.new_branch(
|
89
|
-
name="Writer",
|
90
|
-
system="""You are a technical writer.
|
91
|
-
Write clear reports.
|
92
|
-
Structure information.
|
93
|
-
Explain concepts."""
|
94
|
-
)
|
95
|
-
|
96
|
-
# Configure models
|
97
|
-
for branch in self.session.branches:
|
98
|
-
branch.add_model(self.model)
|
99
|
-
|
100
|
-
# Setup storage
|
101
|
-
self.save_dir = Path(save_dir)
|
102
|
-
self.save_dir.mkdir(exist_ok=True)
|
103
|
-
|
104
|
-
# Track research
|
105
|
-
self.topics: Dict[str, dict] = {}
|
106
|
-
self.reports: Dict[str, dict] = {}
|
107
|
-
self._load_research()
|
108
|
-
|
109
|
-
def _load_research(self):
|
110
|
-
"""Load saved research."""
|
111
|
-
for file in self.save_dir.glob("*.json"):
|
112
|
-
with open(file) as f:
|
113
|
-
research = json.load(f)
|
114
|
-
if research["type"] == "topic":
|
115
|
-
self.topics[research["id"]] = research
|
116
|
-
else:
|
117
|
-
self.reports[research["id"]] = research
|
118
|
-
|
119
|
-
async def research_topic(
|
120
|
-
self,
|
121
|
-
topic: str,
|
122
|
-
depth: str = "comprehensive",
|
123
|
-
focus: List[str] = None
|
124
|
-
) -> dict:
|
125
|
-
"""Research new topic."""
|
126
|
-
try:
|
127
|
-
# Create research
|
128
|
-
topic_id = f"topic_{len(self.topics)}"
|
129
|
-
research = {
|
130
|
-
"id": topic_id,
|
131
|
-
"type": "topic",
|
132
|
-
"topic": topic,
|
133
|
-
"depth": depth,
|
134
|
-
"focus": focus or [],
|
135
|
-
"status": "researching",
|
136
|
-
"timestamp": datetime.now().isoformat()
|
137
|
-
}
|
138
|
-
|
139
|
-
# Get research plan
|
140
|
-
plan = await self.researcher.chat(
|
141
|
-
f"""Create research plan for:
|
142
|
-
Topic: {topic}
|
143
|
-
Depth: {depth}
|
144
|
-
Focus: {focus or 'General'}"""
|
145
|
-
)
|
146
|
-
|
147
|
-
# Get initial research
|
148
|
-
findings = await self.researcher.chat(
|
149
|
-
f"""Research following plan:
|
150
|
-
{plan}"""
|
151
|
-
)
|
152
|
-
|
153
|
-
# Analyze findings
|
154
|
-
analysis = await self.analyst.chat(
|
155
|
-
f"""Analyze research findings:
|
156
|
-
{findings}"""
|
157
|
-
)
|
158
|
-
|
159
|
-
# Update research
|
160
|
-
research["plan"] = plan
|
161
|
-
research["findings"] = findings
|
162
|
-
research["analysis"] = analysis
|
163
|
-
research["status"] = "completed"
|
164
|
-
research["completed"] = datetime.now().isoformat()
|
165
|
-
|
166
|
-
# Save research
|
167
|
-
self.topics[topic_id] = research
|
168
|
-
file_path = self.save_dir / f"{topic_id}.json"
|
169
|
-
with open(file_path, "w") as f:
|
170
|
-
json.dump(research, f, indent=2)
|
171
|
-
|
172
|
-
return {
|
173
|
-
"status": "success",
|
174
|
-
"topic_id": topic_id,
|
175
|
-
"research": research
|
176
|
-
}
|
177
|
-
|
178
|
-
except Exception as e:
|
179
|
-
return {
|
180
|
-
"status": "error",
|
181
|
-
"error": str(e)
|
182
|
-
}
|
183
|
-
|
184
|
-
async def generate_report(
|
185
|
-
self,
|
186
|
-
topic_id: str,
|
187
|
-
format: str = "markdown"
|
188
|
-
) -> dict:
|
189
|
-
"""Generate research report."""
|
190
|
-
if topic_id not in self.topics:
|
191
|
-
return {
|
192
|
-
"status": "error",
|
193
|
-
"error": f"Unknown topic: {topic_id}"
|
194
|
-
}
|
195
|
-
|
196
|
-
try:
|
197
|
-
topic = self.topics[topic_id]
|
198
|
-
|
199
|
-
# Create report
|
200
|
-
report_id = f"report_{len(self.reports)}"
|
201
|
-
report = {
|
202
|
-
"id": report_id,
|
203
|
-
"type": "report",
|
204
|
-
"topic_id": topic_id,
|
205
|
-
"format": format,
|
206
|
-
"status": "generating",
|
207
|
-
"timestamp": datetime.now().isoformat()
|
208
|
-
}
|
209
|
-
|
210
|
-
# Generate report
|
211
|
-
content = await self.writer.chat(
|
212
|
-
f"""Generate {format} report for:
|
213
|
-
Topic: {topic['topic']}
|
214
|
-
Findings: {topic['findings']}
|
215
|
-
Analysis: {topic['analysis']}"""
|
216
|
-
)
|
217
|
-
|
218
|
-
# Update report
|
219
|
-
report["content"] = content
|
220
|
-
report["status"] = "completed"
|
221
|
-
report["completed"] = datetime.now().isoformat()
|
222
|
-
|
223
|
-
# Save report
|
224
|
-
self.reports[report_id] = report
|
225
|
-
file_path = self.save_dir / f"{report_id}.json"
|
226
|
-
with open(file_path, "w") as f:
|
227
|
-
json.dump(report, f, indent=2)
|
228
|
-
|
229
|
-
# Export report
|
230
|
-
if format == "json":
|
231
|
-
JsonFileAdapter.to_obj(
|
232
|
-
content,
|
233
|
-
fp=self.save_dir / f"{report_id}_report.json"
|
234
|
-
)
|
235
|
-
elif format == "csv":
|
236
|
-
CSVFileAdapter.to_obj(
|
237
|
-
content,
|
238
|
-
fp=self.save_dir / f"{report_id}_report.csv",
|
239
|
-
many=True
|
240
|
-
)
|
241
|
-
else:
|
242
|
-
# Save as markdown
|
243
|
-
with open(self.save_dir / f"{report_id}_report.md", "w") as f:
|
244
|
-
f.write(content)
|
245
|
-
|
246
|
-
return {
|
247
|
-
"status": "success",
|
248
|
-
"report_id": report_id,
|
249
|
-
"report": report
|
250
|
-
}
|
251
|
-
|
252
|
-
except Exception as e:
|
253
|
-
return {
|
254
|
-
"status": "error",
|
255
|
-
"error": str(e)
|
256
|
-
}
|
257
|
-
|
258
|
-
def get_topic(
|
259
|
-
self,
|
260
|
-
topic_id: str
|
261
|
-
) -> dict:
|
262
|
-
"""Get topic details."""
|
263
|
-
return self.topics.get(topic_id, {
|
264
|
-
"error": f"Unknown topic: {topic_id}"
|
265
|
-
})
|
266
|
-
|
267
|
-
def get_report(
|
268
|
-
self,
|
269
|
-
report_id: str
|
270
|
-
) -> dict:
|
271
|
-
"""Get report details."""
|
272
|
-
return self.reports.get(report_id, {
|
273
|
-
"error": f"Unknown report: {report_id}"
|
274
|
-
})
|
275
|
-
|
276
|
-
# Usage
|
277
|
-
async def research_ai():
|
278
|
-
"""Demo research system."""
|
279
|
-
# Create system
|
280
|
-
system = ResearchSystem(
|
281
|
-
name="AI Research",
|
282
|
-
save_dir="ai_research"
|
283
|
-
)
|
284
|
-
|
285
|
-
# Research topic
|
286
|
-
result = await system.research_topic(
|
287
|
-
topic="AI Safety",
|
288
|
-
depth="comprehensive",
|
289
|
-
focus=[
|
290
|
-
"technical challenges",
|
291
|
-
"current approaches",
|
292
|
-
"future directions"
|
293
|
-
]
|
294
|
-
)
|
295
|
-
print("\nResearch:", result)
|
296
|
-
|
297
|
-
# Generate report
|
298
|
-
if result["status"] == "success":
|
299
|
-
report = await system.generate_report(
|
300
|
-
result["topic_id"],
|
301
|
-
format="markdown"
|
302
|
-
)
|
303
|
-
print("\nReport:", report)
|
304
|
-
|
305
|
-
# Run research
|
306
|
-
asyncio.run(research_ai())
|
307
|
-
```
|
308
|
-
|
309
|
-
## Advanced Features
|
310
|
-
|
311
|
-
### Multi-User Support
|
312
|
-
```python
|
313
|
-
class ResearchService:
|
314
|
-
"""Multi-user research service."""
|
315
|
-
def __init__(
|
316
|
-
self,
|
317
|
-
name: str = "ResearchService",
|
318
|
-
save_dir: str = "research_service"
|
319
|
-
):
|
320
|
-
# Create system
|
321
|
-
self.system = ResearchSystem(
|
322
|
-
name=name,
|
323
|
-
save_dir=save_dir
|
324
|
-
)
|
325
|
-
|
326
|
-
# Track users
|
327
|
-
self.users: Dict[str, dict] = {}
|
328
|
-
self.requests: Dict[str, dict] = {}
|
329
|
-
|
330
|
-
async def handle_request(
|
331
|
-
self,
|
332
|
-
user_id: str,
|
333
|
-
request: dict
|
334
|
-
) -> dict:
|
335
|
-
"""Handle user request."""
|
336
|
-
try:
|
337
|
-
# Create request
|
338
|
-
request_id = f"req_{len(self.requests)}"
|
339
|
-
record = {
|
340
|
-
"id": request_id,
|
341
|
-
"user_id": user_id,
|
342
|
-
"request": request,
|
343
|
-
"status": "received",
|
344
|
-
"timestamp": datetime.now().isoformat()
|
345
|
-
}
|
346
|
-
|
347
|
-
# Track user
|
348
|
-
if user_id not in self.users:
|
349
|
-
self.users[user_id] = {
|
350
|
-
"id": user_id,
|
351
|
-
"requests": []
|
352
|
-
}
|
353
|
-
self.users[user_id]["requests"].append(request_id)
|
354
|
-
|
355
|
-
# Process request
|
356
|
-
if request["type"] == "research":
|
357
|
-
result = await self.system.research_topic(
|
358
|
-
topic=request["topic"],
|
359
|
-
depth=request.get("depth", "comprehensive"),
|
360
|
-
focus=request.get("focus")
|
361
|
-
)
|
362
|
-
elif request["type"] == "report":
|
363
|
-
result = await self.system.generate_report(
|
364
|
-
topic_id=request["topic_id"],
|
365
|
-
format=request.get("format", "markdown")
|
366
|
-
)
|
367
|
-
else:
|
368
|
-
return {
|
369
|
-
"status": "error",
|
370
|
-
"error": f"Unknown request: {request['type']}"
|
371
|
-
}
|
372
|
-
|
373
|
-
# Update request
|
374
|
-
record["result"] = result
|
375
|
-
record["status"] = "completed"
|
376
|
-
record["completed"] = datetime.now().isoformat()
|
377
|
-
|
378
|
-
# Save request
|
379
|
-
self.requests[request_id] = record
|
380
|
-
|
381
|
-
return {
|
382
|
-
"status": "success",
|
383
|
-
"request_id": request_id,
|
384
|
-
"result": result
|
385
|
-
}
|
386
|
-
|
387
|
-
except Exception as e:
|
388
|
-
return {
|
389
|
-
"status": "error",
|
390
|
-
"error": str(e)
|
391
|
-
}
|
392
|
-
|
393
|
-
def get_user_history(
|
394
|
-
self,
|
395
|
-
user_id: str
|
396
|
-
) -> dict:
|
397
|
-
"""Get user request history."""
|
398
|
-
if user_id not in self.users:
|
399
|
-
return {
|
400
|
-
"error": f"Unknown user: {user_id}"
|
401
|
-
}
|
402
|
-
|
403
|
-
history = []
|
404
|
-
for request_id in self.users[user_id]["requests"]:
|
405
|
-
request = self.requests.get(request_id)
|
406
|
-
if request:
|
407
|
-
history.append(request)
|
408
|
-
|
409
|
-
return {
|
410
|
-
"user_id": user_id,
|
411
|
-
"history": history
|
412
|
-
}
|
413
|
-
|
414
|
-
# Usage
|
415
|
-
async def serve_users():
|
416
|
-
"""Demo research service."""
|
417
|
-
# Create service
|
418
|
-
service = ResearchService(
|
419
|
-
name="Research Service",
|
420
|
-
save_dir="research_data"
|
421
|
-
)
|
422
|
-
|
423
|
-
# Handle requests
|
424
|
-
users = ["user1", "user2"]
|
425
|
-
requests = [
|
426
|
-
{
|
427
|
-
"type": "research",
|
428
|
-
"topic": "Machine Learning",
|
429
|
-
"depth": "basic",
|
430
|
-
"focus": ["fundamentals", "applications"]
|
431
|
-
},
|
432
|
-
{
|
433
|
-
"type": "research",
|
434
|
-
"topic": "Deep Learning",
|
435
|
-
"depth": "comprehensive",
|
436
|
-
"focus": ["architectures", "training"]
|
437
|
-
}
|
438
|
-
]
|
439
|
-
|
440
|
-
# Process each request
|
441
|
-
results = []
|
442
|
-
for user_id, request in zip(users, requests):
|
443
|
-
result = await service.handle_request(
|
444
|
-
user_id,
|
445
|
-
request
|
446
|
-
)
|
447
|
-
results.append(result)
|
448
|
-
print(f"\nUser {user_id} result:", result)
|
449
|
-
|
450
|
-
# Generate report if successful
|
451
|
-
if result["status"] == "success":
|
452
|
-
topic_id = result["result"]["topic_id"]
|
453
|
-
report = await service.handle_request(
|
454
|
-
user_id,
|
455
|
-
{
|
456
|
-
"type": "report",
|
457
|
-
"topic_id": topic_id,
|
458
|
-
"format": "markdown"
|
459
|
-
}
|
460
|
-
)
|
461
|
-
print(f"\nUser {user_id} report:", report)
|
462
|
-
|
463
|
-
# Check history
|
464
|
-
for user_id in users:
|
465
|
-
history = service.get_user_history(user_id)
|
466
|
-
print(f"\nUser {user_id} history:", history)
|
467
|
-
|
468
|
-
# Run service
|
469
|
-
asyncio.run(serve_users())
|
470
|
-
```
|
471
|
-
|
472
|
-
## Best Practices
|
473
|
-
|
474
|
-
1. **System Design**
|
475
|
-
- Define clear interfaces
|
476
|
-
- Handle errors gracefully
|
477
|
-
- Track state properly
|
478
|
-
- Monitor performance
|
479
|
-
|
480
|
-
2. **Service Design**
|
481
|
-
- Support multiple users
|
482
|
-
- Track requests
|
483
|
-
- Maintain history
|
484
|
-
- Handle concurrency
|
485
|
-
|
486
|
-
3. **Integration**
|
487
|
-
- Use rate limiting
|
488
|
-
- Export data cleanly
|
489
|
-
- Log operations
|
490
|
-
- Monitor health
|
491
|
-
|
492
|
-
## Quick Reference
|
493
|
-
```python
|
494
|
-
from lionagi import Branch, Model, Session
|
495
|
-
|
496
|
-
# Create system
|
497
|
-
session = Session()
|
498
|
-
researcher = session.new_branch(
|
499
|
-
name="Researcher",
|
500
|
-
system="You are a researcher."
|
501
|
-
)
|
502
|
-
|
503
|
-
# Configure model
|
504
|
-
model = Model(provider="openai")
|
505
|
-
researcher.add_model(model)
|
506
|
-
|
507
|
-
# Research topic
|
508
|
-
result = await researcher.chat(
|
509
|
-
"Research AI Safety"
|
510
|
-
)
|
511
|
-
```
|
512
|
-
|
513
|
-
## Next Steps
|
514
|
-
|
515
|
-
You've learned:
|
516
|
-
- How to build complete systems
|
517
|
-
- How to handle multiple users
|
518
|
-
- How to manage research
|
519
|
-
- How to generate reports
|
520
|
-
|
521
|
-
In [Chapter 11](ch11_performance.md), we'll explore performance optimization and scaling strategies.
|