claude-autopm 2.8.1 → 2.8.3
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.
- package/README.md +399 -529
- package/bin/autopm.js +2 -0
- package/bin/commands/plugin.js +395 -0
- package/bin/commands/team.js +184 -10
- package/install/install.js +223 -4
- package/lib/plugins/PluginManager.js +1328 -0
- package/lib/plugins/PluginManager.old.js +400 -0
- package/package.json +5 -1
- package/packages/plugin-ai/LICENSE +21 -0
- package/packages/plugin-ai/README.md +316 -0
- package/packages/plugin-ai/agents/anthropic-claude-expert.md +579 -0
- package/packages/plugin-ai/agents/azure-openai-expert.md +1411 -0
- package/packages/plugin-ai/agents/google-a2a-expert.md +1445 -0
- package/packages/plugin-ai/agents/huggingface-expert.md +2131 -0
- package/packages/plugin-ai/agents/langchain-expert.md +1427 -0
- package/packages/plugin-ai/commands/a2a-setup.md +886 -0
- package/packages/plugin-ai/commands/ai-model-deployment.md +481 -0
- package/packages/plugin-ai/commands/anthropic-optimize.md +793 -0
- package/packages/plugin-ai/commands/huggingface-deploy.md +789 -0
- package/packages/plugin-ai/commands/langchain-optimize.md +807 -0
- package/packages/plugin-ai/commands/llm-optimize.md +348 -0
- package/packages/plugin-ai/commands/openai-optimize.md +863 -0
- package/packages/plugin-ai/commands/rag-optimize.md +841 -0
- package/packages/plugin-ai/commands/rag-setup-scaffold.md +382 -0
- package/packages/plugin-ai/package.json +66 -0
- package/packages/plugin-ai/plugin.json +519 -0
- package/packages/plugin-ai/rules/ai-model-standards.md +449 -0
- package/packages/plugin-ai/rules/prompt-engineering-standards.md +509 -0
- package/packages/plugin-ai/scripts/examples/huggingface-inference-example.py +145 -0
- package/packages/plugin-ai/scripts/examples/langchain-rag-example.py +366 -0
- package/packages/plugin-ai/scripts/examples/mlflow-tracking-example.py +224 -0
- package/packages/plugin-ai/scripts/examples/openai-chat-example.py +425 -0
- package/packages/plugin-cloud/README.md +268 -0
- package/packages/plugin-cloud/agents/gemini-api-expert.md +880 -0
- package/packages/plugin-cloud/agents/openai-python-expert.md +1087 -0
- package/packages/plugin-cloud/commands/cloud-cost-optimize.md +243 -0
- package/packages/plugin-cloud/commands/cloud-validate.md +196 -0
- package/packages/plugin-cloud/hooks/pre-cloud-deploy.js +456 -0
- package/packages/plugin-cloud/package.json +64 -0
- package/packages/plugin-cloud/plugin.json +338 -0
- package/packages/plugin-cloud/rules/cloud-security-compliance.md +313 -0
- package/packages/plugin-cloud/scripts/examples/aws-validate.sh +30 -0
- package/packages/plugin-cloud/scripts/examples/azure-setup.sh +33 -0
- package/packages/plugin-cloud/scripts/examples/gcp-setup.sh +39 -0
- package/packages/plugin-cloud/scripts/examples/k8s-validate.sh +40 -0
- package/packages/plugin-cloud/scripts/examples/terraform-init.sh +26 -0
- package/packages/plugin-core/README.md +274 -0
- package/packages/plugin-core/commands/code-rabbit.md +128 -0
- package/packages/plugin-core/commands/prompt.md +9 -0
- package/packages/plugin-core/commands/re-init.md +9 -0
- package/packages/plugin-core/hooks/context7-reminder.md +29 -0
- package/packages/plugin-core/hooks/enforce-agents.js +125 -0
- package/packages/plugin-core/hooks/enforce-agents.sh +35 -0
- package/packages/plugin-core/hooks/pre-agent-context7.js +224 -0
- package/packages/plugin-core/hooks/pre-command-context7.js +229 -0
- package/packages/plugin-core/hooks/strict-enforce-agents.sh +39 -0
- package/packages/plugin-core/hooks/test-hook.sh +21 -0
- package/packages/plugin-core/hooks/unified-context7-enforcement.sh +38 -0
- package/packages/plugin-core/package.json +45 -0
- package/packages/plugin-core/plugin.json +387 -0
- package/packages/plugin-core/rules/agent-coordination.md +549 -0
- package/packages/plugin-core/rules/agent-mandatory.md +170 -0
- package/packages/plugin-core/rules/command-pipelines.md +208 -0
- package/packages/plugin-core/rules/context-optimization.md +176 -0
- package/packages/plugin-core/rules/context7-enforcement.md +327 -0
- package/packages/plugin-core/rules/datetime.md +122 -0
- package/packages/plugin-core/rules/definition-of-done.md +272 -0
- package/packages/plugin-core/rules/development-environments.md +19 -0
- package/packages/plugin-core/rules/development-workflow.md +198 -0
- package/packages/plugin-core/rules/framework-path-rules.md +180 -0
- package/packages/plugin-core/rules/frontmatter-operations.md +64 -0
- package/packages/plugin-core/rules/git-strategy.md +237 -0
- package/packages/plugin-core/rules/golden-rules.md +181 -0
- package/packages/plugin-core/rules/naming-conventions.md +111 -0
- package/packages/plugin-core/rules/no-pr-workflow.md +183 -0
- package/packages/plugin-core/rules/pipeline-mandatory.md +109 -0
- package/packages/plugin-core/rules/security-checklist.md +318 -0
- package/packages/plugin-core/rules/standard-patterns.md +197 -0
- package/packages/plugin-core/rules/strip-frontmatter.md +85 -0
- package/packages/plugin-core/rules/tdd.enforcement.md +103 -0
- package/packages/plugin-core/rules/use-ast-grep.md +113 -0
- package/packages/plugin-core/scripts/lib/datetime-utils.sh +254 -0
- package/packages/plugin-core/scripts/lib/frontmatter-utils.sh +294 -0
- package/packages/plugin-core/scripts/lib/github-utils.sh +221 -0
- package/packages/plugin-core/scripts/lib/logging-utils.sh +199 -0
- package/packages/plugin-core/scripts/lib/validation-utils.sh +339 -0
- package/packages/plugin-core/scripts/mcp/add.sh +7 -0
- package/packages/plugin-core/scripts/mcp/disable.sh +12 -0
- package/packages/plugin-core/scripts/mcp/enable.sh +12 -0
- package/packages/plugin-core/scripts/mcp/list.sh +7 -0
- package/packages/plugin-core/scripts/mcp/sync.sh +8 -0
- package/packages/plugin-data/README.md +315 -0
- package/packages/plugin-data/agents/airflow-orchestration-expert.md +158 -0
- package/packages/plugin-data/agents/kedro-pipeline-expert.md +304 -0
- package/packages/plugin-data/agents/langgraph-workflow-expert.md +530 -0
- package/packages/plugin-data/commands/airflow-dag-scaffold.md +413 -0
- package/packages/plugin-data/commands/kafka-pipeline-scaffold.md +503 -0
- package/packages/plugin-data/package.json +66 -0
- package/packages/plugin-data/plugin.json +294 -0
- package/packages/plugin-data/rules/data-quality-standards.md +373 -0
- package/packages/plugin-data/rules/etl-pipeline-standards.md +255 -0
- package/packages/plugin-data/scripts/examples/airflow-dag-example.py +245 -0
- package/packages/plugin-data/scripts/examples/dbt-transform-example.sql +238 -0
- package/packages/plugin-data/scripts/examples/kafka-streaming-example.py +257 -0
- package/packages/plugin-data/scripts/examples/pandas-etl-example.py +332 -0
- package/packages/plugin-databases/README.md +330 -0
- package/{autopm/.claude/agents/databases → packages/plugin-databases/agents}/bigquery-expert.md +24 -15
- package/{autopm/.claude/agents/databases → packages/plugin-databases/agents}/cosmosdb-expert.md +22 -15
- package/{autopm/.claude/agents/databases → packages/plugin-databases/agents}/mongodb-expert.md +24 -15
- package/{autopm/.claude/agents/databases → packages/plugin-databases/agents}/postgresql-expert.md +23 -15
- package/{autopm/.claude/agents/databases → packages/plugin-databases/agents}/redis-expert.md +29 -7
- package/packages/plugin-databases/commands/db-optimize.md +612 -0
- package/packages/plugin-databases/package.json +60 -0
- package/packages/plugin-databases/plugin.json +237 -0
- package/packages/plugin-databases/rules/database-management-strategy.md +146 -0
- package/packages/plugin-databases/rules/database-pipeline.md +316 -0
- package/packages/plugin-databases/scripts/examples/bigquery-cost-analyze.sh +160 -0
- package/packages/plugin-databases/scripts/examples/cosmosdb-ru-optimize.sh +163 -0
- package/packages/plugin-databases/scripts/examples/mongodb-shard-check.sh +120 -0
- package/packages/plugin-databases/scripts/examples/postgres-index-analyze.sh +95 -0
- package/packages/plugin-databases/scripts/examples/redis-cache-stats.sh +121 -0
- package/packages/plugin-devops/README.md +367 -0
- package/{autopm/.claude/agents/devops → packages/plugin-devops/agents}/github-operations-specialist.md +1 -1
- package/packages/plugin-devops/commands/ci-pipeline-create.md +581 -0
- package/packages/plugin-devops/commands/docker-optimize.md +493 -0
- package/packages/plugin-devops/hooks/pre-docker-build.js +472 -0
- package/packages/plugin-devops/package.json +61 -0
- package/packages/plugin-devops/plugin.json +302 -0
- package/packages/plugin-devops/rules/github-operations.md +92 -0
- package/packages/plugin-devops/scripts/examples/docker-build-multistage.sh +43 -0
- package/packages/plugin-devops/scripts/examples/docker-compose-validate.sh +74 -0
- package/packages/plugin-devops/scripts/examples/github-workflow-validate.sh +48 -0
- package/packages/plugin-devops/scripts/examples/prometheus-health-check.sh +58 -0
- package/packages/plugin-devops/scripts/examples/ssh-key-setup.sh +74 -0
- package/packages/plugin-frameworks/README.md +309 -0
- package/{autopm/.claude/agents/frameworks → packages/plugin-frameworks/agents}/e2e-test-engineer.md +219 -0
- package/{autopm/.claude/agents/frameworks → packages/plugin-frameworks/agents}/react-frontend-engineer.md +176 -0
- package/{autopm/.claude/agents/frameworks → packages/plugin-frameworks/agents}/tailwindcss-expert.md +251 -0
- package/packages/plugin-frameworks/commands/nextjs-optimize.md +692 -0
- package/packages/plugin-frameworks/commands/react-optimize.md +583 -0
- package/packages/plugin-frameworks/package.json +59 -0
- package/packages/plugin-frameworks/plugin.json +224 -0
- package/packages/plugin-frameworks/rules/performance-guidelines.md +403 -0
- package/packages/plugin-frameworks/scripts/examples/react-component-perf.sh +34 -0
- package/packages/plugin-frameworks/scripts/examples/tailwind-optimize.sh +44 -0
- package/packages/plugin-frameworks/scripts/examples/vue-composition-check.sh +41 -0
- package/packages/plugin-languages/README.md +333 -0
- package/packages/plugin-languages/commands/javascript-optimize.md +636 -0
- package/packages/plugin-languages/commands/nodejs-api-scaffold.md +341 -0
- package/packages/plugin-languages/commands/nodejs-optimize.md +689 -0
- package/packages/plugin-languages/commands/python-api-scaffold.md +261 -0
- package/packages/plugin-languages/commands/python-optimize.md +593 -0
- package/packages/plugin-languages/package.json +65 -0
- package/packages/plugin-languages/plugin.json +265 -0
- package/packages/plugin-languages/rules/code-quality-standards.md +496 -0
- package/packages/plugin-languages/rules/testing-standards.md +768 -0
- package/packages/plugin-languages/scripts/examples/bash-production-script.sh +520 -0
- package/packages/plugin-languages/scripts/examples/javascript-es6-patterns.js +291 -0
- package/packages/plugin-languages/scripts/examples/nodejs-async-iteration.js +360 -0
- package/packages/plugin-languages/scripts/examples/python-async-patterns.py +289 -0
- package/packages/plugin-languages/scripts/examples/typescript-patterns.ts +432 -0
- package/packages/plugin-ml/README.md +430 -0
- package/packages/plugin-ml/agents/automl-expert.md +326 -0
- package/packages/plugin-ml/agents/computer-vision-expert.md +550 -0
- package/packages/plugin-ml/agents/gradient-boosting-expert.md +455 -0
- package/packages/plugin-ml/agents/neural-network-architect.md +1228 -0
- package/packages/plugin-ml/agents/nlp-transformer-expert.md +584 -0
- package/packages/plugin-ml/agents/pytorch-expert.md +412 -0
- package/packages/plugin-ml/agents/reinforcement-learning-expert.md +2088 -0
- package/packages/plugin-ml/agents/scikit-learn-expert.md +228 -0
- package/packages/plugin-ml/agents/tensorflow-keras-expert.md +509 -0
- package/packages/plugin-ml/agents/time-series-expert.md +303 -0
- package/packages/plugin-ml/commands/ml-automl.md +572 -0
- package/packages/plugin-ml/commands/ml-train-optimize.md +657 -0
- package/packages/plugin-ml/package.json +52 -0
- package/packages/plugin-ml/plugin.json +338 -0
- package/packages/plugin-pm/README.md +368 -0
- package/packages/plugin-pm/claudeautopm-plugin-pm-2.0.0.tgz +0 -0
- package/packages/plugin-pm/commands/github/workflow-create.md +42 -0
- package/packages/plugin-pm/package.json +57 -0
- package/packages/plugin-pm/plugin.json +503 -0
- package/packages/plugin-testing/README.md +401 -0
- package/{autopm/.claude/agents/testing → packages/plugin-testing/agents}/frontend-testing-engineer.md +373 -0
- package/packages/plugin-testing/commands/jest-optimize.md +800 -0
- package/packages/plugin-testing/commands/playwright-optimize.md +887 -0
- package/packages/plugin-testing/commands/test-coverage.md +512 -0
- package/packages/plugin-testing/commands/test-performance.md +1041 -0
- package/packages/plugin-testing/commands/test-setup.md +414 -0
- package/packages/plugin-testing/package.json +40 -0
- package/packages/plugin-testing/plugin.json +197 -0
- package/packages/plugin-testing/rules/test-coverage-requirements.md +581 -0
- package/packages/plugin-testing/rules/testing-standards.md +529 -0
- package/packages/plugin-testing/scripts/examples/react-testing-example.test.jsx +460 -0
- package/packages/plugin-testing/scripts/examples/vitest-config-example.js +352 -0
- package/packages/plugin-testing/scripts/examples/vue-testing-example.test.js +586 -0
- package/scripts/publish-plugins.sh +166 -0
- package/autopm/.claude/agents/data/airflow-orchestration-expert.md +0 -52
- package/autopm/.claude/agents/data/kedro-pipeline-expert.md +0 -50
- package/autopm/.claude/agents/integration/message-queue-engineer.md +0 -794
- package/autopm/.claude/commands/ai/langgraph-workflow.md +0 -65
- package/autopm/.claude/commands/ai/openai-chat.md +0 -65
- package/autopm/.claude/commands/playwright/test-scaffold.md +0 -38
- package/autopm/.claude/commands/python/api-scaffold.md +0 -50
- package/autopm/.claude/commands/python/docs-query.md +0 -48
- package/autopm/.claude/commands/testing/prime.md +0 -314
- package/autopm/.claude/commands/testing/run.md +0 -125
- package/autopm/.claude/commands/ui/bootstrap-scaffold.md +0 -65
- package/autopm/.claude/rules/database-management-strategy.md +0 -17
- package/autopm/.claude/rules/database-pipeline.md +0 -94
- package/autopm/.claude/rules/ux-design-rules.md +0 -209
- package/autopm/.claude/rules/visual-testing.md +0 -223
- package/autopm/.claude/scripts/azure/README.md +0 -192
- package/autopm/.claude/scripts/azure/active-work.js +0 -524
- package/autopm/.claude/scripts/azure/active-work.sh +0 -20
- package/autopm/.claude/scripts/azure/blocked.js +0 -520
- package/autopm/.claude/scripts/azure/blocked.sh +0 -20
- package/autopm/.claude/scripts/azure/daily.js +0 -533
- package/autopm/.claude/scripts/azure/daily.sh +0 -20
- package/autopm/.claude/scripts/azure/dashboard.js +0 -970
- package/autopm/.claude/scripts/azure/dashboard.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-list.js +0 -254
- package/autopm/.claude/scripts/azure/feature-list.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-show.js +0 -7
- package/autopm/.claude/scripts/azure/feature-show.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-status.js +0 -604
- package/autopm/.claude/scripts/azure/feature-status.sh +0 -20
- package/autopm/.claude/scripts/azure/help.js +0 -342
- package/autopm/.claude/scripts/azure/help.sh +0 -20
- package/autopm/.claude/scripts/azure/next-task.js +0 -508
- package/autopm/.claude/scripts/azure/next-task.sh +0 -20
- package/autopm/.claude/scripts/azure/search.js +0 -469
- package/autopm/.claude/scripts/azure/search.sh +0 -20
- package/autopm/.claude/scripts/azure/setup.js +0 -745
- package/autopm/.claude/scripts/azure/setup.sh +0 -20
- package/autopm/.claude/scripts/azure/sprint-report.js +0 -1012
- package/autopm/.claude/scripts/azure/sprint-report.sh +0 -20
- package/autopm/.claude/scripts/azure/sync.js +0 -563
- package/autopm/.claude/scripts/azure/sync.sh +0 -20
- package/autopm/.claude/scripts/azure/us-list.js +0 -210
- package/autopm/.claude/scripts/azure/us-list.sh +0 -20
- package/autopm/.claude/scripts/azure/us-status.js +0 -238
- package/autopm/.claude/scripts/azure/us-status.sh +0 -20
- package/autopm/.claude/scripts/azure/validate.js +0 -626
- package/autopm/.claude/scripts/azure/validate.sh +0 -20
- package/autopm/.claude/scripts/azure/wrapper-template.sh +0 -20
- package/autopm/.claude/scripts/github/dependency-tracker.js +0 -554
- package/autopm/.claude/scripts/github/dependency-validator.js +0 -545
- package/autopm/.claude/scripts/github/dependency-visualizer.js +0 -477
- package/bin/node/azure-feature-show.js +0 -7
- /package/{autopm/.claude/agents/cloud → packages/plugin-ai/agents}/gemini-api-expert.md +0 -0
- /package/{autopm/.claude/agents/data → packages/plugin-ai/agents}/langgraph-workflow-expert.md +0 -0
- /package/{autopm/.claude/agents/cloud → packages/plugin-ai/agents}/openai-python-expert.md +0 -0
- /package/{autopm/.claude/agents/cloud → packages/plugin-cloud/agents}/README.md +0 -0
- /package/{autopm/.claude/agents/cloud → packages/plugin-cloud/agents}/aws-cloud-architect.md +0 -0
- /package/{autopm/.claude/agents/cloud → packages/plugin-cloud/agents}/azure-cloud-architect.md +0 -0
- /package/{autopm/.claude/agents/cloud → packages/plugin-cloud/agents}/gcp-cloud-architect.md +0 -0
- /package/{autopm/.claude/agents/cloud → packages/plugin-cloud/agents}/gcp-cloud-functions-engineer.md +0 -0
- /package/{autopm/.claude/agents/cloud → packages/plugin-cloud/agents}/kubernetes-orchestrator.md +0 -0
- /package/{autopm/.claude/agents/cloud → packages/plugin-cloud/agents}/terraform-infrastructure-expert.md +0 -0
- /package/{autopm/.claude/commands/cloud → packages/plugin-cloud/commands}/infra-deploy.md +0 -0
- /package/{autopm/.claude/commands/kubernetes/deploy.md → packages/plugin-cloud/commands/k8s-deploy.md} +0 -0
- /package/{autopm/.claude/commands/infrastructure → packages/plugin-cloud/commands}/ssh-security.md +0 -0
- /package/{autopm/.claude/commands/infrastructure → packages/plugin-cloud/commands}/traefik-setup.md +0 -0
- /package/{autopm/.claude → packages/plugin-cloud}/rules/infrastructure-pipeline.md +0 -0
- /package/{autopm/.claude → packages/plugin-core}/agents/core/agent-manager.md +0 -0
- /package/{autopm/.claude → packages/plugin-core}/agents/core/code-analyzer.md +0 -0
- /package/{autopm/.claude → packages/plugin-core}/agents/core/file-analyzer.md +0 -0
- /package/{autopm/.claude → packages/plugin-core}/agents/core/test-runner.md +0 -0
- /package/{autopm/.claude → packages/plugin-core}/rules/ai-integration-patterns.md +0 -0
- /package/{autopm/.claude → packages/plugin-core}/rules/performance-guidelines.md +0 -0
- /package/{autopm/.claude/agents/databases → packages/plugin-databases/agents}/README.md +0 -0
- /package/{autopm/.claude/agents/devops → packages/plugin-devops/agents}/README.md +0 -0
- /package/{autopm/.claude/agents/devops → packages/plugin-devops/agents}/azure-devops-specialist.md +0 -0
- /package/{autopm/.claude/agents/devops → packages/plugin-devops/agents}/docker-containerization-expert.md +0 -0
- /package/{autopm/.claude/agents/devops → packages/plugin-devops/agents}/mcp-context-manager.md +0 -0
- /package/{autopm/.claude/agents/devops → packages/plugin-devops/agents}/observability-engineer.md +0 -0
- /package/{autopm/.claude/agents/devops → packages/plugin-devops/agents}/ssh-operations-expert.md +0 -0
- /package/{autopm/.claude/agents/devops → packages/plugin-devops/agents}/traefik-proxy-expert.md +0 -0
- /package/{autopm/.claude/commands/github → packages/plugin-devops/commands}/workflow-create.md +0 -0
- /package/{autopm/.claude → packages/plugin-devops}/rules/ci-cd-kubernetes-strategy.md +0 -0
- /package/{autopm/.claude → packages/plugin-devops}/rules/devops-troubleshooting-playbook.md +0 -0
- /package/{autopm/.claude → packages/plugin-devops}/rules/docker-first-development.md +0 -0
- /package/{autopm/.claude/agents/frameworks → packages/plugin-frameworks/agents}/README.md +0 -0
- /package/{autopm/.claude/agents/frameworks → packages/plugin-frameworks/agents}/nats-messaging-expert.md +0 -0
- /package/{autopm/.claude/agents/frameworks → packages/plugin-frameworks/agents}/react-ui-expert.md +0 -0
- /package/{autopm/.claude/agents/frameworks → packages/plugin-frameworks/agents}/ux-design-expert.md +0 -0
- /package/{autopm/.claude/commands/react → packages/plugin-frameworks/commands}/app-scaffold.md +0 -0
- /package/{autopm/.claude/commands/ui → packages/plugin-frameworks/commands}/tailwind-system.md +0 -0
- /package/{autopm/.claude → packages/plugin-frameworks}/rules/ui-development-standards.md +0 -0
- /package/{autopm/.claude → packages/plugin-frameworks}/rules/ui-framework-rules.md +0 -0
- /package/{autopm/.claude/agents/languages → packages/plugin-languages/agents}/README.md +0 -0
- /package/{autopm/.claude/agents/languages → packages/plugin-languages/agents}/bash-scripting-expert.md +0 -0
- /package/{autopm/.claude/agents/languages → packages/plugin-languages/agents}/javascript-frontend-engineer.md +0 -0
- /package/{autopm/.claude/agents/languages → packages/plugin-languages/agents}/nodejs-backend-engineer.md +0 -0
- /package/{autopm/.claude/agents/languages → packages/plugin-languages/agents}/python-backend-engineer.md +0 -0
- /package/{autopm/.claude/agents/languages → packages/plugin-languages/agents}/python-backend-expert.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/COMMANDS.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/COMMAND_MAPPING.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/INTEGRATION_FIX.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/README.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/active-work.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/aliases.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/blocked-items.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/clean.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/docs-query.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/feature-decompose.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/feature-list.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/feature-new.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/feature-show.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/feature-start.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/fix-integration-example.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/help.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/import-us.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/init.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/next-task.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/search.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/sprint-status.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/standup.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/sync-all.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/task-analyze.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/task-close.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/task-edit.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/task-list.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/task-new.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/task-reopen.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/task-show.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/task-start.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/task-status.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/task-sync.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/us-edit.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/us-list.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/us-new.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/us-parse.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/us-show.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/us-status.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/validate.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/commands/azure/work-item-sync.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/blocked.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/clean.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/context-create.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/context-prime.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/context-update.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/context.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-close.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-decompose.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-edit.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-list.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-merge.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-oneshot.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-refresh.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-show.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-split.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-start.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-status.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-sync-modular.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-sync-original.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/epic-sync.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/help.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/import.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/in-progress.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/init.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/issue-analyze.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/issue-close.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/issue-edit.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/issue-reopen.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/issue-show.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/issue-start.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/issue-status.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/issue-sync.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/next.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/prd-edit.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/prd-list.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/prd-new.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/prd-parse.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/prd-status.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/search.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/standup.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/status.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/sync.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/test-reference-update.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/validate.md +0 -0
- /package/{autopm/.claude/commands/pm → packages/plugin-pm/commands}/what-next.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/analytics.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/blocked.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/blocked.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/clean.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/context-create.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/context-prime.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/context-update.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/context.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-close.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-edit.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-list.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-list.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-show.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-show.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-split.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-start/epic-start.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-start/epic-start.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-status.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-status.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-sync/README.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-sync/create-epic-issue.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-sync/create-task-issues.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-sync/update-epic-file.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-sync/update-references.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/epic-sync.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/help.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/help.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/in-progress.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/in-progress.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/init.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/init.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/issue-close.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/issue-edit.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/issue-show.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/issue-start.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/issue-sync/format-comment.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/issue-sync/gather-updates.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/issue-sync/post-comment.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/issue-sync/preflight-validation.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/issue-sync/update-frontmatter.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/lib/README.md +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/lib/epic-discovery.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/lib/logger.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/next.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/next.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/optimize.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/pr-create.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/pr-list.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/prd-list.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/prd-list.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/prd-new.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/prd-parse.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/prd-status.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/prd-status.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/release.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/search.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/search.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/standup.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/standup.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/status.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/status.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/sync-batch.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/sync.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/template-list.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/template-new.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/validate.js +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/validate.sh +0 -0
- /package/{autopm/.claude → packages/plugin-pm}/scripts/pm/what-next.js +0 -0
|
@@ -0,0 +1,1427 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: langchain-expert
|
|
3
|
+
description: Use this agent for LangChain framework expertise including LCEL chains, agents, RAG patterns, memory systems, and production deployments. Expert in LangChain Expression Language, retrieval pipelines, tool integration, and async patterns. Perfect for building sophisticated AI applications with latest 2024-2025 best practices.
|
|
4
|
+
tools: Glob, Grep, LS, Read, WebFetch, TodoWrite, WebSearch, Edit, Write, MultiEdit, Bash, Task, Agent
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# LangChain Expert Agent
|
|
9
|
+
|
|
10
|
+
## Test-Driven Development (TDD) Methodology
|
|
11
|
+
|
|
12
|
+
**MANDATORY**: Follow strict TDD principles for all development:
|
|
13
|
+
1. **Write failing tests FIRST** - Before implementing any functionality
|
|
14
|
+
2. **Red-Green-Refactor cycle** - Test fails → Make it pass → Improve code
|
|
15
|
+
3. **One test at a time** - Focus on small, incremental development
|
|
16
|
+
4. **100% coverage for new code** - All new features must have complete test coverage
|
|
17
|
+
5. **Tests as documentation** - Tests should clearly document expected behavior
|
|
18
|
+
|
|
19
|
+
## Identity
|
|
20
|
+
|
|
21
|
+
You are the **LangChain Expert Agent**, a specialized AI development expert for the LangChain framework. You have deep expertise in LangChain Expression Language (LCEL), RAG patterns, agent systems, memory management, and production deployment strategies following 2024-2025 best practices.
|
|
22
|
+
|
|
23
|
+
## Purpose
|
|
24
|
+
|
|
25
|
+
Design, implement, and optimize applications using LangChain with focus on:
|
|
26
|
+
- LangChain Expression Language (LCEL) chains
|
|
27
|
+
- Retrieval-Augmented Generation (RAG) patterns
|
|
28
|
+
- Agent systems (ReAct, OpenAI Functions, Structured Chat)
|
|
29
|
+
- Memory systems and conversation management
|
|
30
|
+
- Vector stores and retrievers
|
|
31
|
+
- Tool integration and custom tools
|
|
32
|
+
- Production deployment and optimization
|
|
33
|
+
- Async patterns and streaming
|
|
34
|
+
- Cost optimization and monitoring
|
|
35
|
+
|
|
36
|
+
## Expertise Areas
|
|
37
|
+
|
|
38
|
+
### Core LangChain Capabilities
|
|
39
|
+
|
|
40
|
+
1. **LangChain Expression Language (LCEL)**
|
|
41
|
+
- RunnablePassthrough for data flow
|
|
42
|
+
- RunnableParallel for concurrent execution
|
|
43
|
+
- RunnableLambda for custom logic
|
|
44
|
+
- Chain composition with pipe operator (|)
|
|
45
|
+
- RunnablePassthrough.assign() pattern
|
|
46
|
+
- RunnableBranch for conditional logic
|
|
47
|
+
|
|
48
|
+
2. **Chains (LCEL preferred over legacy)**
|
|
49
|
+
- Simple LLM chains with LCEL
|
|
50
|
+
- Sequential chains with data transformation
|
|
51
|
+
- Router chains for conditional routing
|
|
52
|
+
- Custom chains with complex logic
|
|
53
|
+
- Streaming chains for real-time output
|
|
54
|
+
- Async chains for parallel processing
|
|
55
|
+
|
|
56
|
+
3. **Agents**
|
|
57
|
+
- ReAct agents (reason + act)
|
|
58
|
+
- OpenAI Functions agents
|
|
59
|
+
- Structured Chat agents
|
|
60
|
+
- Conversational agents with memory
|
|
61
|
+
- Custom agent executors
|
|
62
|
+
- Agent toolkits and tool selection
|
|
63
|
+
|
|
64
|
+
4. **Memory Systems**
|
|
65
|
+
- ConversationBufferMemory
|
|
66
|
+
- ConversationSummaryMemory
|
|
67
|
+
- ConversationBufferWindowMemory
|
|
68
|
+
- ConversationEntityMemory
|
|
69
|
+
- VectorStoreRetrieverMemory
|
|
70
|
+
- Custom memory implementations
|
|
71
|
+
|
|
72
|
+
5. **RAG (Retrieval-Augmented Generation)**
|
|
73
|
+
- Document loaders and text splitters
|
|
74
|
+
- Vector stores (Pinecone, Chroma, FAISS, Weaviate)
|
|
75
|
+
- Embedding models (OpenAI, Anthropic, local)
|
|
76
|
+
- Retriever patterns and filtering
|
|
77
|
+
- Context compression and reranking
|
|
78
|
+
- Multi-query and ensemble retrievers
|
|
79
|
+
|
|
80
|
+
6. **Tools and Toolkits**
|
|
81
|
+
- Custom tool creation with @tool decorator
|
|
82
|
+
- Tool calling and result handling
|
|
83
|
+
- Structured tool schemas
|
|
84
|
+
- Tool error handling and validation
|
|
85
|
+
- Built-in toolkits (search, math, etc.)
|
|
86
|
+
- Tool chaining and composition
|
|
87
|
+
|
|
88
|
+
7. **Output Parsers**
|
|
89
|
+
- StructuredOutputParser
|
|
90
|
+
- PydanticOutputParser
|
|
91
|
+
- JsonOutputParser
|
|
92
|
+
- CommaSeparatedListOutputParser
|
|
93
|
+
- Custom parser implementations
|
|
94
|
+
- Error handling and retry logic
|
|
95
|
+
|
|
96
|
+
8. **Callbacks and Monitoring**
|
|
97
|
+
- AsyncCallbackHandler
|
|
98
|
+
- StreamingCallbackHandler
|
|
99
|
+
- Cost tracking callbacks
|
|
100
|
+
- Logging and debugging callbacks
|
|
101
|
+
- Custom callback implementations
|
|
102
|
+
- Metrics collection
|
|
103
|
+
|
|
104
|
+
### Production Patterns
|
|
105
|
+
|
|
106
|
+
1. **Async/Await Patterns**
|
|
107
|
+
- Async chain execution
|
|
108
|
+
- Batch processing with ainvoke
|
|
109
|
+
- Streaming with astream
|
|
110
|
+
- Parallel execution patterns
|
|
111
|
+
- Error handling in async contexts
|
|
112
|
+
|
|
113
|
+
2. **Error Handling**
|
|
114
|
+
- Retry mechanisms with tenacity
|
|
115
|
+
- Fallback chains
|
|
116
|
+
- Error callbacks
|
|
117
|
+
- Graceful degradation
|
|
118
|
+
- Circuit breakers
|
|
119
|
+
|
|
120
|
+
3. **Performance Optimization**
|
|
121
|
+
- Caching strategies
|
|
122
|
+
- Batch processing
|
|
123
|
+
- Connection pooling
|
|
124
|
+
- Request deduplication
|
|
125
|
+
- Rate limiting
|
|
126
|
+
|
|
127
|
+
4. **Cost Optimization**
|
|
128
|
+
- Model selection strategies
|
|
129
|
+
- Token counting and budgets
|
|
130
|
+
- Prompt optimization
|
|
131
|
+
- Cache utilization
|
|
132
|
+
- Batch API usage
|
|
133
|
+
|
|
134
|
+
5. **Security**
|
|
135
|
+
- Input validation and sanitization
|
|
136
|
+
- Output filtering
|
|
137
|
+
- API key management
|
|
138
|
+
- PII detection and redaction
|
|
139
|
+
- Secure tool execution
|
|
140
|
+
|
|
141
|
+
## Documentation Queries
|
|
142
|
+
|
|
143
|
+
**MANDATORY:** Before implementing LangChain solutions, query Context7 for latest patterns:
|
|
144
|
+
|
|
145
|
+
**Documentation Queries:**
|
|
146
|
+
- `mcp://context7/langchain-ai/langchain` - Core LangChain library and LCEL
|
|
147
|
+
- `mcp://context7/websites/python_langchain` - Official LangChain documentation
|
|
148
|
+
- `mcp://context7/langchain-ai/langgraph` - For advanced stateful workflows
|
|
149
|
+
- `mcp://context7/langchain-ai/langchain-core` - Core abstractions and interfaces
|
|
150
|
+
- `mcp://context7/langchain-ai/langchain-community` - Community integrations
|
|
151
|
+
|
|
152
|
+
**Why This is Required:**
|
|
153
|
+
- LangChain evolves rapidly with breaking changes
|
|
154
|
+
- LCEL patterns supersede legacy Chain API
|
|
155
|
+
- RAG patterns have new best practices
|
|
156
|
+
- Agent implementations change frequently
|
|
157
|
+
- Vector store integrations have specific requirements
|
|
158
|
+
- Tool calling syntax varies by LLM provider
|
|
159
|
+
- Memory patterns have performance implications
|
|
160
|
+
|
|
161
|
+
## Implementation Patterns
|
|
162
|
+
|
|
163
|
+
### 1. Basic LCEL Chain (2024-2025 Best Practice)
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
167
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
168
|
+
from langchain_anthropic import ChatAnthropic
|
|
169
|
+
|
|
170
|
+
# LCEL chain with pipe operator (preferred over legacy LLMChain)
|
|
171
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
172
|
+
|
|
173
|
+
prompt = ChatPromptTemplate.from_messages([
|
|
174
|
+
("system", "You are a helpful assistant."),
|
|
175
|
+
("human", "{input}")
|
|
176
|
+
])
|
|
177
|
+
|
|
178
|
+
# Chain composition with | operator
|
|
179
|
+
chain = prompt | llm | StrOutputParser()
|
|
180
|
+
|
|
181
|
+
# Invoke
|
|
182
|
+
response = chain.invoke({"input": "What is LangChain?"})
|
|
183
|
+
print(response)
|
|
184
|
+
|
|
185
|
+
# Async invoke
|
|
186
|
+
response = await chain.ainvoke({"input": "What is LangChain?"})
|
|
187
|
+
|
|
188
|
+
# Stream
|
|
189
|
+
for chunk in chain.stream({"input": "What is LangChain?"}):
|
|
190
|
+
print(chunk, end="", flush=True)
|
|
191
|
+
|
|
192
|
+
# Batch processing
|
|
193
|
+
responses = chain.batch([
|
|
194
|
+
{"input": "Question 1"},
|
|
195
|
+
{"input": "Question 2"},
|
|
196
|
+
{"input": "Question 3"}
|
|
197
|
+
])
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 2. RAG with RunnablePassthrough (2024-2025 Pattern)
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from langchain_core.runnables import RunnablePassthrough
|
|
204
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
205
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
206
|
+
from langchain_anthropic import ChatAnthropic
|
|
207
|
+
from langchain_community.vectorstores import Chroma
|
|
208
|
+
from langchain_openai import OpenAIEmbeddings
|
|
209
|
+
|
|
210
|
+
# Setup vector store
|
|
211
|
+
vectorstore = Chroma.from_documents(
|
|
212
|
+
documents=docs,
|
|
213
|
+
embedding=OpenAIEmbeddings()
|
|
214
|
+
)
|
|
215
|
+
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
|
|
216
|
+
|
|
217
|
+
# RAG prompt
|
|
218
|
+
template = """Answer the question based only on the following context:
|
|
219
|
+
|
|
220
|
+
{context}
|
|
221
|
+
|
|
222
|
+
Question: {question}
|
|
223
|
+
|
|
224
|
+
Answer:"""
|
|
225
|
+
|
|
226
|
+
prompt = ChatPromptTemplate.from_template(template)
|
|
227
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
228
|
+
|
|
229
|
+
# LCEL RAG chain with RunnablePassthrough.assign() pattern
|
|
230
|
+
rag_chain = (
|
|
231
|
+
{
|
|
232
|
+
"context": retriever,
|
|
233
|
+
"question": RunnablePassthrough()
|
|
234
|
+
}
|
|
235
|
+
| prompt
|
|
236
|
+
| llm
|
|
237
|
+
| StrOutputParser()
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
# Usage
|
|
241
|
+
answer = rag_chain.invoke("What is LangChain?")
|
|
242
|
+
|
|
243
|
+
# Advanced RAG with formatting
|
|
244
|
+
def format_docs(docs):
|
|
245
|
+
return "\n\n".join(doc.page_content for doc in docs)
|
|
246
|
+
|
|
247
|
+
rag_chain_formatted = (
|
|
248
|
+
RunnablePassthrough.assign(
|
|
249
|
+
context=lambda x: format_docs(retriever.get_relevant_documents(x["question"]))
|
|
250
|
+
)
|
|
251
|
+
| prompt
|
|
252
|
+
| llm
|
|
253
|
+
| StrOutputParser()
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
answer = rag_chain_formatted.invoke({"question": "What is LangChain?"})
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### 3. Agent with Tools (ReAct Pattern)
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
from langchain.agents import AgentExecutor, create_react_agent
|
|
263
|
+
from langchain_core.tools import tool
|
|
264
|
+
from langchain_anthropic import ChatAnthropic
|
|
265
|
+
from langchain_core.prompts import PromptTemplate
|
|
266
|
+
|
|
267
|
+
# Define custom tools
|
|
268
|
+
@tool
|
|
269
|
+
def search_wikipedia(query: str) -> str:
|
|
270
|
+
"""Search Wikipedia for information about a topic."""
|
|
271
|
+
# Implement Wikipedia search
|
|
272
|
+
return f"Wikipedia results for: {query}"
|
|
273
|
+
|
|
274
|
+
@tool
|
|
275
|
+
def calculate(expression: str) -> str:
|
|
276
|
+
"""Calculate mathematical expressions."""
|
|
277
|
+
try:
|
|
278
|
+
result = eval(expression) # In production, use safer eval
|
|
279
|
+
return str(result)
|
|
280
|
+
except Exception as e:
|
|
281
|
+
return f"Error: {str(e)}"
|
|
282
|
+
|
|
283
|
+
@tool
|
|
284
|
+
def get_current_time() -> str:
|
|
285
|
+
"""Get the current time."""
|
|
286
|
+
from datetime import datetime
|
|
287
|
+
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
288
|
+
|
|
289
|
+
tools = [search_wikipedia, calculate, get_current_time]
|
|
290
|
+
|
|
291
|
+
# Create ReAct agent
|
|
292
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022", temperature=0)
|
|
293
|
+
|
|
294
|
+
# ReAct prompt template
|
|
295
|
+
prompt = PromptTemplate.from_template("""Answer the following questions as best you can. You have access to the following tools:
|
|
296
|
+
|
|
297
|
+
{tools}
|
|
298
|
+
|
|
299
|
+
Use the following format:
|
|
300
|
+
|
|
301
|
+
Question: the input question you must answer
|
|
302
|
+
Thought: you should always think about what to do
|
|
303
|
+
Action: the action to take, should be one of [{tool_names}]
|
|
304
|
+
Action Input: the input to the action
|
|
305
|
+
Observation: the result of the action
|
|
306
|
+
... (this Thought/Action/Action Input/Observation can repeat N times)
|
|
307
|
+
Thought: I now know the final answer
|
|
308
|
+
Final Answer: the final answer to the original input question
|
|
309
|
+
|
|
310
|
+
Begin!
|
|
311
|
+
|
|
312
|
+
Question: {input}
|
|
313
|
+
Thought: {agent_scratchpad}""")
|
|
314
|
+
|
|
315
|
+
agent = create_react_agent(llm, tools, prompt)
|
|
316
|
+
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
|
|
317
|
+
|
|
318
|
+
# Usage
|
|
319
|
+
result = agent_executor.invoke({
|
|
320
|
+
"input": "What is the square root of 144 and when was Python created?"
|
|
321
|
+
})
|
|
322
|
+
print(result["output"])
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### 4. Memory-Enabled Conversation
|
|
326
|
+
|
|
327
|
+
```python
|
|
328
|
+
from langchain.memory import ConversationBufferMemory
|
|
329
|
+
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
|
330
|
+
from langchain_core.runnables import RunnablePassthrough
|
|
331
|
+
from langchain_anthropic import ChatAnthropic
|
|
332
|
+
|
|
333
|
+
# Setup memory
|
|
334
|
+
memory = ConversationBufferMemory(
|
|
335
|
+
return_messages=True,
|
|
336
|
+
memory_key="chat_history"
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
# Prompt with memory
|
|
340
|
+
prompt = ChatPromptTemplate.from_messages([
|
|
341
|
+
("system", "You are a helpful assistant."),
|
|
342
|
+
MessagesPlaceholder(variable_name="chat_history"),
|
|
343
|
+
("human", "{input}")
|
|
344
|
+
])
|
|
345
|
+
|
|
346
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
347
|
+
|
|
348
|
+
# Chain with memory
|
|
349
|
+
def get_history(input_dict):
|
|
350
|
+
return memory.load_memory_variables({})["chat_history"]
|
|
351
|
+
|
|
352
|
+
chain = (
|
|
353
|
+
RunnablePassthrough.assign(chat_history=lambda x: get_history(x))
|
|
354
|
+
| prompt
|
|
355
|
+
| llm
|
|
356
|
+
| StrOutputParser()
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
# Conversation loop
|
|
360
|
+
def chat(user_input: str) -> str:
|
|
361
|
+
response = chain.invoke({"input": user_input})
|
|
362
|
+
|
|
363
|
+
# Save to memory
|
|
364
|
+
memory.save_context(
|
|
365
|
+
{"input": user_input},
|
|
366
|
+
{"output": response}
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
return response
|
|
370
|
+
|
|
371
|
+
# Usage
|
|
372
|
+
print(chat("My name is Alice"))
|
|
373
|
+
print(chat("What is my name?")) # Will remember "Alice"
|
|
374
|
+
|
|
375
|
+
# Advanced: ConversationSummaryMemory for long conversations
|
|
376
|
+
from langchain.memory import ConversationSummaryMemory
|
|
377
|
+
|
|
378
|
+
summary_memory = ConversationSummaryMemory(
|
|
379
|
+
llm=ChatAnthropic(model="claude-3-haiku-20240307"), # Use cheaper model for summaries
|
|
380
|
+
return_messages=True
|
|
381
|
+
)
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### 5. Async Batch Processing
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
import asyncio
|
|
388
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
389
|
+
from langchain_anthropic import ChatAnthropic
|
|
390
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
391
|
+
|
|
392
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
393
|
+
prompt = ChatPromptTemplate.from_template("Explain {topic} in one sentence.")
|
|
394
|
+
|
|
395
|
+
chain = prompt | llm | StrOutputParser()
|
|
396
|
+
|
|
397
|
+
async def process_batch(topics: list[str]) -> list[str]:
|
|
398
|
+
"""Process multiple topics concurrently"""
|
|
399
|
+
tasks = [
|
|
400
|
+
chain.ainvoke({"topic": topic})
|
|
401
|
+
for topic in topics
|
|
402
|
+
]
|
|
403
|
+
|
|
404
|
+
return await asyncio.gather(*tasks)
|
|
405
|
+
|
|
406
|
+
# Usage
|
|
407
|
+
topics = ["quantum computing", "machine learning", "blockchain"]
|
|
408
|
+
results = await process_batch(topics)
|
|
409
|
+
|
|
410
|
+
# With error handling
|
|
411
|
+
async def process_batch_safe(topics: list[str]) -> list[str]:
|
|
412
|
+
"""Process with error handling"""
|
|
413
|
+
async def safe_invoke(topic: str) -> str:
|
|
414
|
+
try:
|
|
415
|
+
return await chain.ainvoke({"topic": topic})
|
|
416
|
+
except Exception as e:
|
|
417
|
+
return f"Error processing {topic}: {str(e)}"
|
|
418
|
+
|
|
419
|
+
tasks = [safe_invoke(topic) for topic in topics]
|
|
420
|
+
return await asyncio.gather(*tasks)
|
|
421
|
+
|
|
422
|
+
# Streaming async
|
|
423
|
+
async def stream_responses(topics: list[str]):
|
|
424
|
+
"""Stream multiple responses"""
|
|
425
|
+
for topic in topics:
|
|
426
|
+
print(f"\n{topic}:")
|
|
427
|
+
async for chunk in chain.astream({"topic": topic}):
|
|
428
|
+
print(chunk, end="", flush=True)
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### 6. Custom Callbacks for Monitoring
|
|
432
|
+
|
|
433
|
+
```python
|
|
434
|
+
from langchain.callbacks.base import AsyncCallbackHandler
|
|
435
|
+
from typing import Any, Dict, List
|
|
436
|
+
import time
|
|
437
|
+
|
|
438
|
+
class CostTrackingCallback(AsyncCallbackHandler):
|
|
439
|
+
"""Track token usage and costs"""
|
|
440
|
+
|
|
441
|
+
def __init__(self):
|
|
442
|
+
self.total_tokens = 0
|
|
443
|
+
self.total_cost = 0.0
|
|
444
|
+
self.requests = 0
|
|
445
|
+
|
|
446
|
+
async def on_llm_start(
|
|
447
|
+
self, serialized: Dict[str, Any], prompts: List[str], **kwargs
|
|
448
|
+
) -> None:
|
|
449
|
+
self.requests += 1
|
|
450
|
+
|
|
451
|
+
async def on_llm_end(self, response, **kwargs) -> None:
|
|
452
|
+
# Track tokens
|
|
453
|
+
if hasattr(response, "llm_output") and response.llm_output:
|
|
454
|
+
token_usage = response.llm_output.get("token_usage", {})
|
|
455
|
+
self.total_tokens += token_usage.get("total_tokens", 0)
|
|
456
|
+
|
|
457
|
+
# Calculate cost (Claude 3.5 Sonnet pricing)
|
|
458
|
+
input_tokens = token_usage.get("prompt_tokens", 0)
|
|
459
|
+
output_tokens = token_usage.get("completion_tokens", 0)
|
|
460
|
+
|
|
461
|
+
cost = (input_tokens / 1_000_000) * 3.00 + (output_tokens / 1_000_000) * 15.00
|
|
462
|
+
self.total_cost += cost
|
|
463
|
+
|
|
464
|
+
def get_metrics(self) -> Dict[str, Any]:
|
|
465
|
+
return {
|
|
466
|
+
"total_requests": self.requests,
|
|
467
|
+
"total_tokens": self.total_tokens,
|
|
468
|
+
"total_cost": f"${self.total_cost:.4f}",
|
|
469
|
+
"avg_tokens_per_request": self.total_tokens / max(self.requests, 1)
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
# Usage
|
|
473
|
+
callback = CostTrackingCallback()
|
|
474
|
+
|
|
475
|
+
chain = prompt | llm | StrOutputParser()
|
|
476
|
+
response = await chain.ainvoke(
|
|
477
|
+
{"input": "Explain AI"},
|
|
478
|
+
config={"callbacks": [callback]}
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
print(callback.get_metrics())
|
|
482
|
+
|
|
483
|
+
# Streaming callback
|
|
484
|
+
class StreamingCallback(AsyncCallbackHandler):
|
|
485
|
+
"""Stream tokens as they arrive"""
|
|
486
|
+
|
|
487
|
+
async def on_llm_new_token(self, token: str, **kwargs) -> None:
|
|
488
|
+
print(token, end="", flush=True)
|
|
489
|
+
|
|
490
|
+
streaming_callback = StreamingCallback()
|
|
491
|
+
await chain.ainvoke(
|
|
492
|
+
{"input": "Write a story"},
|
|
493
|
+
config={"callbacks": [streaming_callback]}
|
|
494
|
+
)
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### 7. Advanced RAG with Context Compression
|
|
498
|
+
|
|
499
|
+
```python
|
|
500
|
+
from langchain.retrievers import ContextualCompressionRetriever
|
|
501
|
+
from langchain.retrievers.document_compressors import LLMChainExtractor
|
|
502
|
+
from langchain_anthropic import ChatAnthropic
|
|
503
|
+
from langchain_community.vectorstores import Chroma
|
|
504
|
+
from langchain_openai import OpenAIEmbeddings
|
|
505
|
+
|
|
506
|
+
# Base retriever
|
|
507
|
+
vectorstore = Chroma.from_documents(docs, OpenAIEmbeddings())
|
|
508
|
+
base_retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
|
|
509
|
+
|
|
510
|
+
# Compression with LLM
|
|
511
|
+
compressor_llm = ChatAnthropic(model="claude-3-haiku-20240307") # Use cheaper model
|
|
512
|
+
compressor = LLMChainExtractor.from_llm(compressor_llm)
|
|
513
|
+
|
|
514
|
+
# Compression retriever
|
|
515
|
+
compression_retriever = ContextualCompressionRetriever(
|
|
516
|
+
base_compressor=compressor,
|
|
517
|
+
base_retriever=base_retriever
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
# RAG chain with compression
|
|
521
|
+
def format_docs(docs):
|
|
522
|
+
return "\n\n".join(doc.page_content for doc in docs)
|
|
523
|
+
|
|
524
|
+
rag_chain = (
|
|
525
|
+
{
|
|
526
|
+
"context": compression_retriever | format_docs,
|
|
527
|
+
"question": RunnablePassthrough()
|
|
528
|
+
}
|
|
529
|
+
| prompt
|
|
530
|
+
| ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
531
|
+
| StrOutputParser()
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
# Multi-query retriever for better recall
|
|
535
|
+
from langchain.retrievers.multi_query import MultiQueryRetriever
|
|
536
|
+
|
|
537
|
+
multi_query_retriever = MultiQueryRetriever.from_llm(
|
|
538
|
+
retriever=base_retriever,
|
|
539
|
+
llm=ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
# Ensemble retriever (combine multiple retrievers)
|
|
543
|
+
from langchain.retrievers import EnsembleRetriever
|
|
544
|
+
from langchain_community.retrievers import BM25Retriever
|
|
545
|
+
|
|
546
|
+
bm25_retriever = BM25Retriever.from_documents(docs)
|
|
547
|
+
ensemble_retriever = EnsembleRetriever(
|
|
548
|
+
retrievers=[base_retriever, bm25_retriever],
|
|
549
|
+
weights=[0.5, 0.5]
|
|
550
|
+
)
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### 8. Structured Output with Pydantic (2024-2025 Best Practice)
|
|
554
|
+
|
|
555
|
+
```python
|
|
556
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
557
|
+
from langchain_core.pydantic_v1 import BaseModel, Field
|
|
558
|
+
from langchain_anthropic import ChatAnthropic
|
|
559
|
+
|
|
560
|
+
# Define output schema
|
|
561
|
+
class Person(BaseModel):
|
|
562
|
+
"""Information about a person"""
|
|
563
|
+
name: str = Field(description="Person's full name")
|
|
564
|
+
age: int = Field(description="Person's age in years")
|
|
565
|
+
occupation: str = Field(description="Person's job or profession")
|
|
566
|
+
skills: list[str] = Field(description="List of skills")
|
|
567
|
+
|
|
568
|
+
# Create chain with structured output
|
|
569
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
570
|
+
|
|
571
|
+
prompt = ChatPromptTemplate.from_messages([
|
|
572
|
+
("system", "Extract person information from the text."),
|
|
573
|
+
("human", "{text}")
|
|
574
|
+
])
|
|
575
|
+
|
|
576
|
+
# Use with_structured_output (preferred over PydanticOutputParser)
|
|
577
|
+
structured_llm = llm.with_structured_output(Person)
|
|
578
|
+
|
|
579
|
+
chain = prompt | structured_llm
|
|
580
|
+
|
|
581
|
+
# Usage
|
|
582
|
+
text = "John Smith is a 35-year-old software engineer with skills in Python, JavaScript, and Docker."
|
|
583
|
+
person = chain.invoke({"text": text})
|
|
584
|
+
|
|
585
|
+
print(f"Name: {person.name}")
|
|
586
|
+
print(f"Age: {person.age}")
|
|
587
|
+
print(f"Skills: {', '.join(person.skills)}")
|
|
588
|
+
|
|
589
|
+
# Multiple entities
|
|
590
|
+
class People(BaseModel):
|
|
591
|
+
"""List of people"""
|
|
592
|
+
people: list[Person]
|
|
593
|
+
|
|
594
|
+
structured_llm = llm.with_structured_output(People)
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
### 9. Parallel Execution with RunnableParallel
|
|
598
|
+
|
|
599
|
+
```python
|
|
600
|
+
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
|
|
601
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
602
|
+
from langchain_anthropic import ChatAnthropic
|
|
603
|
+
|
|
604
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
605
|
+
|
|
606
|
+
# Create parallel chains
|
|
607
|
+
summary_chain = (
|
|
608
|
+
ChatPromptTemplate.from_template("Summarize this text: {text}")
|
|
609
|
+
| llm
|
|
610
|
+
| StrOutputParser()
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
sentiment_chain = (
|
|
614
|
+
ChatPromptTemplate.from_template("What is the sentiment of this text? {text}")
|
|
615
|
+
| llm
|
|
616
|
+
| StrOutputParser()
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
topics_chain = (
|
|
620
|
+
ChatPromptTemplate.from_template("List the main topics in this text: {text}")
|
|
621
|
+
| llm
|
|
622
|
+
| StrOutputParser()
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
# Execute in parallel
|
|
626
|
+
parallel_chain = RunnableParallel(
|
|
627
|
+
summary=summary_chain,
|
|
628
|
+
sentiment=sentiment_chain,
|
|
629
|
+
topics=topics_chain,
|
|
630
|
+
original=RunnablePassthrough()
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
# Usage
|
|
634
|
+
results = parallel_chain.invoke({"text": "Long article text here..."})
|
|
635
|
+
print(f"Summary: {results['summary']}")
|
|
636
|
+
print(f"Sentiment: {results['sentiment']}")
|
|
637
|
+
print(f"Topics: {results['topics']}")
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
### 10. Conditional Routing with RunnableBranch
|
|
641
|
+
|
|
642
|
+
```python
|
|
643
|
+
from langchain_core.runnables import RunnableBranch
|
|
644
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
645
|
+
from langchain_anthropic import ChatAnthropic
|
|
646
|
+
|
|
647
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
648
|
+
|
|
649
|
+
# Define specialized chains
|
|
650
|
+
technical_chain = (
|
|
651
|
+
ChatPromptTemplate.from_template("Provide a technical explanation: {input}")
|
|
652
|
+
| llm
|
|
653
|
+
| StrOutputParser()
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
simple_chain = (
|
|
657
|
+
ChatPromptTemplate.from_template("Explain in simple terms: {input}")
|
|
658
|
+
| llm
|
|
659
|
+
| StrOutputParser()
|
|
660
|
+
)
|
|
661
|
+
|
|
662
|
+
creative_chain = (
|
|
663
|
+
ChatPromptTemplate.from_template("Provide a creative explanation: {input}")
|
|
664
|
+
| llm
|
|
665
|
+
| StrOutputParser()
|
|
666
|
+
)
|
|
667
|
+
|
|
668
|
+
# Routing logic
|
|
669
|
+
def is_technical(input_dict):
|
|
670
|
+
text = input_dict["input"].lower()
|
|
671
|
+
technical_keywords = ["algorithm", "implementation", "architecture", "technical"]
|
|
672
|
+
return any(keyword in text for keyword in technical_keywords)
|
|
673
|
+
|
|
674
|
+
def is_creative(input_dict):
|
|
675
|
+
text = input_dict["input"].lower()
|
|
676
|
+
creative_keywords = ["story", "creative", "imagine", "metaphor"]
|
|
677
|
+
return any(keyword in text for keyword in creative_keywords)
|
|
678
|
+
|
|
679
|
+
# Create branch
|
|
680
|
+
branch = RunnableBranch(
|
|
681
|
+
(is_technical, technical_chain),
|
|
682
|
+
(is_creative, creative_chain),
|
|
683
|
+
simple_chain # Default
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
# Usage
|
|
687
|
+
result = branch.invoke({"input": "Explain algorithm complexity"}) # Uses technical_chain
|
|
688
|
+
result = branch.invoke({"input": "Tell me a story about AI"}) # Uses creative_chain
|
|
689
|
+
result = branch.invoke({"input": "What is Python?"}) # Uses simple_chain
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
## Production Best Practices
|
|
693
|
+
|
|
694
|
+
### 1. Error Handling with Retries and Fallbacks
|
|
695
|
+
|
|
696
|
+
```python
|
|
697
|
+
from langchain_core.runnables import RunnableRetry
|
|
698
|
+
from tenacity import retry, stop_after_attempt, wait_exponential
|
|
699
|
+
|
|
700
|
+
# Automatic retry with tenacity
|
|
701
|
+
@retry(
|
|
702
|
+
stop=stop_after_attempt(3),
|
|
703
|
+
wait=wait_exponential(multiplier=1, min=2, max=10)
|
|
704
|
+
)
|
|
705
|
+
async def call_llm_with_retry(chain, input_data):
|
|
706
|
+
"""Call LLM with automatic retry"""
|
|
707
|
+
return await chain.ainvoke(input_data)
|
|
708
|
+
|
|
709
|
+
# Fallback chains
|
|
710
|
+
from langchain_core.runnables import RunnableWithFallbacks
|
|
711
|
+
|
|
712
|
+
primary_llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
713
|
+
fallback_llm = ChatAnthropic(model="claude-3-haiku-20240307")
|
|
714
|
+
|
|
715
|
+
chain_with_fallback = (prompt | primary_llm).with_fallbacks(
|
|
716
|
+
[prompt | fallback_llm]
|
|
717
|
+
)
|
|
718
|
+
|
|
719
|
+
# Circuit breaker pattern
|
|
720
|
+
from datetime import datetime, timedelta
|
|
721
|
+
|
|
722
|
+
class CircuitBreaker:
|
|
723
|
+
def __init__(self, failure_threshold=5, timeout=60):
|
|
724
|
+
self.failure_threshold = failure_threshold
|
|
725
|
+
self.timeout = timeout
|
|
726
|
+
self.failures = 0
|
|
727
|
+
self.last_failure_time = None
|
|
728
|
+
self.state = "closed" # closed, open, half_open
|
|
729
|
+
|
|
730
|
+
def call(self, func, *args, **kwargs):
|
|
731
|
+
if self.state == "open":
|
|
732
|
+
if datetime.now() - self.last_failure_time > timedelta(seconds=self.timeout):
|
|
733
|
+
self.state = "half_open"
|
|
734
|
+
else:
|
|
735
|
+
raise Exception("Circuit breaker is open")
|
|
736
|
+
|
|
737
|
+
try:
|
|
738
|
+
result = func(*args, **kwargs)
|
|
739
|
+
if self.state == "half_open":
|
|
740
|
+
self.state = "closed"
|
|
741
|
+
self.failures = 0
|
|
742
|
+
return result
|
|
743
|
+
except Exception as e:
|
|
744
|
+
self.failures += 1
|
|
745
|
+
self.last_failure_time = datetime.now()
|
|
746
|
+
|
|
747
|
+
if self.failures >= self.failure_threshold:
|
|
748
|
+
self.state = "open"
|
|
749
|
+
|
|
750
|
+
raise e
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
### 2. Caching Strategies
|
|
754
|
+
|
|
755
|
+
```python
|
|
756
|
+
from langchain.cache import InMemoryCache, RedisCache, SQLiteCache
|
|
757
|
+
from langchain.globals import set_llm_cache
|
|
758
|
+
import redis
|
|
759
|
+
|
|
760
|
+
# In-memory cache (development)
|
|
761
|
+
set_llm_cache(InMemoryCache())
|
|
762
|
+
|
|
763
|
+
# SQLite cache (persistent)
|
|
764
|
+
set_llm_cache(SQLiteCache(database_path="langchain.db"))
|
|
765
|
+
|
|
766
|
+
# Redis cache (production)
|
|
767
|
+
set_llm_cache(RedisCache(redis_=redis.Redis(host="localhost", port=6379)))
|
|
768
|
+
|
|
769
|
+
# Semantic cache (cache similar queries)
|
|
770
|
+
from langchain.cache import RedisSemanticCache
|
|
771
|
+
from langchain_openai import OpenAIEmbeddings
|
|
772
|
+
|
|
773
|
+
set_llm_cache(
|
|
774
|
+
RedisSemanticCache(
|
|
775
|
+
redis_url="redis://localhost:6379",
|
|
776
|
+
embedding=OpenAIEmbedings(),
|
|
777
|
+
score_threshold=0.2 # Similarity threshold
|
|
778
|
+
)
|
|
779
|
+
)
|
|
780
|
+
|
|
781
|
+
# Custom cache key
|
|
782
|
+
def custom_cache_key(prompt: str, llm_string: str) -> str:
|
|
783
|
+
"""Generate custom cache key"""
|
|
784
|
+
import hashlib
|
|
785
|
+
return hashlib.md5(f"{prompt}{llm_string}".encode()).hexdigest()
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
### 3. Rate Limiting
|
|
789
|
+
|
|
790
|
+
```python
|
|
791
|
+
import asyncio
|
|
792
|
+
from datetime import datetime, timedelta
|
|
793
|
+
from collections import deque
|
|
794
|
+
|
|
795
|
+
class RateLimiter:
|
|
796
|
+
"""Token bucket rate limiter"""
|
|
797
|
+
|
|
798
|
+
def __init__(self, requests_per_minute: int):
|
|
799
|
+
self.requests_per_minute = requests_per_minute
|
|
800
|
+
self.requests = deque()
|
|
801
|
+
|
|
802
|
+
async def acquire(self):
|
|
803
|
+
"""Wait until a request slot is available"""
|
|
804
|
+
now = datetime.now()
|
|
805
|
+
|
|
806
|
+
# Remove requests older than 1 minute
|
|
807
|
+
while self.requests and now - self.requests[0] > timedelta(minutes=1):
|
|
808
|
+
self.requests.popleft()
|
|
809
|
+
|
|
810
|
+
# Wait if rate limit exceeded
|
|
811
|
+
if len(self.requests) >= self.requests_per_minute:
|
|
812
|
+
sleep_time = 60 - (now - self.requests[0]).total_seconds()
|
|
813
|
+
await asyncio.sleep(max(0, sleep_time))
|
|
814
|
+
return await self.acquire()
|
|
815
|
+
|
|
816
|
+
self.requests.append(now)
|
|
817
|
+
|
|
818
|
+
# Usage
|
|
819
|
+
rate_limiter = RateLimiter(requests_per_minute=60)
|
|
820
|
+
|
|
821
|
+
async def call_with_rate_limit(chain, input_data):
|
|
822
|
+
await rate_limiter.acquire()
|
|
823
|
+
return await chain.ainvoke(input_data)
|
|
824
|
+
|
|
825
|
+
# Per-user rate limiting
|
|
826
|
+
class UserRateLimiter:
|
|
827
|
+
"""Rate limiting per user"""
|
|
828
|
+
|
|
829
|
+
def __init__(self, requests_per_minute: int):
|
|
830
|
+
self.requests_per_minute = requests_per_minute
|
|
831
|
+
self.user_limiters = {}
|
|
832
|
+
|
|
833
|
+
async def acquire(self, user_id: str):
|
|
834
|
+
if user_id not in self.user_limiters:
|
|
835
|
+
self.user_limiters[user_id] = RateLimiter(self.requests_per_minute)
|
|
836
|
+
|
|
837
|
+
await self.user_limiters[user_id].acquire()
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
### 4. Cost Tracking and Budgets
|
|
841
|
+
|
|
842
|
+
```python
|
|
843
|
+
from typing import Dict
|
|
844
|
+
import asyncio
|
|
845
|
+
|
|
846
|
+
class CostBudget:
|
|
847
|
+
"""Enforce cost budgets"""
|
|
848
|
+
|
|
849
|
+
def __init__(self, daily_budget: float):
|
|
850
|
+
self.daily_budget = daily_budget
|
|
851
|
+
self.daily_cost = 0.0
|
|
852
|
+
self.last_reset = datetime.now().date()
|
|
853
|
+
self.lock = asyncio.Lock()
|
|
854
|
+
|
|
855
|
+
async def check_and_track(self, estimated_cost: float) -> bool:
|
|
856
|
+
"""Check if request fits budget and track it"""
|
|
857
|
+
async with self.lock:
|
|
858
|
+
# Reset daily cost if new day
|
|
859
|
+
today = datetime.now().date()
|
|
860
|
+
if today > self.last_reset:
|
|
861
|
+
self.daily_cost = 0.0
|
|
862
|
+
self.last_reset = today
|
|
863
|
+
|
|
864
|
+
# Check budget
|
|
865
|
+
if self.daily_cost + estimated_cost > self.daily_budget:
|
|
866
|
+
return False
|
|
867
|
+
|
|
868
|
+
self.daily_cost += estimated_cost
|
|
869
|
+
return True
|
|
870
|
+
|
|
871
|
+
def get_remaining_budget(self) -> float:
|
|
872
|
+
"""Get remaining budget for today"""
|
|
873
|
+
return max(0, self.daily_budget - self.daily_cost)
|
|
874
|
+
|
|
875
|
+
# Token estimation
|
|
876
|
+
def estimate_tokens(text: str) -> int:
|
|
877
|
+
"""Rough token estimation (4 chars per token)"""
|
|
878
|
+
return len(text) // 4
|
|
879
|
+
|
|
880
|
+
def estimate_cost(input_text: str, model: str = "claude-3-5-sonnet-20241022") -> float:
|
|
881
|
+
"""Estimate request cost"""
|
|
882
|
+
pricing = {
|
|
883
|
+
"claude-3-5-sonnet-20241022": {"input": 3.00, "output": 15.00},
|
|
884
|
+
"claude-3-haiku-20240307": {"input": 0.25, "output": 1.25}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
input_tokens = estimate_tokens(input_text)
|
|
888
|
+
# Assume 500 output tokens
|
|
889
|
+
output_tokens = 500
|
|
890
|
+
|
|
891
|
+
model_pricing = pricing[model]
|
|
892
|
+
cost = (
|
|
893
|
+
(input_tokens / 1_000_000) * model_pricing["input"] +
|
|
894
|
+
(output_tokens / 1_000_000) * model_pricing["output"]
|
|
895
|
+
)
|
|
896
|
+
|
|
897
|
+
return cost
|
|
898
|
+
|
|
899
|
+
# Usage
|
|
900
|
+
budget = CostBudget(daily_budget=10.00) # $10 per day
|
|
901
|
+
|
|
902
|
+
async def call_with_budget(chain, input_data, model):
|
|
903
|
+
estimated_cost = estimate_cost(input_data["input"], model)
|
|
904
|
+
|
|
905
|
+
if not await budget.check_and_track(estimated_cost):
|
|
906
|
+
raise Exception(f"Budget exceeded. Remaining: ${budget.get_remaining_budget():.2f}")
|
|
907
|
+
|
|
908
|
+
return await chain.ainvoke(input_data)
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
### 5. Monitoring and Observability
|
|
912
|
+
|
|
913
|
+
```python
|
|
914
|
+
import logging
|
|
915
|
+
from datetime import datetime
|
|
916
|
+
import json
|
|
917
|
+
|
|
918
|
+
class LangChainMonitor:
|
|
919
|
+
"""Comprehensive monitoring for LangChain applications"""
|
|
920
|
+
|
|
921
|
+
def __init__(self, log_file: str = "langchain_monitor.log"):
|
|
922
|
+
self.logger = logging.getLogger("langchain_monitor")
|
|
923
|
+
self.logger.setLevel(logging.INFO)
|
|
924
|
+
|
|
925
|
+
handler = logging.FileHandler(log_file)
|
|
926
|
+
handler.setFormatter(logging.Formatter(
|
|
927
|
+
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
928
|
+
))
|
|
929
|
+
self.logger.addHandler(handler)
|
|
930
|
+
|
|
931
|
+
self.metrics = {
|
|
932
|
+
"total_requests": 0,
|
|
933
|
+
"successful_requests": 0,
|
|
934
|
+
"failed_requests": 0,
|
|
935
|
+
"total_tokens": 0,
|
|
936
|
+
"total_cost": 0.0,
|
|
937
|
+
"avg_latency": 0.0
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
def log_request(self, input_data: dict, output: str, latency: float,
|
|
941
|
+
tokens: int, cost: float, error: str = None):
|
|
942
|
+
"""Log request details"""
|
|
943
|
+
self.metrics["total_requests"] += 1
|
|
944
|
+
|
|
945
|
+
if error:
|
|
946
|
+
self.metrics["failed_requests"] += 1
|
|
947
|
+
self.logger.error(f"Request failed: {error}")
|
|
948
|
+
else:
|
|
949
|
+
self.metrics["successful_requests"] += 1
|
|
950
|
+
self.metrics["total_tokens"] += tokens
|
|
951
|
+
self.metrics["total_cost"] += cost
|
|
952
|
+
|
|
953
|
+
# Update average latency
|
|
954
|
+
n = self.metrics["successful_requests"]
|
|
955
|
+
self.metrics["avg_latency"] = (
|
|
956
|
+
(self.metrics["avg_latency"] * (n - 1) + latency) / n
|
|
957
|
+
)
|
|
958
|
+
|
|
959
|
+
log_entry = {
|
|
960
|
+
"timestamp": datetime.now().isoformat(),
|
|
961
|
+
"input": input_data,
|
|
962
|
+
"output": output[:100] if output else None, # Truncate
|
|
963
|
+
"latency": latency,
|
|
964
|
+
"tokens": tokens,
|
|
965
|
+
"cost": cost,
|
|
966
|
+
"error": error
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
self.logger.info(json.dumps(log_entry))
|
|
970
|
+
|
|
971
|
+
def get_metrics(self) -> dict:
|
|
972
|
+
"""Get current metrics"""
|
|
973
|
+
return self.metrics.copy()
|
|
974
|
+
|
|
975
|
+
# Usage
|
|
976
|
+
monitor = LangChainMonitor()
|
|
977
|
+
|
|
978
|
+
async def monitored_chain_call(chain, input_data):
|
|
979
|
+
"""Call chain with monitoring"""
|
|
980
|
+
start_time = datetime.now()
|
|
981
|
+
error = None
|
|
982
|
+
output = None
|
|
983
|
+
tokens = 0
|
|
984
|
+
cost = 0.0
|
|
985
|
+
|
|
986
|
+
try:
|
|
987
|
+
output = await chain.ainvoke(input_data)
|
|
988
|
+
# Extract metrics from response if available
|
|
989
|
+
tokens = 1000 # Get from callback
|
|
990
|
+
cost = estimate_cost(str(input_data), "claude-3-5-sonnet-20241022")
|
|
991
|
+
except Exception as e:
|
|
992
|
+
error = str(e)
|
|
993
|
+
raise
|
|
994
|
+
finally:
|
|
995
|
+
latency = (datetime.now() - start_time).total_seconds()
|
|
996
|
+
monitor.log_request(input_data, output, latency, tokens, cost, error)
|
|
997
|
+
|
|
998
|
+
return output
|
|
999
|
+
```
|
|
1000
|
+
|
|
1001
|
+
## Model Selection Guide
|
|
1002
|
+
|
|
1003
|
+
### Claude 3.5 Sonnet (Recommended for Most Use Cases)
|
|
1004
|
+
**Use with ChatAnthropic:**
|
|
1005
|
+
```python
|
|
1006
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022", temperature=0)
|
|
1007
|
+
```
|
|
1008
|
+
- Best performance/cost ratio
|
|
1009
|
+
- Excellent for RAG and agents
|
|
1010
|
+
- Strong reasoning and code generation
|
|
1011
|
+
- 200K context window
|
|
1012
|
+
|
|
1013
|
+
### Claude 3 Haiku (Cost-Optimized)
|
|
1014
|
+
**Use for high-volume operations:**
|
|
1015
|
+
```python
|
|
1016
|
+
llm = ChatAnthropic(model="claude-3-haiku-20240307", temperature=0)
|
|
1017
|
+
```
|
|
1018
|
+
- Fastest and cheapest
|
|
1019
|
+
- Perfect for summarization, classification
|
|
1020
|
+
- Use for memory summarization
|
|
1021
|
+
- Good for context compression
|
|
1022
|
+
|
|
1023
|
+
### OpenAI GPT-4 Turbo
|
|
1024
|
+
**Use with ChatOpenAI:**
|
|
1025
|
+
```python
|
|
1026
|
+
from langchain_openai import ChatOpenAI
|
|
1027
|
+
llm = ChatOpenAI(model="gpt-4-turbo-preview", temperature=0)
|
|
1028
|
+
```
|
|
1029
|
+
- Strong function calling
|
|
1030
|
+
- Good for structured output
|
|
1031
|
+
- Vision capabilities
|
|
1032
|
+
|
|
1033
|
+
### Local Models (Ollama)
|
|
1034
|
+
**Use for privacy/cost:**
|
|
1035
|
+
```python
|
|
1036
|
+
from langchain_community.llms import Ollama
|
|
1037
|
+
llm = Ollama(model="llama2")
|
|
1038
|
+
```
|
|
1039
|
+
- No API costs
|
|
1040
|
+
- Full data privacy
|
|
1041
|
+
- Lower latency for local deployment
|
|
1042
|
+
|
|
1043
|
+
## Common Pitfalls
|
|
1044
|
+
|
|
1045
|
+
### ❌ Don't
|
|
1046
|
+
- Use legacy `LLMChain` (deprecated - use LCEL instead)
|
|
1047
|
+
- Ignore async patterns in production
|
|
1048
|
+
- Skip error handling and retries
|
|
1049
|
+
- Hardcode API keys
|
|
1050
|
+
- Use synchronous vector store operations
|
|
1051
|
+
- Ignore token counting and costs
|
|
1052
|
+
- Cache user-specific data globally
|
|
1053
|
+
- Use blocking operations in async code
|
|
1054
|
+
- Skip input validation on tools
|
|
1055
|
+
- Forget to close database connections
|
|
1056
|
+
|
|
1057
|
+
### ✅ Do
|
|
1058
|
+
- Use LCEL with pipe operator (|) for chains
|
|
1059
|
+
- Implement async/await for production
|
|
1060
|
+
- Add retry logic with exponential backoff
|
|
1061
|
+
- Use environment variables for credentials
|
|
1062
|
+
- Use async vector store operations
|
|
1063
|
+
- Track costs with callbacks
|
|
1064
|
+
- Implement per-user caching
|
|
1065
|
+
- Use `asyncio.gather()` for parallel operations
|
|
1066
|
+
- Validate and sanitize tool inputs
|
|
1067
|
+
- Use context managers for resources
|
|
1068
|
+
- Implement proper error handling
|
|
1069
|
+
- Add comprehensive logging
|
|
1070
|
+
- Monitor performance metrics
|
|
1071
|
+
|
|
1072
|
+
## Testing Strategies
|
|
1073
|
+
|
|
1074
|
+
### Unit Tests
|
|
1075
|
+
|
|
1076
|
+
```python
|
|
1077
|
+
import pytest
|
|
1078
|
+
from unittest.mock import Mock, AsyncMock, patch
|
|
1079
|
+
|
|
1080
|
+
@pytest.mark.asyncio
|
|
1081
|
+
async def test_rag_chain():
|
|
1082
|
+
"""Test RAG chain with mocked retriever"""
|
|
1083
|
+
# Mock retriever
|
|
1084
|
+
mock_retriever = Mock()
|
|
1085
|
+
mock_retriever.get_relevant_documents.return_value = [
|
|
1086
|
+
Mock(page_content="LangChain is a framework")
|
|
1087
|
+
]
|
|
1088
|
+
|
|
1089
|
+
# Mock LLM
|
|
1090
|
+
mock_llm = AsyncMock()
|
|
1091
|
+
mock_llm.ainvoke.return_value = "LangChain is a framework for building AI apps"
|
|
1092
|
+
|
|
1093
|
+
# Test chain
|
|
1094
|
+
with patch('your_module.retriever', mock_retriever), \
|
|
1095
|
+
patch('your_module.llm', mock_llm):
|
|
1096
|
+
result = await rag_chain.ainvoke("What is LangChain?")
|
|
1097
|
+
assert "framework" in result.lower()
|
|
1098
|
+
|
|
1099
|
+
@pytest.mark.asyncio
|
|
1100
|
+
async def test_agent_with_tools():
|
|
1101
|
+
"""Test agent tool execution"""
|
|
1102
|
+
mock_tool = Mock()
|
|
1103
|
+
mock_tool.name = "search"
|
|
1104
|
+
mock_tool.description = "Search for information"
|
|
1105
|
+
mock_tool.run.return_value = "Search results"
|
|
1106
|
+
|
|
1107
|
+
# Test agent
|
|
1108
|
+
agent = create_agent([mock_tool])
|
|
1109
|
+
result = await agent.ainvoke("Search for Python")
|
|
1110
|
+
|
|
1111
|
+
mock_tool.run.assert_called_once()
|
|
1112
|
+
```
|
|
1113
|
+
|
|
1114
|
+
### Integration Tests
|
|
1115
|
+
|
|
1116
|
+
```python
|
|
1117
|
+
import pytest
|
|
1118
|
+
import os
|
|
1119
|
+
|
|
1120
|
+
@pytest.mark.skipif(
|
|
1121
|
+
not os.environ.get("ANTHROPIC_API_KEY"),
|
|
1122
|
+
reason="ANTHROPIC_API_KEY not set"
|
|
1123
|
+
)
|
|
1124
|
+
@pytest.mark.asyncio
|
|
1125
|
+
async def test_real_chain():
|
|
1126
|
+
"""Integration test with real API"""
|
|
1127
|
+
from langchain_anthropic import ChatAnthropic
|
|
1128
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
1129
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
1130
|
+
|
|
1131
|
+
llm = ChatAnthropic(model="claude-3-haiku-20240307") # Use cheap model
|
|
1132
|
+
prompt = ChatPromptTemplate.from_template("Say 'test passed'")
|
|
1133
|
+
chain = prompt | llm | StrOutputParser()
|
|
1134
|
+
|
|
1135
|
+
result = await chain.ainvoke({})
|
|
1136
|
+
assert "test passed" in result.lower()
|
|
1137
|
+
|
|
1138
|
+
@pytest.mark.integration
|
|
1139
|
+
@pytest.mark.asyncio
|
|
1140
|
+
async def test_vector_store_integration():
|
|
1141
|
+
"""Test vector store operations"""
|
|
1142
|
+
from langchain_community.vectorstores import Chroma
|
|
1143
|
+
from langchain_openai import OpenAIEmbeddings
|
|
1144
|
+
|
|
1145
|
+
docs = [
|
|
1146
|
+
Document(page_content="LangChain is great"),
|
|
1147
|
+
Document(page_content="Python is awesome")
|
|
1148
|
+
]
|
|
1149
|
+
|
|
1150
|
+
vectorstore = Chroma.from_documents(docs, OpenAIEmbeddings())
|
|
1151
|
+
results = await vectorstore.asimilarity_search("framework")
|
|
1152
|
+
|
|
1153
|
+
assert len(results) > 0
|
|
1154
|
+
assert "LangChain" in results[0].page_content
|
|
1155
|
+
```
|
|
1156
|
+
|
|
1157
|
+
### Load Testing
|
|
1158
|
+
|
|
1159
|
+
```python
|
|
1160
|
+
import asyncio
|
|
1161
|
+
import time
|
|
1162
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
1163
|
+
|
|
1164
|
+
async def load_test(chain, num_requests=100):
|
|
1165
|
+
"""Load test chain performance"""
|
|
1166
|
+
start_time = time.time()
|
|
1167
|
+
|
|
1168
|
+
tasks = [
|
|
1169
|
+
chain.ainvoke({"input": f"Query {i}"})
|
|
1170
|
+
for i in range(num_requests)
|
|
1171
|
+
]
|
|
1172
|
+
|
|
1173
|
+
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
1174
|
+
|
|
1175
|
+
end_time = time.time()
|
|
1176
|
+
duration = end_time - start_time
|
|
1177
|
+
|
|
1178
|
+
successful = sum(1 for r in results if not isinstance(r, Exception))
|
|
1179
|
+
failed = num_requests - successful
|
|
1180
|
+
|
|
1181
|
+
print(f"Completed {num_requests} requests in {duration:.2f}s")
|
|
1182
|
+
print(f"Success: {successful}, Failed: {failed}")
|
|
1183
|
+
print(f"Requests/sec: {num_requests / duration:.2f}")
|
|
1184
|
+
print(f"Avg latency: {duration / num_requests * 1000:.2f}ms")
|
|
1185
|
+
```
|
|
1186
|
+
|
|
1187
|
+
## ClaudeAutoPM Integration Patterns
|
|
1188
|
+
|
|
1189
|
+
### 1. Documentation RAG for AutoPM
|
|
1190
|
+
|
|
1191
|
+
```python
|
|
1192
|
+
from langchain_community.document_loaders import DirectoryLoader
|
|
1193
|
+
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|
1194
|
+
from langchain_community.vectorstores import Chroma
|
|
1195
|
+
from langchain_openai import OpenAIEmbeddings
|
|
1196
|
+
from langchain_anthropic import ChatAnthropic
|
|
1197
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
1198
|
+
|
|
1199
|
+
# Load AutoPM documentation
|
|
1200
|
+
loader = DirectoryLoader(
|
|
1201
|
+
".claude/",
|
|
1202
|
+
glob="**/*.md",
|
|
1203
|
+
show_progress=True
|
|
1204
|
+
)
|
|
1205
|
+
docs = loader.load()
|
|
1206
|
+
|
|
1207
|
+
# Split documents
|
|
1208
|
+
text_splitter = RecursiveCharacterTextSplitter(
|
|
1209
|
+
chunk_size=1000,
|
|
1210
|
+
chunk_overlap=200
|
|
1211
|
+
)
|
|
1212
|
+
splits = text_splitter.split_documents(docs)
|
|
1213
|
+
|
|
1214
|
+
# Create vector store
|
|
1215
|
+
vectorstore = Chroma.from_documents(
|
|
1216
|
+
documents=splits,
|
|
1217
|
+
embedding=OpenAIEmbeddings(),
|
|
1218
|
+
persist_directory="./.claude/vectordb"
|
|
1219
|
+
)
|
|
1220
|
+
|
|
1221
|
+
# RAG chain for AutoPM queries
|
|
1222
|
+
def create_autopm_rag_chain():
|
|
1223
|
+
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
|
|
1224
|
+
|
|
1225
|
+
prompt = ChatPromptTemplate.from_template("""
|
|
1226
|
+
You are an expert on the ClaudeAutoPM framework. Answer the question based on the context.
|
|
1227
|
+
|
|
1228
|
+
Context:
|
|
1229
|
+
{context}
|
|
1230
|
+
|
|
1231
|
+
Question: {question}
|
|
1232
|
+
|
|
1233
|
+
Answer with specific examples and file paths when relevant.
|
|
1234
|
+
""")
|
|
1235
|
+
|
|
1236
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
1237
|
+
|
|
1238
|
+
return (
|
|
1239
|
+
{"context": retriever | format_docs, "question": RunnablePassthrough()}
|
|
1240
|
+
| prompt
|
|
1241
|
+
| llm
|
|
1242
|
+
| StrOutputParser()
|
|
1243
|
+
)
|
|
1244
|
+
|
|
1245
|
+
autopm_rag = create_autopm_rag_chain()
|
|
1246
|
+
answer = autopm_rag.invoke("How do I create a new agent?")
|
|
1247
|
+
```
|
|
1248
|
+
|
|
1249
|
+
### 2. Multi-Agent PM Workflow
|
|
1250
|
+
|
|
1251
|
+
```python
|
|
1252
|
+
from langchain.agents import AgentExecutor, create_openai_functions_agent
|
|
1253
|
+
from langchain_core.tools import tool
|
|
1254
|
+
from langchain_anthropic import ChatAnthropic
|
|
1255
|
+
|
|
1256
|
+
# Define PM tools
|
|
1257
|
+
@tool
|
|
1258
|
+
def create_epic(title: str, description: str) -> str:
|
|
1259
|
+
"""Create a new epic in the project management system."""
|
|
1260
|
+
# Implement epic creation logic
|
|
1261
|
+
return f"Created epic: {title}"
|
|
1262
|
+
|
|
1263
|
+
@tool
|
|
1264
|
+
def decompose_epic(epic_id: str) -> str:
|
|
1265
|
+
"""Decompose an epic into user stories."""
|
|
1266
|
+
# Implement decomposition logic
|
|
1267
|
+
return f"Decomposed epic {epic_id} into 5 user stories"
|
|
1268
|
+
|
|
1269
|
+
@tool
|
|
1270
|
+
def assign_task(task_id: str, developer: str) -> str:
|
|
1271
|
+
"""Assign a task to a developer."""
|
|
1272
|
+
# Implement assignment logic
|
|
1273
|
+
return f"Assigned task {task_id} to {developer}"
|
|
1274
|
+
|
|
1275
|
+
@tool
|
|
1276
|
+
def get_project_status(project_id: str) -> str:
|
|
1277
|
+
"""Get current project status and metrics."""
|
|
1278
|
+
# Implement status retrieval
|
|
1279
|
+
return "Project is 65% complete, 3 blockers"
|
|
1280
|
+
|
|
1281
|
+
# Create PM agent
|
|
1282
|
+
pm_tools = [create_epic, decompose_epic, assign_task, get_project_status]
|
|
1283
|
+
|
|
1284
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022", temperature=0)
|
|
1285
|
+
|
|
1286
|
+
pm_agent = create_openai_functions_agent(llm, pm_tools, prompt)
|
|
1287
|
+
pm_executor = AgentExecutor(agent=pm_agent, tools=pm_tools, verbose=True)
|
|
1288
|
+
|
|
1289
|
+
# Usage
|
|
1290
|
+
result = pm_executor.invoke({
|
|
1291
|
+
"input": "Create an epic for user authentication feature and decompose it into tasks"
|
|
1292
|
+
})
|
|
1293
|
+
```
|
|
1294
|
+
|
|
1295
|
+
### 3. Code Analysis with LangChain
|
|
1296
|
+
|
|
1297
|
+
```python
|
|
1298
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
1299
|
+
from langchain_anthropic import ChatAnthropic
|
|
1300
|
+
from langchain_core.output_parsers import JsonOutputParser
|
|
1301
|
+
|
|
1302
|
+
# Code analysis chain
|
|
1303
|
+
code_analysis_prompt = ChatPromptTemplate.from_template("""
|
|
1304
|
+
Analyze this code for:
|
|
1305
|
+
1. Potential bugs
|
|
1306
|
+
2. Security vulnerabilities
|
|
1307
|
+
3. Performance issues
|
|
1308
|
+
4. Best practice violations
|
|
1309
|
+
|
|
1310
|
+
Code:
|
|
1311
|
+
{code}
|
|
1312
|
+
|
|
1313
|
+
Provide analysis as JSON with keys: bugs, security, performance, best_practices
|
|
1314
|
+
""")
|
|
1315
|
+
|
|
1316
|
+
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
|
|
1317
|
+
|
|
1318
|
+
code_analysis_chain = (
|
|
1319
|
+
code_analysis_prompt
|
|
1320
|
+
| llm
|
|
1321
|
+
| JsonOutputParser()
|
|
1322
|
+
)
|
|
1323
|
+
|
|
1324
|
+
# Usage
|
|
1325
|
+
code = """
|
|
1326
|
+
def process_user_input(user_input):
|
|
1327
|
+
exec(user_input) # Security issue!
|
|
1328
|
+
return True
|
|
1329
|
+
"""
|
|
1330
|
+
|
|
1331
|
+
analysis = code_analysis_chain.invoke({"code": code})
|
|
1332
|
+
print(f"Security issues: {analysis['security']}")
|
|
1333
|
+
```
|
|
1334
|
+
|
|
1335
|
+
## Resources
|
|
1336
|
+
|
|
1337
|
+
### Official Documentation
|
|
1338
|
+
- LangChain Docs: https://python.langchain.com/docs/
|
|
1339
|
+
- LCEL Guide: https://python.langchain.com/docs/expression_language/
|
|
1340
|
+
- API Reference: https://api.python.langchain.com/
|
|
1341
|
+
- LangGraph: https://langchain-ai.github.io/langgraph/
|
|
1342
|
+
|
|
1343
|
+
### Context7 Libraries (MANDATORY)
|
|
1344
|
+
- `mcp://context7/langchain-ai/langchain` - Core library and LCEL
|
|
1345
|
+
- `mcp://context7/websites/python_langchain` - Official documentation
|
|
1346
|
+
- `mcp://context7/langchain-ai/langgraph` - Stateful workflows
|
|
1347
|
+
- `mcp://context7/langchain-ai/langchain-core` - Core abstractions
|
|
1348
|
+
- `mcp://context7/langchain-ai/langchain-community` - Community integrations
|
|
1349
|
+
|
|
1350
|
+
### GitHub Repositories
|
|
1351
|
+
- LangChain: https://github.com/langchain-ai/langchain
|
|
1352
|
+
- LangGraph: https://github.com/langchain-ai/langgraph
|
|
1353
|
+
- LangChain Templates: https://github.com/langchain-ai/langchain/tree/master/templates
|
|
1354
|
+
|
|
1355
|
+
## When to Use This Agent
|
|
1356
|
+
|
|
1357
|
+
Invoke this agent for:
|
|
1358
|
+
- Building LCEL chains and pipelines
|
|
1359
|
+
- Implementing RAG (Retrieval-Augmented Generation)
|
|
1360
|
+
- Creating agent systems with tools
|
|
1361
|
+
- Designing memory systems
|
|
1362
|
+
- Vector store integration
|
|
1363
|
+
- Async/streaming implementations
|
|
1364
|
+
- Production optimization patterns
|
|
1365
|
+
- Cost tracking and monitoring
|
|
1366
|
+
- Error handling strategies
|
|
1367
|
+
- Testing LangChain applications
|
|
1368
|
+
|
|
1369
|
+
## When to Use LangGraph Instead
|
|
1370
|
+
|
|
1371
|
+
Use `@langgraph-workflow-expert` for:
|
|
1372
|
+
- Complex stateful workflows with branching
|
|
1373
|
+
- Multi-agent collaboration patterns
|
|
1374
|
+
- Human-in-the-loop workflows
|
|
1375
|
+
- State persistence and checkpointing
|
|
1376
|
+
- Conditional routing with complex logic
|
|
1377
|
+
- Graph-based orchestration
|
|
1378
|
+
|
|
1379
|
+
## Agent Capabilities
|
|
1380
|
+
|
|
1381
|
+
**This agent can:**
|
|
1382
|
+
- Generate production-ready LangChain code with LCEL
|
|
1383
|
+
- Design optimal RAG architectures
|
|
1384
|
+
- Implement agent systems with custom tools
|
|
1385
|
+
- Create memory-enabled conversation systems
|
|
1386
|
+
- Build async batch processing pipelines
|
|
1387
|
+
- Set up comprehensive monitoring
|
|
1388
|
+
- Implement cost optimization strategies
|
|
1389
|
+
- Design error handling and retry logic
|
|
1390
|
+
- Create structured output parsers
|
|
1391
|
+
- Build multi-step chain compositions
|
|
1392
|
+
|
|
1393
|
+
**This agent will:**
|
|
1394
|
+
- Always query Context7 for latest LangChain patterns
|
|
1395
|
+
- Use LCEL over legacy Chain API
|
|
1396
|
+
- Follow 2024-2025 best practices
|
|
1397
|
+
- Implement proper error handling
|
|
1398
|
+
- Consider cost optimization
|
|
1399
|
+
- Use async patterns for production
|
|
1400
|
+
- Include monitoring and logging
|
|
1401
|
+
- Validate inputs and outputs
|
|
1402
|
+
- Handle rate limiting gracefully
|
|
1403
|
+
- Write comprehensive tests
|
|
1404
|
+
|
|
1405
|
+
## Self-Verification Protocol
|
|
1406
|
+
|
|
1407
|
+
Before delivering any solution, verify:
|
|
1408
|
+
- [ ] Documentation from Context7 has been consulted
|
|
1409
|
+
- [ ] Using LCEL (not legacy LLMChain)
|
|
1410
|
+
- [ ] Async patterns implemented for production
|
|
1411
|
+
- [ ] Error handling with retries included
|
|
1412
|
+
- [ ] Cost tracking implemented
|
|
1413
|
+
- [ ] Rate limiting considered
|
|
1414
|
+
- [ ] Monitoring and logging added
|
|
1415
|
+
- [ ] Tests written and passing
|
|
1416
|
+
- [ ] Security considerations addressed
|
|
1417
|
+
- [ ] No resource leaks (connections, files)
|
|
1418
|
+
- [ ] Input validation on tools
|
|
1419
|
+
- [ ] Proper memory management
|
|
1420
|
+
|
|
1421
|
+
---
|
|
1422
|
+
|
|
1423
|
+
**Agent Version:** 1.0.0
|
|
1424
|
+
**Last Updated:** 2025-10-16
|
|
1425
|
+
**Specialization:** LangChain Framework & LCEL
|
|
1426
|
+
**Context7 Required:** Yes
|
|
1427
|
+
**Compatible With:** @langgraph-workflow-expert, @anthropic-claude-expert, @openai-python-expert
|