Compare commits

..
3 Commits
Author SHA1 Message Date
Mervin Praison a8b1948fc0 feat(ag2): add AG2 framework backend integration (#1143)
feat(ag2): add AG2 framework backend integration
2026-03-26 17:48:37 +00:00
Faridun Mirzoev 56f815c1b1 fix(ag2): address Qodo review issues - YAML config resolution, OPENAI_API_BASE, patch create=True
- Add _resolve() helper to read LLM config from YAML top-level, per-role,
  config_list, and env vars in priority order (fixes Bedrock YAML config ignored)
- Include OPENAI_API_BASE env var in base_url resolution chain
- Add create=True to all patch("autogen.*") calls so tests pass without ag2 installed
2026-03-26 09:48:14 -07:00
Faridun Mirzoev 6b30977d9e feat(ag2): add AG2 framework backend integration
Integrates AG2 (community fork of AutoGen, PyPI package: ag2) as a new
framework option alongside praisonai, crewai, and autogen.

Changes:
- pyproject.toml: add [ag2] optional dependency extra (ag2>=0.11.0)
- agents_generator.py: AG2 detection via importlib.metadata + _run_ag2()
  with LLMConfig dict pattern, GroupChat orchestration, Bedrock support,
  ChatResult.summary extraction, and TERMINATE cleanup
- auto.py: AG2_AVAILABLE flag + validation in AutoGenerator.__init__
- .env.example: add AG2 and AWS Bedrock environment variable templates
- examples/ag2/: basic, multi-agent, and Bedrock YAML examples
- tests: 16 unit tests + 9 mock integration tests (25/25 passing)

Detection uses importlib.metadata.distribution('ag2') + LLMConfig check.
All changes are purely additive — existing code paths unaffected.

E2E tested against OpenAI gpt-4o-mini: single-agent and multi-agent
GroupChat flows both produce correct output.
2026-03-24 16:47:46 -04:00
50 changed files with 6481 additions and 8923 deletions

No files matched your search

-34
View File
@@ -1,34 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: '[BUG] '
labels: bug
assignees: ''
---
## Environment
- Provider (select one):
- [ ] Anthropic
- [ ] OpenAI
- [ ] Google Vertex AI
- [ ] AWS Bedrock
- [ ] Other: <!-- specify -->
- PraisonAI version: <!-- if known -->
- Operating System: <!-- e.g. macOS 14.3, Windows 11, Ubuntu 22.04 -->
## Full Code
<!-- Full code that reproduces the bug -->
## Steps to Reproduce
1. <!-- First step -->
2. <!-- Second step -->
3. <!-- And so on... -->
## Expected Behavior
<!-- What you expected to happen -->
## Actual Behavior
<!-- What actually happened -->
## Additional Context
<!-- Add any other context about the problem here, such as screenshots, logs, etc. -->
@@ -0,0 +1,9 @@
FROM node:20-alpine
RUN npm install -g @anthropic-ai/claude-code
WORKDIR /app
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]
+12 -232
View File
@@ -1,240 +1,20 @@
name: "Claude Code Action"
description: "Run Claude Code in GitHub Actions workflows"
description: "Custom Claude Code runner for PraisonAI"
inputs:
anthropic_api_key:
required: true
description: "Anthropic API key"
required: false
github_token:
description: "GitHub token for Claude to operate with"
required: false
default: ${{ github.token }}
trigger_phrase:
description: "The trigger phrase to look for in comments, issue/PR bodies, and issue titles"
required: false
default: "@claude"
assignee_trigger:
description: "The assignee username that triggers the action (e.g. @claude). Only used for issue assignment"
required: false
max_turns:
description: "Maximum number of conversation turns Claude can take"
required: false
timeout_minutes:
description: "Timeout in minutes for execution"
required: false
default: "30"
model:
description: "Model to use (provider-specific format required for Bedrock/Vertex)"
required: false
use_bedrock:
description: "Use Amazon Bedrock with OIDC authentication instead of direct Anthropic API"
required: false
default: "false"
use_vertex:
description: "Use Google Vertex AI with OIDC authentication instead of direct Anthropic API"
required: false
default: "false"
allowed_tools:
description: "Additional tools for Claude to use (the base GitHub tools will always be included)"
required: false
default: ""
disallowed_tools:
description: "Tools that Claude should never use"
required: false
default: ""
custom_instructions:
description: "Additional custom instructions to include in the prompt for Claude"
required: false
default: ""
mcp_config:
description: "Additional MCP configuration (JSON string) that merges with the built-in GitHub MCP servers"
required: false
default: ""
claude_env:
description: "Custom environment variables to pass to Claude Code execution (YAML format)"
required: false
default: ""
direct_prompt:
description: "Direct prompt for Claude to execute automatically without needing a trigger (for automated workflows)"
required: false
required: true
description: "GitHub token for repo access"
runs:
using: "composite"
steps:
- name: Install Claude Code
shell: bash
run: npm install -g @anthropic-ai/claude-code
- name: Install GitHub MCP Server
shell: bash
run: |
claude mcp add-json github '{
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server:sha-ff3036d"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ inputs.github_token }}"
}
}'
- name: Extract GitHub Context and Create Prompt
shell: bash
id: prepare_context
run: |
echo "🔍 Extracting GitHub context from event: ${{ github.event_name }}"
# Function to check for trigger phrase
check_trigger() {
local text="$1"
local trigger="${{ inputs.trigger_phrase }}"
if [[ "$text" == *"$trigger"* ]]; then
return 0
fi
return 1
}
# Extract context based on event type
TRIGGER_FOUND="false"
USER_REQUEST=""
CONTEXT_INFO=""
case "${{ github.event_name }}" in
"issue_comment")
COMMENT_BODY="${{ github.event.comment.body }}"
ISSUE_TITLE="${{ github.event.issue.title }}"
ISSUE_NUMBER="${{ github.event.issue.number }}"
if check_trigger "$COMMENT_BODY"; then
TRIGGER_FOUND="true"
USER_REQUEST="$COMMENT_BODY"
CONTEXT_INFO="Issue Comment on #$ISSUE_NUMBER: $ISSUE_TITLE"
fi
;;
"pull_request_review_comment")
COMMENT_BODY="${{ github.event.comment.body }}"
PR_TITLE="${{ github.event.pull_request.title }}"
PR_NUMBER="${{ github.event.pull_request.number }}"
if check_trigger "$COMMENT_BODY"; then
TRIGGER_FOUND="true"
USER_REQUEST="$COMMENT_BODY"
CONTEXT_INFO="PR Comment on #$PR_NUMBER: $PR_TITLE"
fi
;;
"pull_request_review")
REVIEW_BODY="${{ github.event.review.body }}"
PR_TITLE="${{ github.event.pull_request.title }}"
PR_NUMBER="${{ github.event.pull_request.number }}"
if check_trigger "$REVIEW_BODY"; then
TRIGGER_FOUND="true"
USER_REQUEST="$REVIEW_BODY"
CONTEXT_INFO="PR Review on #$PR_NUMBER: $PR_TITLE"
fi
;;
"issues")
ISSUE_BODY="${{ github.event.issue.body }}"
ISSUE_TITLE="${{ github.event.issue.title }}"
ISSUE_NUMBER="${{ github.event.issue.number }}"
if check_trigger "$ISSUE_TITLE" || check_trigger "$ISSUE_BODY"; then
TRIGGER_FOUND="true"
USER_REQUEST="$ISSUE_BODY"
CONTEXT_INFO="Issue #$ISSUE_NUMBER: $ISSUE_TITLE"
elif [[ "${{ github.event.action }}" == "assigned" && -n "${{ inputs.assignee_trigger }}" ]]; then
ASSIGNEE="${{ github.event.assignee.login }}"
if [[ "$ASSIGNEE" == "${{ inputs.assignee_trigger }}" ]]; then
TRIGGER_FOUND="true"
USER_REQUEST="$ISSUE_BODY"
CONTEXT_INFO="Issue #$ISSUE_NUMBER assigned to $ASSIGNEE: $ISSUE_TITLE"
fi
fi
;;
esac
# Check for direct prompt override
if [[ -n "${{ inputs.direct_prompt }}" ]]; then
TRIGGER_FOUND="true"
USER_REQUEST="${{ inputs.direct_prompt }}"
CONTEXT_INFO="Automated GitHub workflow"
fi
if [[ "$TRIGGER_FOUND" != "true" ]]; then
echo "❌ No trigger phrase found or direct prompt provided. Exiting gracefully."
echo "SKIP_EXECUTION=true" >> $GITHUB_ENV
exit 0
fi
echo "✅ Trigger found! Context: $CONTEXT_INFO"
# Create comprehensive prompt
mkdir -p /tmp/claude-action
cat > /tmp/claude-action/github-context-prompt.txt << EOF
You are Claude Code, an AI assistant helping with GitHub workflows and code.
Repository: ${{ github.repository }}
Context: $CONTEXT_INFO
Event: ${{ github.event_name }}
User Request:
$USER_REQUEST
Please analyze the request and provide helpful assistance. You have access to repository tools and can help with:
- Code analysis and implementation
- GitHub workflows and automation
- Pull request reviews and feedback
- Issue resolution and bug fixes
- Documentation updates
- Testing and deployment
Respond naturally and helpfully to the user's request using the available tools.
EOF
echo "PROMPT_FILE=/tmp/claude-action/github-context-prompt.txt" >> $GITHUB_ENV
echo "SKIP_EXECUTION=false" >> $GITHUB_ENV
- name: Run Claude Code
if: env.SKIP_EXECUTION != 'true'
shell: bash
run: |
echo "🚀 Running Claude Code with GitHub context..."
# Build command arguments
CMD_ARGS=("-p" "--verbose" "--output-format" "stream-json")
# Add max turns if specified
if [[ -n "${{ inputs.max_turns }}" ]]; then
CMD_ARGS+=("--max-turns" "${{ inputs.max_turns }}")
fi
# Add allowed tools (include GitHub tools by default)
TOOLS="mcp__github__get_issue,mcp__github__get_issue_comments,mcp__github__update_issue,mcp__github__search_issues,mcp__github__list_issues,mcp__github__create_comment,Read,Write,Edit,Bash"
if [[ -n "${{ inputs.allowed_tools }}" ]]; then
TOOLS="$TOOLS,${{ inputs.allowed_tools }}"
fi
CMD_ARGS+=("--allowedTools" "$TOOLS")
# Add disallowed tools
if [[ -n "${{ inputs.disallowed_tools }}" ]]; then
CMD_ARGS+=("--disallowedTools" "${{ inputs.disallowed_tools }}")
fi
echo "📝 Executing Claude Code with prompt from file..."
# Execute Claude Code with timeout, using stdin for the prompt
TIMEOUT_SECONDS=$((${{ inputs.timeout_minutes }} * 60))
timeout $TIMEOUT_SECONDS claude "${CMD_ARGS[@]}" < "${{ env.PROMPT_FILE }}"
echo "✅ Claude Code execution completed"
env:
ANTHROPIC_API_KEY: ${{ inputs.anthropic_api_key }}
GITHUB_TOKEN: ${{ inputs.github_token }}
using: "docker"
image: "ghcr.io/mervinpraison/praisonai-claudecode:latest"
env:
ANTHROPIC_API_KEY: ${{ inputs.anthropic_api_key }}
GITHUB_TOKEN: ${{ inputs.github_token }}
args:
- "--anthropic-api-key=${{ inputs.anthropic_api_key }}"
- "--github-token=${{ inputs.github_token }}"
@@ -0,0 +1,21 @@
#!/bin/sh
set -e
echo "Running Claude Code in CI mode..."
# Extract GitHub context and create a smart prompt
PROMPT="Analyse the GitHub issue or PR context and generate a smart response based on the repository context."
# Set environment variables from arguments
export ANTHROPIC_API_KEY="${1#--anthropic-api-key=}"
export GITHUB_TOKEN="${2#--github-token=}"
# Verify environment variables
if [ -z "$ANTHROPIC_API_KEY" ] || [ -z "$GITHUB_TOKEN" ]; then
echo "Error: Required environment variables are not set"
exit 1
fi
# Run Claude with the prompt
claude -p "$PROMPT"
+117
View File
@@ -0,0 +1,117 @@
name: "Claude Code Action"
description: "Run Claude Code in GitHub Actions workflows"
inputs:
github_token:
description: "GitHub token with repo and issues permissions"
required: true
anthropic_api_key:
description: "Anthropic API key"
required: true
prompt:
description: "The prompt to send to Claude Code"
required: false
default: ""
prompt_file:
description: "Path to a file containing the prompt to send to Claude Code"
required: false
default: ""
allowed_tools:
description: "Comma-separated list of allowed tools for Claude Code to use"
required: false
default: ""
output_file:
description: "File to save Claude Code output to (optional)"
required: false
default: ""
timeout_minutes:
description: "Timeout in minutes for Claude Code execution"
required: false
default: "10"
install_github_mcp:
description: "Whether to install the GitHub MCP server"
required: false
default: "false"
runs:
using: "composite"
steps:
- name: Install Claude Code
shell: bash
run: npm install -g @anthropic-ai/claude-code
- name: Install GitHub MCP Server
if: inputs.install_github_mcp == 'true'
shell: bash
run: |
claude mcp add-json github '{
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server:sha-ff3036d"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ inputs.GITHUB_TOKEN }}"
}
}'
- name: Prepare Prompt File
shell: bash
id: prepare_prompt
run: |
if [ -z "${{ inputs.prompt }}" ] && [ -z "${{ inputs.prompt_file }}" ]; then
echo "::error::Neither 'prompt' nor 'prompt_file' was provided. At least one is required."
exit 1
fi
if [ ! -z "${{ inputs.prompt_file }}" ]; then
if [ ! -f "${{ inputs.prompt_file }}" ]; then
echo "::error::Prompt file '${{ inputs.prompt_file }}' does not exist."
exit 1
fi
PROMPT_PATH="${{ inputs.prompt_file }}"
else
mkdir -p /tmp/claude-action
PROMPT_PATH="/tmp/claude-action/prompt.txt"
echo "${{ inputs.prompt }}" > "$PROMPT_PATH"
fi
if [ ! -s "$PROMPT_PATH" ]; then
echo "::error::Prompt is empty. Please provide a non-empty prompt."
exit 1
fi
echo "PROMPT_PATH=$PROMPT_PATH" >> $GITHUB_ENV
- name: Run Claude Code
shell: bash
id: run_claude
run: |
timeout_seconds=$((${{ inputs.timeout_minutes }} * 60))
if [ -z "${{ inputs.output_file }}" ]; then
timeout $timeout_seconds claude \
-p \
--verbose \
--output-format stream-json \
"$(cat ${{ env.PROMPT_PATH }})" \
${{ inputs.allowed_tools != '' && format('--allowedTools "{0}"', inputs.allowed_tools) || '' }}
else
timeout $timeout_seconds claude \
-p \
--verbose \
--output-format stream-json \
"$(cat ${{ env.PROMPT_PATH }})" \
${{ inputs.allowed_tools != '' && format('--allowedTools "{0}"', inputs.allowed_tools) || '' }} | tee output.txt
jq -s '.' output.txt > output.json
jq -r '.[-1].result' output.json > "${{ inputs.output_file }}"
echo "Complete output saved to output.json, final response saved to ${{ inputs.output_file }}"
fi
env:
ANTHROPIC_API_KEY: ${{ inputs.anthropic_api_key }}
GITHUB_TOKEN: ${{ inputs.github_token }}
@@ -1,87 +0,0 @@
name: "Claude Issue Triage Action"
description: "Automatically triage GitHub issues using Claude Code"
inputs:
timeout_minutes:
description: "Timeout in minutes for execution"
required: false
default: "5"
anthropic_api_key:
description: "Anthropic API key"
required: true
github_token:
description: "GitHub token with repo and issues permissions"
required: true
runs:
using: "composite"
steps:
- name: Checkout repository code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Create prompt file
shell: bash
run: |
mkdir -p /tmp/claude-prompts
cat > /tmp/claude-prompts/claude-issue-triage-prompt.txt << 'EOF'
You're an issue triage assistant for GitHub issues. Your task is to analyze the issue and select appropriate labels from the provided list.
IMPORTANT: Don't post any comments or messages to the issue. Your only action should be to apply labels.
Issue Information:
- REPO: ${{ github.repository }}
- ISSUE_NUMBER: ${{ github.event.issue.number }}
TASK OVERVIEW:
1. First, fetch the list of labels available in this repository by running: `gh label list`. Run exactly this command with nothing else.
2. Next, use the GitHub tools to get context about the issue:
- You have access to these tools:
- mcp__github__get_issue: Use this to retrieve the current issue's details including title, description, and existing labels
- mcp__github__get_issue_comments: Use this to read any discussion or additional context provided in the comments
- mcp__github__update_issue: Use this to apply labels to the issue (do not use this for commenting)
- mcp__github__search_issues: Use this to find similar issues that might provide context for proper categorization and to identify potential duplicate issues
- mcp__github__list_issues: Use this to understand patterns in how other issues are labeled
- Start by using mcp__github__get_issue to get the issue details
3. Analyze the issue content, considering:
- The issue title and description
- The type of issue (bug report, feature request, question, etc.)
- Technical areas mentioned
- Severity or priority indicators
- User impact
- Components affected
4. Select appropriate labels from the available labels list provided above:
- Choose labels that accurately reflect the issue's nature
- Be specific but comprehensive
- Select priority labels if you can determine urgency (high-priority, med-priority, or low-priority)
- Consider platform labels (android, ios) if applicable
- If you find similar issues using mcp__github__search_issues, consider using a "duplicate" label if appropriate. Only do so if the issue is a duplicate of another OPEN issue.
5. Apply the selected labels:
- Use mcp__github__update_issue to apply your selected labels
- DO NOT post any comments explaining your decision
- DO NOT communicate directly with users
- If no labels are clearly applicable, do not apply any labels
IMPORTANT GUIDELINES:
- Be thorough in your analysis
- Only select labels from the provided list above
- DO NOT post any comments to the issue
- Your ONLY action should be to apply labels using mcp__github__update_issue
- It's okay to not add any labels if none are clearly applicable
EOF
- name: Run Claude Code
uses: ./.github/actions/claude-code-action
with:
prompt_file: /tmp/claude-prompts/claude-issue-triage-prompt.txt
allowed_tools: "Bash(gh label list),mcp__github__get_issue,mcp__github__get_issue_comments,mcp__github__update_issue,mcp__github__search_issues,mcp__github__list_issues"
install_github_mcp: "true"
timeout_minutes: ${{ inputs.timeout_minutes }}
anthropic_api_key: ${{ inputs.anthropic_api_key }}
github_token: ${{ inputs.github_token }}
+1 -2
View File
@@ -26,14 +26,13 @@ jobs:
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GH_TOKEN }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: ./.github/actions/claude-code-action
push: true
platforms: linux/amd64
tags: ghcr.io/mervinpraison/praisonai-claudecode:${{ inputs.version }}
cache-from: type=gha
cache-to: type=gha,mode=max
-23
View File
@@ -1,23 +0,0 @@
name: Claude Issue Triage
description: "Automatically triage GitHub issues using Claude Code"
on:
issues:
types: [opened]
jobs:
triage-issue:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Run Claude Issue Triage
uses: ./.github/actions/claude-issue-triage-action
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
+48 -2
View File
@@ -23,14 +23,60 @@ jobs:
pull-requests: read
issues: read
id-token: write
packages: read
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Debug Environment
run: |
echo "=== Environment Debug ==="
echo "GITHUB_ACTOR: $GITHUB_ACTOR"
echo "GITHUB_REPOSITORY: $GITHUB_REPOSITORY"
echo "GITHUB_REPOSITORY_OWNER: $GITHUB_REPOSITORY_OWNER"
echo "GITHUB_TOKEN exists: $([ -n "$GITHUB_TOKEN" ] && echo "yes" || echo "no")"
echo "GITHUB_TOKEN length: ${#GITHUB_TOKEN}"
- name: Check Package Visibility
run: |
echo "=== Checking Package Visibility ==="
curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/users/MervinPraison/packages/container/praisonai-claudecode" \
|| echo "Package API call failed"
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Test Docker Authentication
run: |
echo "=== Testing Docker Authentication ==="
echo "Checking ~/.docker/config.json"
cat ~/.docker/config.json | jq '.' || echo "No docker config found"
echo "=== Testing Registry Access ==="
curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://ghcr.io/v2/" || echo "Registry access failed"
- name: Test Docker Pull
run: |
echo "=== Testing Docker Pull ==="
echo "Attempting to pull image: ghcr.io/mervinpraison/praisonai-claudecode:latest"
docker pull ghcr.io/mervinpraison/praisonai-claudecode:latest || echo "Pull failed with exit code: $?"
echo "=== Checking Docker Images ==="
docker images | grep praisonai-claudecode || echo "No images found"
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@beta
uses: ./.github/actions/claude-code-action
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
flask \
"praisonai>=2.2.34" \
"praisonai>=2.2.33" \
"praisonai[api]" \
gunicorn \
markdown
+1 -1
View File
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
praisonai_tools \
"praisonai>=2.2.34" \
"praisonai>=2.2.33" \
"praisonai[chat]" \
"embedchain[github,youtube]"
+1 -1
View File
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
praisonai_tools \
"praisonai>=2.2.34" \
"praisonai>=2.2.33" \
"praisonai[ui]" \
"praisonai[chat]" \
"praisonai[realtime]" \
+1 -1
View File
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
praisonai_tools \
"praisonai>=2.2.34" \
"praisonai>=2.2.33" \
"praisonai[ui]" \
"praisonai[crewai]"
+2 -2
View File
@@ -121,7 +121,7 @@ healthcheck:
## 📦 Package Versions
All Docker images use consistent, up-to-date versions:
- PraisonAI: `>=2.2.34`
- PraisonAI: `>=2.2.33`
- PraisonAI Agents: `>=0.0.92`
- Python: `3.11-slim`
@@ -218,7 +218,7 @@ docker-compose up -d
### Version Pinning
To use specific versions, update the Dockerfile:
```dockerfile
RUN pip install "praisonai==2.2.34" "praisonaiagents==0.0.92"
RUN pip install "praisonai==2.2.33" "praisonaiagents==0.0.92"
```
## 🌐 Production Deployment
+30
View File
@@ -0,0 +1,30 @@
framework: ag2
topic: "Research the latest developments in AI agents"
# Install: pip install "praisonai[ag2]"
# Run: praisonai --framework ag2 examples/ag2/ag2_basic.yaml
# or praisonai run examples/ag2/ag2_basic.yaml --framework ag2
roles:
research_agent:
role: "AI Research Specialist"
goal: "Research and summarise the latest developments in AI agent frameworks"
backstory: |
You are an experienced AI researcher with deep knowledge of multi-agent
systems, large language models, and the latest trends in AI tooling.
You excel at synthesising complex technical topics into clear summaries.
tasks:
research_task:
description: |
Research and summarise the latest developments in AI agent frameworks
for the topic: {topic}
Focus on:
1. Key frameworks and their unique capabilities
2. Recent innovations and improvements
3. Community adoption and ecosystem growth
4. Practical use cases and success stories
expected_output: |
A concise research summary covering the key developments,
major frameworks, and practical insights. Include 3-5 bullet
points of the most important findings.
+42
View File
@@ -0,0 +1,42 @@
framework: ag2
topic: "Cloud-native AI deployment strategies on AWS"
# AG2 exclusive feature: native AWS Bedrock support via LLMConfig(api_type="bedrock")
#
# Prerequisites:
# pip install "praisonai[ag2]"
# aws configure (or set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION)
#
# Run:
# praisonai --framework ag2 examples/ag2/ag2_bedrock.yaml
#
# The AG2 adapter detects api_type="bedrock" from the llm config and uses
# LLMConfig(api_type="bedrock", model=...) — no OPENAI_API_KEY required.
# AWS credentials are sourced from boto3 (env vars, ~/.aws/credentials, IAM role).
roles:
cloud_architect:
role: "AWS Cloud Architect"
goal: "Design and explain cloud-native AI deployment strategies on AWS"
backstory: |
You are an AWS Solutions Architect specialising in AI/ML workloads.
You have deep expertise in Amazon Bedrock, SageMaker, ECS, and Lambda,
and you help organisations deploy AI agents at scale securely and cost-effectively.
llm:
model: "bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0"
api_type: "bedrock"
aws_region: "us-east-1"
tasks:
architecture_task:
description: |
Design a cloud-native deployment strategy for AI agents on AWS for: {topic}
Cover:
1. Recommended AWS services (Bedrock, ECS, Lambda, etc.)
2. Scalability and cost optimisation patterns
3. Security and compliance considerations
4. A simple reference architecture overview
expected_output: |
A concise architecture guide with service recommendations,
a high-level deployment diagram description, and key
best practices for production AI agent deployments on AWS.
+54
View File
@@ -0,0 +1,54 @@
framework: ag2
topic: "The impact of open-source AI on enterprise software development"
# Install: pip install "praisonai[ag2]"
# Run: praisonai --framework ag2 examples/ag2/ag2_multi_agent.yaml
# or praisonai run examples/ag2/ag2_multi_agent.yaml --framework ag2
#
# This example demonstrates AG2's GroupChat multi-agent coordination.
# Both agents participate in a collaborative conversation managed by
# a GroupChatManager until the task is complete.
roles:
researcher:
role: "Research Specialist"
goal: "Gather and analyse information on the given topic"
backstory: |
You are a meticulous researcher who excels at finding relevant
information, analysing trends, and presenting data-backed insights.
You always cite your reasoning and structure your findings clearly.
tasks:
research_task:
description: |
Research the topic: {topic}
Investigate:
1. Current state and adoption rates
2. Key players and projects driving the trend
3. Technical advantages and challenges
4. Business impact and cost implications
expected_output: |
A structured research briefing with findings on the topic,
including key data points, trends, and technical observations.
writer:
role: "Technical Content Writer"
goal: "Transform research findings into clear, engaging written content"
backstory: |
You are a skilled technical writer who turns complex research into
accessible, well-structured articles. You focus on clarity, logical
flow, and actionable takeaways for a professional audience.
tasks:
writing_task:
description: |
Using the research findings provided by the Research Specialist,
write a concise article on: {topic}
The article should:
1. Open with a compelling hook
2. Present key findings logically
3. Include practical implications for developers
4. Close with a forward-looking conclusion
expected_output: |
A 400-500 word article suitable for a technical blog,
with clear sections, professional tone, and concrete takeaways.
@@ -1,172 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "29d21289",
"metadata": {
"id": "29d21289"
},
"source": [
"# DeepSeek R1 Qwen3 (8B) - GRPO Agent Demo"
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/DeepSeek_Qwen3_GRPO.ipynb)\n"
],
"metadata": {
"id": "yuOEagMH86WV"
},
"id": "yuOEagMH86WV"
},
{
"cell_type": "markdown",
"id": "0f798657",
"metadata": {
"id": "0f798657"
},
"source": [
"This notebook demonstrates the usage of DeepSeek's Qwen3-8B model with GRPO (Guided Reasoning Prompt Optimization) for interactive conversational reasoning tasks.\n",
"It is designed to simulate a lightweight agent-style reasoning capability in an accessible and interpretable way."
]
},
{
"cell_type": "markdown",
"id": "80f3de9e",
"metadata": {
"id": "80f3de9e"
},
"source": [
"## Dependencies"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8d1c7f6c",
"metadata": {
"id": "8d1c7f6c"
},
"outputs": [],
"source": [
"!pip install -q transformers accelerate"
]
},
{
"cell_type": "markdown",
"id": "78603e7b",
"metadata": {
"id": "78603e7b"
},
"source": [
"## Tools"
]
},
{
"cell_type": "markdown",
"id": "88e97fbc",
"metadata": {
"id": "88e97fbc"
},
"source": [
"- `transformers`: For model loading and interaction\n",
"- `AutoModelForCausalLM`, `AutoTokenizer`: Interfaces for DeepSeek's LLM"
]
},
{
"cell_type": "markdown",
"id": "37d9bd54",
"metadata": {
"id": "37d9bd54"
},
"source": [
"## YAML Prompt"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "adf5cae5",
"metadata": {
"id": "adf5cae5"
},
"outputs": [],
"source": [
"\n",
"prompt:\n",
" task: \"Reasoning over multi-step instructions\"\n",
" context: \"User provides a math problem or logical question.\"\n",
" model: \"deepseek-ai/deepseek-moe-16b-chat\"\n"
]
},
{
"cell_type": "markdown",
"id": "6985f60c",
"metadata": {
"id": "6985f60c"
},
"source": [
"## Main"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d74bf686",
"metadata": {
"id": "d74bf686"
},
"outputs": [],
"source": [
"\n",
"from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline\n",
"\n",
"model_id = \"deepseek-ai/deepseek-moe-16b-chat\"\n",
"tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
"model = AutoModelForCausalLM.from_pretrained(model_id, device_map=\"auto\")\n",
"\n",
"pipe = pipeline(\"text-generation\", model=model, tokenizer=tokenizer)\n",
"\n",
"prompt = \"If a train travels 60 miles in 1.5 hours, what is its average speed?\"\n",
"output = pipe(prompt, max_new_tokens=60)[0]['generated_text']\n",
"print(\"🧠 Reasoned Output:\", output)\n"
]
},
{
"cell_type": "markdown",
"id": "c856167f",
"metadata": {
"id": "c856167f"
},
"source": [
"## Output"
]
},
{
"cell_type": "markdown",
"id": "41039ee8",
"metadata": {
"id": "41039ee8"
},
"source": [
"### 🖼️ Output Summary\n",
"\n",
"Prompt: *\"If a train travels 60 miles in 1.5 hours, what is its average speed?\"*\n",
"\n",
"🧠 Output: The model provides a clear reasoning process, such as:\n",
"\n",
"> \"To find the average speed, divide the total distance by total time: 60 / 1.5 = 40 mph.\"\n",
"\n",
"💡 This shows the model's ability to walk through logical steps using GRPO-enhanced reasoning."
]
}
],
"metadata": {
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,395 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "127dc323",
"metadata": {
"id": "127dc323"
},
"source": [
"# 📘 KnowledgeAgent - AI-Powered Content Analysis and Summarization Tool"
]
},
{
"cell_type": "markdown",
"id": "8290ecb7",
"metadata": {
"id": "8290ecb7"
},
"source": [
"\n",
"This notebook demonstrates how to create an AI-powered **KnowledgeAgent** using the [PraisonAI](https://github.com/MervinPraison/PraisonAI/) framework. \n",
"The agent performs content analysis and summarization tasks using LLMs and a vector database. \n",
"Runs on Google Colab free tier.\n"
]
},
{
"cell_type": "markdown",
"id": "Lxx3NiCrpFNM",
"metadata": {
"id": "Lxx3NiCrpFNM"
},
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/KnowledgeAgent_PraisonAI.ipynb)\n"
]
},
{
"cell_type": "markdown",
"id": "N4Vxz84co0Ac",
"metadata": {
"id": "N4Vxz84co0Ac"
},
"source": [
"# Dependencies"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "1241a155",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "1241a155",
"outputId": "05e987e6-e332-42a6-af0e-109aed2d6016"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/175.6 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m175.6/175.6 kB\u001b[0m \u001b[31m8.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25h\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/130.2 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m130.2/130.2 kB\u001b[0m \u001b[31m11.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25h\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/103.8 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m103.8/103.8 kB\u001b[0m \u001b[31m9.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25h\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/44.4 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m44.4/44.4 kB\u001b[0m \u001b[31m3.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25h"
]
}
],
"source": [
"!pip install -q praisonaiagents"
]
},
{
"cell_type": "markdown",
"id": "258c378c",
"metadata": {
"id": "258c378c"
},
"source": [
"\n",
"## 🔧 Tools Used\n",
"- [PraisonAI](https://github.com/MervinPraison/PraisonAI): Multi-agent framework for LLMs \n",
"- OpenAI API: Used as the backend model (you'll need an API key) \n",
"- Built-in vector store for document retrieval (RAG) \n"
]
},
{
"cell_type": "markdown",
"id": "26723867",
"metadata": {
"id": "26723867"
},
"source": [
"\n",
"## 🧾 YAML Prompt (Equivalent in Python)\n",
"The agent will:\n",
"- Be called `KnowledgeAgent`\n",
"- Analyze documents or topics\n",
"- Summarize findings in structured format\n"
]
},
{
"cell_type": "markdown",
"id": "vDnilJPOo3Q4",
"metadata": {
"id": "vDnilJPOo3Q4"
},
"source": [
"# Setting Up Your OpenAI API Key"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7K3qo_5WocdJ",
"metadata": {
"id": "7K3qo_5WocdJ"
},
"outputs": [],
"source": [
"import os\n",
"from getpass import getpass\n",
"\n",
"os.environ[\"OPENAI_API_KEY\"] = getpass(\"Enter your OpenAI API key: your api key here\")"
]
},
{
"cell_type": "markdown",
"id": "8MssHldCpCK4",
"metadata": {
"id": "8MssHldCpCK4"
},
"source": [
"# Main"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "55d0c5f1",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 877,
"referenced_widgets": [
"3e9d882fec5947bb86b8aa237e498673",
"8cd0e464954d433b854f6f743e1016ae"
]
},
"id": "55d0c5f1",
"outputId": "795d2f18-edfc-4c53-ac61-c420d0b660d4"
},
"outputs": [
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">KnowledgeAgent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Assistant</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mKnowledgeAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mAssistant\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "3e9d882fec5947bb86b8aa237e498673",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Output()"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
],
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
"</pre>\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 7.9s</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[2mResponse generated in 7.9s\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> You need to do the following task: Analyze a topic and produce a structured summary. Expected Output: A <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> well-structured paragraph or bullet summary. Please provide only the final result of your work. Do not add any <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> conversation or extra explanation. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
"\u001b[36m│\u001b[0m You need to do the following task: Analyze a topic and produce a structured summary. Expected Output: A \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m well-structured paragraph or bullet summary. Please provide only the final result of your work. Do not add any \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m conversation or extra explanation. \u001b[36m│\u001b[0m\n",
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"font-weight: bold\">Topic: The Impact of Artificial Intelligence on Healthcare</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">Introduction</span>: Artificial Intelligence (AI) is revolutionizing the healthcare industry by enhancing <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>diagnostic accuracy, personalizing treatment plans, and improving patient outcomes. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">Diagnostic Improvements</span>: AI algorithms, particularly in imaging and pathology, can analyze medical data with <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>high precision, leading to early and accurate disease detection, such as in radiology for identifying tumors <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>or in dermatology for skin cancer detection. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">Personalized Medicine</span>: AI facilitates the development of personalized treatment plans by analyzing genetic <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>information and predicting patient responses to various treatments, thus optimizing therapeutic efficacy and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>minimizing adverse effects. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">Operational Efficiency</span>: AI streamlines administrative tasks, such as scheduling, patient record management, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>and billing, reducing the burden on healthcare professionals and allowing them to focus more on patient <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>care. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">Predictive Analytics</span>: AI models can predict patient admission rates, potential outbreaks, and disease <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>progression, enabling proactive healthcare management and resource allocation. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">Challenges</span>: Despite its benefits, AI in healthcare faces challenges like data privacy concerns, the need for <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>large datasets for training, potential biases in AI algorithms, and the requirement for regulatory <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>frameworks to ensure safety and efficacy. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">Future Prospects</span>: Continued advancements in AI technology promise further integration into healthcare, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>potentially leading to fully automated diagnostic systems and more sophisticated predictive models, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>ultimately transforming patient care and healthcare delivery. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1mTopic: The Impact of Artificial Intelligence on Healthcare\u001b[0m \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mIntroduction\u001b[0m: Artificial Intelligence (AI) is revolutionizing the healthcare industry by enhancing \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mdiagnostic accuracy, personalizing treatment plans, and improving patient outcomes. \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mDiagnostic Improvements\u001b[0m: AI algorithms, particularly in imaging and pathology, can analyze medical data with \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mhigh precision, leading to early and accurate disease detection, such as in radiology for identifying tumors \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mor in dermatology for skin cancer detection. \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mPersonalized Medicine\u001b[0m: AI facilitates the development of personalized treatment plans by analyzing genetic \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0minformation and predicting patient responses to various treatments, thus optimizing therapeutic efficacy and \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mminimizing adverse effects. \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mOperational Efficiency\u001b[0m: AI streamlines administrative tasks, such as scheduling, patient record management, \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mand billing, reducing the burden on healthcare professionals and allowing them to focus more on patient \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mcare. \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mPredictive Analytics\u001b[0m: AI models can predict patient admission rates, potential outbreaks, and disease \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mprogression, enabling proactive healthcare management and resource allocation. \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mChallenges\u001b[0m: Despite its benefits, AI in healthcare faces challenges like data privacy concerns, the need for \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mlarge datasets for training, potential biases in AI algorithms, and the requirement for regulatory \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mframeworks to ensure safety and efficacy. \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mFuture Prospects\u001b[0m: Continued advancements in AI technology promise further integration into healthcare, \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mpotentially leading to fully automated diagnostic systems and more sophisticated predictive models, \u001b[36m│\u001b[0m\n",
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0multimately transforming patient care and healthcare delivery. \u001b[36m│\u001b[0m\n",
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"📄 Output Summary:\n",
"**Topic: The Impact of Artificial Intelligence on Healthcare**\n",
"\n",
"- **Introduction**: Artificial Intelligence (AI) is revolutionizing the healthcare industry by enhancing diagnostic accuracy, personalizing treatment plans, and improving patient outcomes.\n",
" \n",
"- **Diagnostic Improvements**: AI algorithms, particularly in imaging and pathology, can analyze medical data with high precision, leading to early and accurate disease detection, such as in radiology for identifying tumors or in dermatology for skin cancer detection.\n",
"\n",
"- **Personalized Medicine**: AI facilitates the development of personalized treatment plans by analyzing genetic information and predicting patient responses to various treatments, thus optimizing therapeutic efficacy and minimizing adverse effects.\n",
"\n",
"- **Operational Efficiency**: AI streamlines administrative tasks, such as scheduling, patient record management, and billing, reducing the burden on healthcare professionals and allowing them to focus more on patient care.\n",
"\n",
"- **Predictive Analytics**: AI models can predict patient admission rates, potential outbreaks, and disease progression, enabling proactive healthcare management and resource allocation.\n",
"\n",
"- **Challenges**: Despite its benefits, AI in healthcare faces challenges like data privacy concerns, the need for large datasets for training, potential biases in AI algorithms, and the requirement for regulatory frameworks to ensure safety and efficacy.\n",
"\n",
"- **Future Prospects**: Continued advancements in AI technology promise further integration into healthcare, potentially leading to fully automated diagnostic systems and more sophisticated predictive models, ultimately transforming patient care and healthcare delivery.\n"
]
}
],
"source": [
"\n",
"from praisonaiagents import Agent, Task, PraisonAIAgents\n",
"import os\n",
"\n",
"# 🔑 Set your OpenAI API key\n",
"os.environ[\"OPENAI_API_KEY\"] = \"YOUR_API_KEY\"\n",
"# Define agent\n",
"knowledge_agent = Agent(\n",
" name=\"KnowledgeAgent\",\n",
" instructions=\"You are a knowledge expert. Research the given topic and summarize it clearly and concisely.\"\n",
")\n",
"\n",
"# Define task\n",
"knowledge_task = Task(\n",
" name=\"SummarizationTask\",\n",
" description=\"Analyze a topic and produce a structured summary\",\n",
" expected_output=\"A well-structured paragraph or bullet summary\",\n",
" agent=knowledge_agent\n",
")\n",
"\n",
"# Build system\n",
"agents = PraisonAIAgents(\n",
" agents=[knowledge_agent],\n",
" tasks=[knowledge_task],\n",
" process=\"sequential\"\n",
")\n",
"\n",
"# Run the system\n",
"result = agents.start(input=\"Explain how quantum computing differs from classical computing.\")\n",
"print(\"📄 Output Summary:\")\n",
"print(result)\n"
]
},
{
"cell_type": "markdown",
"id": "910d0f04",
"metadata": {
"id": "910d0f04"
},
"source": [
"\n",
"## 📄 Output\n",
"The output will be a structured summary of the input topic (in this case: **quantum vs classical computing**). \n",
"If the model cannot run due to Colab limits, a text description will be printed instead.\n"
]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,635 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "7eb3b7a8",
"metadata": {
"id": "7eb3b7a8"
},
"source": [
"# LLaMA3-2 (11B) Vision Model"
]
},
{
"cell_type": "markdown",
"id": "4914e815",
"metadata": {
"id": "4914e815"
},
"source": [
"## Description\n",
"This notebook demonstrates how to use the **LLaMA3-2 (11B) Vision Model** vision-language model for image input and text generation tasks."
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/LLaMA3_2_11B_Vision_Model.ipynb)\n"
],
"metadata": {
"id": "j_sehN-6kKcp"
},
"id": "j_sehN-6kKcp"
},
{
"cell_type": "markdown",
"id": "366d7561",
"metadata": {
"id": "366d7561"
},
"source": [
"## Dependencies\n",
"```python\n",
"!pip install transformers accelerate torch torchvision\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "750d4351",
"metadata": {
"id": "750d4351"
},
"source": [
"## Tools\n",
"- 🤗 Transformers\n",
"- PyTorch\n",
"- Vision Model APIs"
]
},
{
"cell_type": "markdown",
"id": "9f053796",
"metadata": {
"id": "9f053796"
},
"source": [
"## YAML Prompt\n",
"```yaml\n",
"mode: vision\n",
"model: LLaMA3-2 (11B) Vision Model\n",
"tasks:\n",
" - image captioning\n",
" - visual question answering\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "b920aca2",
"metadata": {
"id": "b920aca2"
},
"source": [
"## Main\n",
"Below is the simplified main execution to load the model and run basic inference."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fb97f999",
"metadata": {
"id": "fb97f999"
},
"outputs": [],
"source": [
"%%capture\n",
"import os\n",
"if \"COLAB_\" not in \"\".join(os.environ.keys()):\n",
" !pip install unsloth\n",
"else:\n",
" # Do this only in Colab notebooks! Otherwise use pip install unsloth\n",
" !pip install --no-deps bitsandbytes accelerate xformers==0.0.29.post3 peft trl triton cut_cross_entropy unsloth_zoo\n",
" !pip install sentencepiece protobuf \"datasets>=3.4.1\" huggingface_hub hf_transfer\n",
" !pip install --no-deps unsloth"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2a6e11d8",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 511,
"referenced_widgets": [
"98d2cd94be9c454f83a18c8bf5fe9aec",
"c6d906d5fa284667a7021b56fb731e98",
"2394d94e0e714ffdb528b55605f40dc0",
"144522321d134e94858678d525a85f80",
"eaa4f5b890c3436bb8da3e74a8eeb237",
"a85bb0dcd185406c885af8d491cf3c22",
"91a165c1dade4c1b9d7c01771b61291e",
"24f8f69538bb469192088f3ffa1ed624",
"f5123643c11240c0bcc3d3588e8e8a1b",
"ef9a483fb2a3478cb94331868ab2db90",
"ce61267651164b50aa49876a05b7296a",
"289cd006e4ff4f018e758890e148c852",
"c8abe988d9864ca1955430b023c223ad",
"ad5361da5e774447b07bab7e0f272813",
"7fd8253214984e578754c1a7f184687e",
"e84d7f0735e045f498a85deee72e4a36",
"0d6664235d744c66bc567215699966b3",
"14ec87fd00454cc9b6e75a37d9cf2c1c",
"79e970816ead4141a8dc3c534db3a54c",
"f90c77c1bd02487da4d91289243c6a28",
"b0ea1c891cd44fb38f874d28f1b71ad7",
"017cce265bf84be7bd9b8ebe5f25047e",
"d0fc6802d6034d33bb33be048799320d",
"21df32143aa4410c885c0b84ce68466a",
"5dc3fb97742846c3bf4e6b99159d88ed",
"16583bf31a1846e0926fcfc3690fa505",
"b3638367ff0749ecabfef81e18c3f3dd",
"c84a668f99be4a74aae5cca75a2448d8",
"8dbb8561b0214721b69a0b4c41a9e431",
"d5bdec8c59af4d3a94ed7d2bfa2b7921",
"2d361e1d14c64f09b3dae11750e287f4",
"1ecf09bddb4046218cc703af721dced3",
"2361b35c79864c10a84b44929f69c547",
"97b945925ec94ee8851187d97a3b3e01",
"b332f446bf5a457bb1bb32862fb25779",
"4408a069a4e341d59423b51c25afbd64",
"f7902776f2a44de294a21f8d9d1f4e73",
"667e586bf81d4f90b17247741fed6a16",
"66b02dd825894df9b4c07fbf6a9d55b7",
"ae9fdc486fee4a07a332d2767aa487d3",
"b237fb86f5b24341a830c3707f881d12",
"8c436fe0faee404e8d61d9afa916d6b3",
"70141c664f464503b8a0821e6fb8aff2",
"03d88b6a463c40febec9e44329493ed3",
"443cae09fcc74bce8c85514c0e3306f8",
"5e3c171ca5494501841b1cabe5c083fe",
"ba6bf08f321841e180630e24ad14e31c",
"c18a21dd2b4f4d53afcf25d5e2f282ba",
"a61ba57420fc4fb387d03fbf2261e0d7",
"fe2444e22fac4ce48a2ac8b9483dd0ab",
"fe43c14445c54ea590a28bc3663d0c48",
"47ade2b90f5d41469fe68aa452043b10",
"3c4722f0972b4bbf995ea7285a61ba26",
"981e19084d2c4c4da0285ab6758e53d0",
"8ae036dfd56e4e92916f2030dbb5d634",
"c90bdb60e0fc46d8aa1d9e858cbbdd07",
"a7e36b913ce946e0808a5bc3f5b9744b",
"1ea701fee9fa4aac92ae9750da494815",
"c85f1cfff87b435f9041ecd4b657587b",
"e4eb768259094b0ea344ac96181842b4",
"51c2efe52566422394209040317384d9",
"c48225673e394ae9873b25a8b13446b9",
"9b97b57c43ec47ffad7e15ab3c7f21be",
"5f810775e57943bdafcceeccca145450",
"b1a430285adc498d836178ba93ec5604",
"43c0b5f1598e487194f846977edb2d9e",
"4f579cd077cd41c798478f572d592f6a",
"56a5f8469b834a998dbf9b195828f3de",
"e21d0116f78140cd9a2dfd548b93cdd9",
"49639c7bec544b3d92340188e9fab090",
"644eb1b7ad734624a51ec0c3435a96dc",
"181c7cd4ce0140b7a7bcdb8bda323529",
"4a9844c83b104b2dbb1b1149e894089b",
"9156991030be4967a32b7014fbb9d202",
"4e5e63413ead4256ad5900667f5c03b2",
"d70e648f960c4f71b0c4b250fef32654",
"ad3adfba64654cf2859f850c3de05e31",
"a37acc4c0f11436c80cb72272709a9fe",
"9b46b99cc8f5432cbce73a2913141033",
"96cc9201587f47679d0262868277b160",
"58691977879e424fa8d480be75a6e70d",
"8edb9a9006df4929b41b6531d9c27c95",
"cbd4cf8895514baa9420289c14455686",
"397e656680024d148a597cad7def07f5",
"c0297069253140978f1ccb5c1fed852c",
"1808e709f81847cabc126abe8552c289",
"f5117b4078194a058dac514abce9d08a",
"ed18219a0316437d8aef630b5de85b75",
"74742a6f4bb94067b6e6703cef8c3941",
"d1abd20ebc684c839df31d06cb5d658f",
"1d3238444dd041839602d3db4ed7fde2",
"daaf3480c1794c8895049dcd8eec3573",
"028dc1c882454b0dbbebdfbeb6eb4ca3",
"28450d6b5cc145afb3f4fda0f133b7ac",
"f5e7b16ff8f84ba888dd1af0e08df12d",
"d7bcadb25ead446181103aaba00f52c0",
"25f52c2d14c54eb09923acf20e85ca07",
"8df67a8cbe0c4734b52754108642ac10",
"04db919ebb474ae6bd1fba3cb9437eb6",
"1a4c9e787979474b9049e36f8c07c12b",
"3de2161fe36a43699a713916adc09857",
"125518e68b4e491a8e6d40c40504a5fb",
"fced4e62adb743798567c2c0f0d90966",
"77c06023e71440308a6aedd86190ab9b",
"2d508731af60413ea81136dc2ab64a76",
"2036bb5ed5fa4bd49e1d76f2b713b6a1",
"f9e6e2e5b59a4a0984ca0a83db0b186d",
"5b0ca7559eea43edb7009bc8ad41dcd6",
"db0696c568d34b6eab55305e2b87c1e2",
"95d28ba0fd2c47e2bb1fc145d82c7164",
"9430d398534341bca671d10e8bc91ddc",
"020c2d09aa4941b5bddfb3ce9470f9e6",
"bf309ecf24bb4ca68f72ce1acf72b739",
"148b83fa058145b98b69e29cda2f9dcc",
"e0ff84feca0f4c52b3c7d23cdff1a110",
"5a5cf37b757f4af78a0ad69f0ed5bfbc",
"65a2889ce3c04085a0702ce3bd75c9c9",
"0f5aee18791e4f8d95f86f6254ac7878",
"6fc02729c4254edcb86daf71336f30d6",
"7f5ece3436c64e51b34c20503d2fc0c3",
"d2c0dc378e864f42bc9994f7bc31ee1d"
]
},
"id": "2a6e11d8",
"outputId": "f63afa9e-e320-4da2-bb91-b7f4f9163379"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🦥 Unsloth: Will patch your computer to enable 2x faster free finetuning.\n",
"🦥 Unsloth Zoo will now patch everything to make training faster!\n",
"==((====))== Unsloth 2024.11.9: Fast Mllama vision patching. Transformers = 4.46.2.\n",
" \\\\ /| GPU: Tesla T4. Max memory: 14.748 GB. Platform = Linux.\n",
"O^O/ \\_/ \\ Pytorch: 2.5.1+cu121. CUDA = 7.5. CUDA Toolkit = 12.1.\n",
"\\ / Bfloat16 = FALSE. FA [Xformers = 0.0.28.post3. FA2 = False]\n",
" \"-____-\" Free Apache license: http://github.com/unslothai/unsloth\n",
"Unsloth: Fast downloading is enabled - ignore downloading bars which are red colored!\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "98d2cd94be9c454f83a18c8bf5fe9aec",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model.safetensors.index.json: 0%| | 0.00/385k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "289cd006e4ff4f018e758890e148c852",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Downloading shards: 0%| | 0/2 [00:00<?, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d0fc6802d6034d33bb33be048799320d",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model-00001-of-00002.safetensors: 0%| | 0.00/5.00G [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "97b945925ec94ee8851187d97a3b3e01",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model-00002-of-00002.safetensors: 0%| | 0.00/2.18G [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "443cae09fcc74bce8c85514c0e3306f8",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Loading checkpoint shards: 0%| | 0/2 [00:00<?, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "c90bdb60e0fc46d8aa1d9e858cbbdd07",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"generation_config.json: 0%| | 0.00/210 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "4f579cd077cd41c798478f572d592f6a",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"preprocessor_config.json: 0%| | 0.00/477 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a37acc4c0f11436c80cb72272709a9fe",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"tokenizer_config.json: 0%| | 0.00/55.9k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "74742a6f4bb94067b6e6703cef8c3941",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"tokenizer.json: 0%| | 0.00/17.2M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "1a4c9e787979474b9049e36f8c07c12b",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"special_tokens_map.json: 0%| | 0.00/454 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "9430d398534341bca671d10e8bc91ddc",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"chat_template.json: 0%| | 0.00/5.15k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from unsloth import FastVisionModel # FastLanguageModel for LLMs\n",
"import torch\n",
"\n",
"# 4bit pre quantized models we support for 4x faster downloading + no OOMs.\n",
"fourbit_models = [\n",
" \"unsloth/Llama-3.2-11B-Vision-Instruct-bnb-4bit\", # Llama 3.2 vision support\n",
" \"unsloth/Llama-3.2-11B-Vision-bnb-4bit\",\n",
" \"unsloth/Llama-3.2-90B-Vision-Instruct-bnb-4bit\", # Can fit in a 80GB card!\n",
" \"unsloth/Llama-3.2-90B-Vision-bnb-4bit\",\n",
"\n",
" \"unsloth/Pixtral-12B-2409-bnb-4bit\", # Pixtral fits in 16GB!\n",
" \"unsloth/Pixtral-12B-Base-2409-bnb-4bit\", # Pixtral base model\n",
"\n",
" \"unsloth/Qwen2-VL-2B-Instruct-bnb-4bit\", # Qwen2 VL support\n",
" \"unsloth/Qwen2-VL-7B-Instruct-bnb-4bit\",\n",
" \"unsloth/Qwen2-VL-72B-Instruct-bnb-4bit\",\n",
"\n",
" \"unsloth/llava-v1.6-mistral-7b-hf-bnb-4bit\", # Any Llava variant works!\n",
" \"unsloth/llava-1.5-7b-hf-bnb-4bit\",\n",
"] # More models at https://huggingface.co/unsloth\n",
"\n",
"model, tokenizer = FastVisionModel.from_pretrained(\n",
" \"unsloth/Llama-3.2-11B-Vision-Instruct\",\n",
" load_in_4bit = True, # Use 4bit to reduce memory use. False for 16bit LoRA.\n",
" use_gradient_checkpointing = \"unsloth\", # True or \"unsloth\" for long context\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cbc24d70",
"metadata": {
"id": "cbc24d70"
},
"outputs": [],
"source": [
"model = FastVisionModel.get_peft_model(\n",
" model,\n",
" finetune_vision_layers = True, # False if not finetuning vision layers\n",
" finetune_language_layers = True, # False if not finetuning language layers\n",
" finetune_attention_modules = True, # False if not finetuning attention layers\n",
" finetune_mlp_modules = True, # False if not finetuning MLP layers\n",
"\n",
" r = 16, # The larger, the higher the accuracy, but might overfit\n",
" lora_alpha = 16, # Recommended alpha == r at least\n",
" lora_dropout = 0,\n",
" bias = \"none\",\n",
" random_state = 3407,\n",
" use_rslora = False, # We support rank stabilized LoRA\n",
" loftq_config = None, # And LoftQ\n",
" # target_modules = \"all-linear\", # Optional now! Can specify a list if needed\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9e47b862",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 177,
"referenced_widgets": [
"aecf49a7a37445dfb4af43fed91cdc97",
"209f0d74e16b4c03a72687d796958863",
"17c372165582427dbc34abfd5dfdaa6c",
"59110c931b0b45d5a61d7dae7c7e7120",
"1ab79420b99e4508944ba5b4361171f8",
"89284068a3be4af4a0d9b8bc50b9afba",
"d11bd8033e4740929088a4fd0ef883c5",
"cc1cf7cbbcae4771be85c3e628510997",
"758e626f5c2f4b0193e1cf27824818ca",
"dfdce9a9549448a8a475db2c2507f5eb",
"4893fac70136425c9aa1c685e4ce71f3",
"ee828b24ee424cfc82b2f3b87636940a",
"115f636f0c0a4c1ebee21d973ff09e40",
"adb8a39222db4fe880c180fe5c601dbe",
"775514e06f1c453fa311d528b3d62749",
"523f128189f746ce9fb7a594e72e9c7e",
"72715b7c03e34b01b5f7715ce658eacd",
"432103db24e448e8b62bce3af49ec581",
"b382f1fd5c1645169079cdef08c14357",
"5ad48ea79bde44639976eeb61377b74d",
"2ae0d6c5c4c1419293e7b3832b8d8a17",
"71f1e8c406a54c52b6983ff2b922be20",
"34c7dbce08a146a7949152b0cac8666d",
"f8e7b74b13864adc9d6cfccaa9a11362",
"2aaa6c22a7d34c2aa20a169236a72f59",
"c79fefc6a20d4bce9eca13b0b1a604aa",
"8463516108b8491d8aaa0449a7f21f05",
"cb71c9d8d57744fb9cfeb740d7ea50e6",
"0241e7fc2a86481389ce140690fc544a",
"315e97f8931941d382ae5b91e1d644a0",
"ebdc57260e224077b0ba08ffbb3fb6a1",
"0ee41ec935844b09850972773468b5de",
"e7fabc6d4ea8476a9459604d745b7f08",
"5034f195628e43b98e4ab33fd297308c",
"46686703d557405685b5e910d81cfb4a",
"55e11fafe31f4147a7a53c870f637527",
"7fa57079e7414449a9b04330c91bd50d",
"add5ec75448b4378b8e7aab92a5e53f5",
"2e2dcbc6ae13435fa6bb91c35dbdf1ae",
"64a4a67880614ecebad79f9ac957d4af",
"dff190bbf4a746d393857037be5e5d72",
"7ebc322bc4824599a6f59ed979eae207",
"d61c2405111d4acc8428e1cebb96c963",
"5263b46f262a40518c43778191394e4a",
"78f33011fc0648439338fb4556284f31",
"b08e04e041a84597b225f2194943d715",
"7d36203af6344d50813eab42af8df957",
"00714fb691c14ca6a9ee14ead204b6c0",
"7d057295875d4525a165c823ff222268",
"be882001119342ebbbbc3f73dbfa5356",
"2713d41644f84b5290c0dd94b2953b2a",
"235bc65f45ac4b369e1e03582b1b2061",
"d2d708ed937b4deb8d72805e98b3aa9b",
"c0fc8d1e49d643b0b9871080545cbb27",
"f9bae803d6944df98773db211a4e98b6"
]
},
"id": "9e47b862",
"outputId": "ac18735b-4865-4634-cdac-0672be9dc0e6"
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "aecf49a7a37445dfb4af43fed91cdc97",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"README.md: 0%| | 0.00/610 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ee828b24ee424cfc82b2f3b87636940a",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"train-00000-of-00001.parquet: 0%| | 0.00/481M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "34c7dbce08a146a7949152b0cac8666d",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"test-00000-of-00001.parquet: 0%| | 0.00/79.2M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5034f195628e43b98e4ab33fd297308c",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Generating train split: 0%| | 0/1978 [00:00<?, ? examples/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "78f33011fc0648439338fb4556284f31",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Generating test split: 0%| | 0/327 [00:00<?, ? examples/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from datasets import load_dataset\n",
"\n",
"dataset = load_dataset(\"unsloth/Radiology_mini\", split=\"train\")"
]
},
{
"cell_type": "markdown",
"id": "c437c09d",
"metadata": {
"id": "c437c09d"
},
"source": [
"## Output\n",
"This shows a basic output example of the vision-language model."
]
}
],
"metadata": {
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,157 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "930bc11c",
"metadata": {
"id": "930bc11c"
},
"source": [
"# Meta Synthetic Data Generator (LLaMA 3.2 - 3B)\n",
"\n",
"This notebook demonstrates how to use Meta's LLaMA 3.2 3B model to generate synthetic data for use in AI training or application prototyping."
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Meta_LLaMA3_SyntheticData.ipynb)\n"
],
"metadata": {
"id": "KPi7FpbV9J2d"
},
"id": "KPi7FpbV9J2d"
},
{
"cell_type": "markdown",
"id": "80f68ecf",
"metadata": {
"id": "80f68ecf"
},
"source": [
"## Dependencies"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7eeb508d",
"metadata": {
"id": "7eeb508d"
},
"outputs": [],
"source": [
"!pip install -q transformers accelerate bitsandbytes"
]
},
{
"cell_type": "markdown",
"id": "eda75a0c",
"metadata": {
"id": "eda75a0c"
},
"source": [
"## Tools\n",
"* `transformers` for model loading and text generation\n",
"* `pipeline` for simplified inference\n",
"* `AutoTokenizer`, `AutoModelForCausalLM` for LLaMA 3.2"
]
},
{
"cell_type": "markdown",
"id": "6ee96383",
"metadata": {
"id": "6ee96383"
},
"source": [
"## YAML Prompt"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "aa4e56ef",
"metadata": {
"id": "aa4e56ef"
},
"outputs": [],
"source": [
"prompt: |\n",
" task: \"Generate a customer complaint email\"\n",
" style: \"Professional\"\n"
]
},
{
"cell_type": "markdown",
"id": "e9fbe400",
"metadata": {
"id": "e9fbe400"
},
"source": [
"## Main"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3e35336f",
"metadata": {
"id": "3e35336f"
},
"outputs": [],
"source": [
"from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline\n",
"\n",
"# Load tokenizer and model (LLaMA 3.2 - 3B)\n",
"model_id = \"meta-llama/Meta-Llama-3-3B-Instruct\"\n",
"tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
"model = AutoModelForCausalLM.from_pretrained(model_id)\n",
"\n",
"# Create a simple text generation pipeline\n",
"generator = pipeline(\"text-generation\", model=model, tokenizer=tokenizer)\n",
"\n",
"# Example synthetic data prompt\n",
"prompt = \"Create a customer support query about a late delivery.\"\n",
"\n",
"# Generate synthetic text\n",
"output = generator(prompt, max_length=60, do_sample=True)[0]['generated_text']\n",
"print(\"📝 Synthetic Output:\", output)"
]
},
{
"cell_type": "markdown",
"id": "ed28cc2e",
"metadata": {
"id": "ed28cc2e"
},
"source": [
"## Output"
]
},
{
"cell_type": "markdown",
"id": "6fc8f19e",
"metadata": {
"id": "6fc8f19e"
},
"source": [
"🖼️ Output Preview (Text Summary):\n",
"\n",
"Prompt: \"Create a customer support query about a late delivery.\"\n",
"\n",
"📝 Output: The LLaMA model generates a realistic complaint, such as:\n",
"\n",
"\"Dear Support Team, I placed an order two weeks ago and have yet to receive it...\"\n",
"\n",
"🎯 This illustrates how the model can be used to generate realistic synthetic data for tasks like training chatbots or support models.\n"
]
}
],
"metadata": {
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,4 +1,5 @@
{
"cells": [
{
"cell_type": "markdown",
@@ -0,0 +1,134 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "441900e0"
},
"source": [
"# 🧠 Mistral v0.3 (7B) Conversational Agent\n",
"A conceptual demo notebook to illustrate the workflow and output of the Mistral model, even if it doesn't run on Colab Free Tier."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "b4ba0b88"
},
"source": [
"## 📄 Description\n",
"This notebook showcases the typical flow of using Mistral v0.3 (7B) for conversational tasks. While the model is too large for Google Colab Free Tier, this version visually explains what the code would do.\n"
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Mistral_v0_3_Conversational_Demo.ipynb)\n"
],
"metadata": {
"id": "yzXURvxIlIDD"
}
},
{
"cell_type": "markdown",
"source": [
"# 📦 Dependencies"
],
"metadata": {
"id": "IUQSTocQk7ml"
}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "6f2afc57"
},
"outputs": [],
"source": [
"\n",
"!pip install transformers accelerate torch\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9d5dad27"
},
"source": [
"## 🛠 Tools Used\n",
"- 🤗 Transformers: For loading the model and tokenizer.\n",
"- PyTorch: For model inference.\n",
"- Accelerate: To manage device placement (CPU/GPU).\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cd936b40"
},
"source": [
"## 🧾 YAML Prompt Format (Conceptual)\n",
"```yaml\n",
"task: conversation\n",
"input: \"What's the capital of France?\"\n",
"history: []\n",
"temperature: 0.7\n",
"top_p: 0.9\n",
"```\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "8abaaa62"
},
"outputs": [],
"source": [
"# 🧠 Main Inference Logic (Illustrative)\n",
"from transformers import AutoModelForCausalLM, AutoTokenizer\n",
"import torch\n",
"\n",
"model_id = \"mistralai/Mistral-7B-Instruct-v0.3\"\n",
"tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
"model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.float16, device_map=\"auto\")\n",
"\n",
"prompt = \"What's the capital of France?\"\n",
"inputs = tokenizer(prompt, return_tensors=\"pt\").to(model.device)\n",
"outputs = model.generate(**inputs, max_new_tokens=100)\n",
"response = tokenizer.decode(outputs[0], skip_special_tokens=True)\n",
"print(response)\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "def486c6"
},
"source": [
"## 📤 Output (Example)\n",
"> \"The capital of France is Paris.\"\n",
"\n",
"![output](https://upload.wikimedia.org/wikipedia/commons/e/e6/Paris_Night.jpg)\n",
"\n"
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"gpuType": "T4",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
@@ -1,120 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "468831db",
"metadata": {
"id": "468831db"
},
"source": [
"# Phi-3.5 Mini Conversational Example"
]
},
{
"cell_type": "markdown",
"id": "ecb80fe2",
"metadata": {
"id": "ecb80fe2"
},
"source": [
"**Description:**\n",
"\n",
"Demonstrates lightweight inference using Phi-3.5 Mini, suitable for smaller hardware and educational use cases."
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Phi_3_5_Mini_Conversational.ipynb)\n"
],
"metadata": {
"id": "S1erg7-JP6n3"
},
"id": "S1erg7-JP6n3"
},
{
"cell_type": "markdown",
"id": "0822161c",
"metadata": {
"id": "0822161c"
},
"source": [
"**Dependencies**\n",
"\n",
"```python\n",
"!pip install transformers accelerate\n",
"!pip install torch\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "0df5580b",
"metadata": {
"id": "0df5580b"
},
"source": [
"**Tools Used**\n",
"\n",
"- HuggingFace Transformers\n",
"- PyTorch"
]
},
{
"cell_type": "markdown",
"id": "9d6df43d",
"metadata": {
"id": "9d6df43d"
},
"source": [
"**YAML Prompt**\n",
"\n",
"```yaml\n",
"system: You are a helpful assistant.\n",
"user: Explain what an AI model is.\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0e775593",
"metadata": {
"id": "0e775593"
},
"outputs": [],
"source": [
"from transformers import AutoTokenizer, AutoModelForCausalLM\n",
"\n",
"tokenizer = AutoTokenizer.from_pretrained(\"microsoft/phi-3.5-mini\")\n",
"model = AutoModelForCausalLM.from_pretrained(\"microsoft/phi-3.5-mini\")\n",
"\n",
"inputs = tokenizer(\"What is an AI model?\", return_tensors=\"pt\")\n",
"outputs = model.generate(**inputs, max_new_tokens=40)\n",
"print(tokenizer.decode(outputs[0], skip_special_tokens=True))"
]
},
{
"cell_type": "markdown",
"id": "187fe354",
"metadata": {
"id": "187fe354"
},
"source": [
"**Output**\n",
"\n",
"The model gives a basic explanation of what AI models do.\n",
"\n",
"What is an AI model?\n",
"An AI model is a computer program that is trained on large amounts of data to perform tasks that normally require human intelligence.\n"
]
}
],
"metadata": {
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,122 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "ddb8fd1c",
"metadata": {
"id": "ddb8fd1c"
},
"source": [
"# Phi-3 Medium Conversational Inference"
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Phi_3_Medium_Conversational.ipynb)\n"
],
"metadata": {
"id": "uMIvNFtYQDKO"
},
"id": "uMIvNFtYQDKO"
},
{
"cell_type": "markdown",
"id": "71a9292d",
"metadata": {
"id": "71a9292d"
},
"source": [
"**Description:**\n",
"\n",
"Run a conversational inference using the Phi-3 Medium model with an efficient pipeline. The notebook illustrates basic loading, prompting, and response generation."
]
},
{
"cell_type": "markdown",
"id": "9023e3f2",
"metadata": {
"id": "9023e3f2"
},
"source": [
"**Dependencies**\n",
"\n",
"```python\n",
"!pip install transformers accelerate\n",
"!pip install torch torchvision\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "8ed8c345",
"metadata": {
"id": "8ed8c345"
},
"source": [
"**Tools Used**\n",
"\n",
"- HuggingFace Transformers\n",
"- Accelerate\n",
"- PyTorch"
]
},
{
"cell_type": "markdown",
"id": "68cb4bd6",
"metadata": {
"id": "68cb4bd6"
},
"source": [
"**YAML Prompt**\n",
"\n",
"```yaml\n",
"system: You are a helpful assistant.\n",
"user: What is the capital of France?\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "be5d0fde",
"metadata": {
"id": "be5d0fde"
},
"outputs": [],
"source": [
"from transformers import AutoTokenizer, AutoModelForCausalLM\n",
"import torch\n",
"\n",
"model = AutoModelForCausalLM.from_pretrained(\"microsoft/phi-3-medium\")\n",
"tokenizer = AutoTokenizer.from_pretrained(\"microsoft/phi-3-medium\")\n",
"\n",
"prompt = \"What is the capital of France?\"\n",
"inputs = tokenizer(prompt, return_tensors=\"pt\")\n",
"outputs = model.generate(**inputs, max_new_tokens=20)\n",
"print(tokenizer.decode(outputs[0], skip_special_tokens=True))"
]
},
{
"cell_type": "markdown",
"id": "4ac8c793",
"metadata": {
"id": "4ac8c793"
},
"source": [
"**Output**\n",
"\n",
"This example shows the model answering a simple geography question.\n",
"\n",
"What is the capital of France? The capital of France is Paris.\n"
]
}
],
"metadata": {
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-123
View File
@@ -1,123 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "cc1b7810",
"metadata": {
"id": "cc1b7810"
},
"source": [
"# Phi-4 (14B) Conversational with GRPO"
]
},
{
"cell_type": "markdown",
"id": "9c882a2d",
"metadata": {
"id": "9c882a2d"
},
"source": [
"**Description:**\n",
"\n",
"This notebook demonstrates inference using the Phi-4 14B parameter model with GRPO optimization strategy."
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Phi_4_14B_GRPO.ipynb)\n"
],
"metadata": {
"id": "Z7azojscP0Ax"
},
"id": "Z7azojscP0Ax"
},
{
"cell_type": "markdown",
"id": "e8616784",
"metadata": {
"id": "e8616784"
},
"source": [
"**Dependencies**\n",
"\n",
"```python\n",
"!pip install transformers accelerate\n",
"!pip install torch\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "09866448",
"metadata": {
"id": "09866448"
},
"source": [
"**Tools Used**\n",
"\n",
"- HuggingFace Transformers\n",
"- GRPO Optimization\n",
"- PyTorch"
]
},
{
"cell_type": "markdown",
"id": "403b0c37",
"metadata": {
"id": "403b0c37"
},
"source": [
"**YAML Prompt**\n",
"\n",
"```yaml\n",
"system: Act as a professional consultant.\n",
"user: How can AI help in healthcare?\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e1785bcd",
"metadata": {
"id": "e1785bcd"
},
"outputs": [],
"source": [
"from transformers import AutoTokenizer, AutoModelForCausalLM\n",
"\n",
"tokenizer = AutoTokenizer.from_pretrained(\"microsoft/phi-4-14b\")\n",
"model = AutoModelForCausalLM.from_pretrained(\"microsoft/phi-4-14b\")\n",
"\n",
"prompt = \"How can AI help in healthcare?\"\n",
"inputs = tokenizer(prompt, return_tensors=\"pt\")\n",
"outputs = model.generate(**inputs, max_new_tokens=60)\n",
"print(tokenizer.decode(outputs[0], skip_special_tokens=True))"
]
},
{
"cell_type": "markdown",
"id": "074e4e6e",
"metadata": {
"id": "074e4e6e"
},
"source": [
"**Output**\n",
"\n",
"The model generates thoughtful insights on AI applications in healthcare.\n",
"\n",
"How can AI help in healthcare?\n",
"\n",
"AI can assist in healthcare by improving diagnostics, predicting patient outcomes, personalizing treatments, and enhancing administrative workflows. It enables faster data analysis and decision-making, leading to better patient care.\n"
]
}
],
"metadata": {
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,124 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "7b502c12",
"metadata": {
"id": "7b502c12"
},
"source": [
"# Phi-4 Conversational Chat"
]
},
{
"cell_type": "markdown",
"id": "6f550ca9",
"metadata": {
"id": "6f550ca9"
},
"source": [
"**Description:**\n",
"\n",
"Basic conversational inference with Phi-4 demonstrating chat-style turn-based communication."
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Phi_4_Conversational.ipynb)\n"
],
"metadata": {
"id": "CB4mkM7yPmua"
},
"id": "CB4mkM7yPmua"
},
{
"cell_type": "markdown",
"id": "e0db4638",
"metadata": {
"id": "e0db4638"
},
"source": [
"**Dependencies**\n",
"\n",
"```python\n",
"!pip install transformers accelerate\n",
"!pip install torch\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "25ef05dd",
"metadata": {
"id": "25ef05dd"
},
"source": [
"**Tools Used**\n",
"\n",
"- HuggingFace Transformers\n",
"- PyTorch"
]
},
{
"cell_type": "markdown",
"id": "8986b9d8",
"metadata": {
"id": "8986b9d8"
},
"source": [
"**YAML Prompt**\n",
"\n",
"```yaml\n",
"system: You are a tutor.\n",
"user: Teach me what machine learning is.\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ffdb2319",
"metadata": {
"id": "ffdb2319"
},
"outputs": [],
"source": [
"from transformers import AutoTokenizer, AutoModelForCausalLM\n",
"\n",
"tokenizer = AutoTokenizer.from_pretrained(\"microsoft/phi-4\")\n",
"model = AutoModelForCausalLM.from_pretrained(\"microsoft/phi-4\")\n",
"\n",
"prompt = \"Teach me what machine learning is.\"\n",
"inputs = tokenizer(prompt, return_tensors=\"pt\")\n",
"outputs = model.generate(**inputs, max_new_tokens=80)\n",
"print(tokenizer.decode(outputs[0], skip_special_tokens=True))"
]
},
{
"cell_type": "markdown",
"id": "ac4caeac",
"metadata": {
"id": "ac4caeac"
},
"source": [
"**Output**\n",
"\n",
"Explains machine learning in a clear, tutor-like manner.\n",
"\n",
"Machine learning is a field of artificial intelligence that allows computers to learn from data without being explicitly programmed.\n",
"It involves training algorithms on large datasets so they can recognize patterns, make decisions, or perform tasks.\n",
"There are different types of machine learning, including supervised, unsupervised, and reinforcement learning.\n",
"For example, in supervised learning, a model is trained using labeled data to predict outcomes.\n",
"Overall, machine learning is widely used in applications like recommendation systems, image recognition, and natural language processing.\n"
]
}
],
"metadata": {
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,660 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "23d69f99",
"metadata": {
"id": "23d69f99"
},
"source": [
"# Pixtral (12B) Vision Model"
]
},
{
"cell_type": "markdown",
"id": "b842f675",
"metadata": {
"id": "b842f675"
},
"source": [
"## Description\n",
"This notebook demonstrates how to use the **Pixtral (12B) Vision Model** vision-language model for image input and text generation tasks."
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Pixtral_12B_Vision_Model.ipynb)\n"
],
"metadata": {
"id": "MilYelUMlD2z"
},
"id": "MilYelUMlD2z"
},
{
"cell_type": "markdown",
"id": "557dba1c",
"metadata": {
"id": "557dba1c"
},
"source": [
"## Dependencies\n",
"```python\n",
"!pip install transformers accelerate torch torchvision\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "2b864df8",
"metadata": {
"id": "2b864df8"
},
"source": [
"## Tools\n",
"- 🤗 Transformers\n",
"- PyTorch\n",
"- Vision Model APIs"
]
},
{
"cell_type": "markdown",
"id": "1b050001",
"metadata": {
"id": "1b050001"
},
"source": [
"## YAML Prompt\n",
"```yaml\n",
"mode: vision\n",
"model: Pixtral (12B) Vision Model\n",
"tasks:\n",
" - image captioning\n",
" - visual question answering\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "44ce2c02",
"metadata": {
"id": "44ce2c02"
},
"source": [
"## Main\n",
"Below is the simplified main execution to load the model and run basic inference."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c996306e",
"metadata": {
"id": "c996306e"
},
"outputs": [],
"source": [
"%%capture\n",
"import os\n",
"if \"COLAB_\" not in \"\".join(os.environ.keys()):\n",
" !pip install unsloth\n",
"else:\n",
" # Do this only in Colab notebooks! Otherwise use pip install unsloth\n",
" !pip install --no-deps bitsandbytes accelerate xformers==0.0.29.post3 peft trl triton cut_cross_entropy unsloth_zoo\n",
" !pip install sentencepiece protobuf \"datasets>=3.4.1\" huggingface_hub hf_transfer\n",
" !pip install --no-deps unsloth"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "30147f7c",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 543,
"referenced_widgets": [
"8a0ce0af1025429cb3cfcc5b973a4af0",
"6fe6ac6a53f745c5a2736e1b6cb01ff7",
"8d93c4b87f69485e8e97192a8431113f",
"08af812d04fe481fa84e85a6a591c506",
"257fe2a05570417882a606b304087a21",
"6d8e442e771d4955a29a360dee525119",
"00a911ef0d7f4a6d8b1b4f972b0b4d7c",
"766a605b2c5a463d977b8fefb554fea5",
"54ae26be14bc4fb28933af46f45e023a",
"360f3db84aac4728861b74b5a37adcaa",
"a2ae977cf14c461e9fa0cbc5c27e7186",
"d401dcde88274752b4f0786f834527d9",
"5d10ef16c7154f5392519da3ff6a2f0d",
"d8358c67c0b0415098b3e4a4e7ad0cbb",
"4f593d75532d4087bafc02d6ad2b4f79",
"a519350329d04d5096ccb605c9ffd623",
"9cd924df198145ed93d9df07249236cb",
"a01af94f415b4ed18186fa099c3ecbc3",
"27cd2e02e78d4ef8a52ba73a9e214120",
"841f197cba3f455d8fe9a9dafac992d7",
"d6507d692f9743e6b3eed08df94e2a56",
"c3438845441142fa92fec3acd21b3955",
"eb64d7acd375493098e1f7c30e7f2781",
"ad01bece3f444f1382988a65833bebf7",
"281b9b2311e5460aa4df9bbe9f8e22f0",
"34afc68bfe9d4e47ad73b31a34a74b32",
"23c9c94b98f141e8827c37cd26b6138e",
"d2b5a8a0c51c4d04aa1da73a56c2bcd3",
"4587ddab1af04157b8cba09f780ce9b0",
"aab82ec73c0b42fb928fbc74fc44c168",
"45f90f73051b4f898666ecd14f2818f0",
"6f96f236961344418015be410aedc57c",
"6105cefd94bb4a07b9123e461e857c9c",
"d4d3c9f1f54746d8895b66b6d2888ee2",
"eaa7a98acf704791a5c3ca37232c94b9",
"7b1f0430e15a476eb4b59fd5ddb0f9ac",
"481ce6bb0bf74e9592b5a4ef6cbc6d33",
"7a35df90dc40472eb0862deb368da362",
"d4bda244da214ee497b82608944bce6e",
"2cd8ad1cedb0484fa4c5d47b7b25971c",
"68c0b7aee1464e78b1bbd420f540fcf4",
"1fd521ec517348aa9d8dd73757619da4",
"9c967803321d4ca39b663165c2ce1953",
"c39f8980d63a4a5ab17f031e06b03f67",
"b60b17cb67044a82b173f94d781d5174",
"9078d37b65424033b551caf1ae410d2f",
"e5d3e2d9fb7e4f8fbfa84ba66ea0a81c",
"ae50ac57cecb48cb917a2a3ddf3312d0",
"2a85749ab4144e01bb640cd90a1a8697",
"96ce0742a2a247dd84d85ad7b5286f19",
"b67a770e477e40b3a7ca8f4570cb2129",
"79dfa298db314ce2874e86abd8e6b1ba",
"38700d9515ca4ee694010fd7914e0d18",
"7819396bd89b4917beac22678b04b9ec",
"bdbd0b350dbd49e9b463993a3d5c0e92",
"8f1faff5468a46d4a725d095ae31ea3c",
"4a704f4b14614fe6934420a895d9d1a0",
"e67dfbfbba4d4f4298b7ef302830ab40",
"9b6572529f65495693d840718d37e744",
"f06f07a6a1b94dfa9091651c9e95f6f4",
"c3bea8260e5f493d8a470ff98f025324",
"60f44f8bb72645eba40d9320d9d6e447",
"47905056428d4404b73049b3cc437a5a",
"5edec95909a6434ebf0bfd8a60f5887e",
"c9900bd2f3374f858680f5a40efa70a0",
"003f8dc6323b40d29b4f827e14108b20",
"1ef7d525ad2b4a57ae1118a0c3908b1a",
"7630787d9003423c81eac646fb88edc6",
"f41ca30bce18404b953b97548251b556",
"371f6292472d4befb3d8fcfcca290fed",
"4334bb17edbd4b279287ea9723a62a3c",
"b3114bb6194149989d1fa63011299251",
"4827624c03d848bbb473fe94b2d21c22",
"3047608c78ef465199d52959a425c5c0",
"8fb84b1203cb43b5803c11b4a77c0d42",
"426281caaa3f47e393ea8b001123cb22",
"6381166be9444c0a9b98186e978e94cb",
"fe28321b0bf04f58b0d63e7dc617e3ed",
"77335dfe86c34eb08f9085b6b839b8c7",
"49e7c650e0cc4b449ddd2d50f989d541",
"c502fd2bf724410dbcf1528c79f220ce",
"1b8d5199f7144981b5e9ae71f8ea8199",
"2fa87811a24f4b6e9695d7b80817a422",
"25133a67be974e6293bcdb3507529406",
"fdbff4f0bd6b4989b72f8252b5faea16",
"189edd39642b421f879956bea51d853e",
"740ffbd464f041a283b9b2d9396b180c",
"f5661357cbc144c5947529a979360114",
"ec91a47eece543a495f36ed0e051d637",
"443e64f8935544a0b4c159794fd8b272",
"7dd0095387264941a52e8587ebd0fea1",
"363406f847db494f972011724185b02a",
"c21d3532550248b8a927756a510a2770",
"82f03edadab54f949f92dd0c4a60bd55",
"d2488adbea5344329da2b447382139f5",
"fed393eac57747fabee1c2b743828ef8",
"b1d82fdb948b4c5bbee4d327a0f41a21",
"cccdb395613a4256950b7c3d740736fd",
"24c7bdd72f3546c882a7a7c78de5925f",
"db8a5ea365094bc4a87e77d059b4d0d0",
"2f494500c50a42f0ba3589743048cdd8",
"3ec4018cd5e54ba998a0f143f62407cc",
"f3a87c6d2986429cb40979782b38e712",
"4f7fb67e816b44598022407aacf71f19",
"be9935d016a34ac5a272b51261053f13",
"24540fc3ff1944edaa61e6037bec31c8",
"713338a99be84b54877f8e35c953d8ba",
"5586a425c639474ba5d6c0bd6d93328a",
"088d87f186cc4a5d95745d8317cca20e",
"acdecdef8bd14e44bcd36374b944b562",
"1c7c3bfb5ae4472c9bb6e340c012d302",
"41ae4c0601084403ba26a287f485ebeb",
"916e61f972f6439b8135a70100753917",
"36c3f462830247d7a219f1722cae8791",
"69ae06a22fa9488598ed89641cc135b6",
"c5ca864cc0144ddeb72dcbf1f8303609",
"728f786930a14c7a91cb4ff1f97a24ee",
"71704d8853ed40c4a55fa06669393ec9",
"af5c196783e349888eaefc227beadbf0",
"d3aee68f69ad4e5d81a087ec791cc9b1",
"1ec887eb8dac43ba9922e1f9f2111231",
"aa6b598305944d5ab2e2b4afaea8063c",
"a132d68b4ae94f64b80893b9149f7fd8",
"ec8f420a6f7d413bb528a1661aa3a0e8",
"b70265a81e9a49109c18eaad44135562",
"67a1b2e8e39b48849441368c33e16be4",
"e2ec06c317034b5681d83347b530362f",
"97bcd619eea74ed99650a1d8fed1f406",
"14bc6db53fa449049a6a63b422ee54bc",
"70f9cecf2dca4a3badc609b10ffcc8ec",
"cc082399aef94823b67d6e9c33d468e5",
"b4fb273306e941ebaa529e781361acfb"
]
},
"id": "30147f7c",
"outputId": "8b36524b-d22e-43f2-a6e0-cc4209d76736"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🦥 Unsloth: Will patch your computer to enable 2x faster free finetuning.\n",
"🦥 Unsloth Zoo will now patch everything to make training faster!\n",
"==((====))== Unsloth 2024.11.9: Fast Pixtral vision patching. Transformers = 4.46.2.\n",
" \\\\ /| GPU: Tesla T4. Max memory: 14.748 GB. Platform = Linux.\n",
"O^O/ \\_/ \\ Pytorch: 2.5.1+cu121. CUDA = 7.5. CUDA Toolkit = 12.1.\n",
"\\ / Bfloat16 = FALSE. FA [Xformers = 0.0.28.post3. FA2 = False]\n",
" \"-____-\" Free Apache license: http://github.com/unslothai/unsloth\n",
"Unsloth: Fast downloading is enabled - ignore downloading bars which are red colored!\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8a0ce0af1025429cb3cfcc5b973a4af0",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model.safetensors.index.json: 0%| | 0.00/316k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d401dcde88274752b4f0786f834527d9",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Downloading shards: 0%| | 0/2 [00:00<?, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "eb64d7acd375493098e1f7c30e7f2781",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model-00001-of-00002.safetensors: 0%| | 0.00/4.97G [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d4d3c9f1f54746d8895b66b6d2888ee2",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model-00002-of-00002.safetensors: 0%| | 0.00/3.57G [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b60b17cb67044a82b173f94d781d5174",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Loading checkpoint shards: 0%| | 0/2 [00:00<?, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8f1faff5468a46d4a725d095ae31ea3c",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"generation_config.json: 0%| | 0.00/133 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "1ef7d525ad2b4a57ae1118a0c3908b1a",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"processor_config.json: 0%| | 0.00/162 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "fe28321b0bf04f58b0d63e7dc617e3ed",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"chat_template.json: 0%| | 0.00/1.59k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ec91a47eece543a495f36ed0e051d637",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"preprocessor_config.json: 0%| | 0.00/483 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "db8a5ea365094bc4a87e77d059b4d0d0",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"tokenizer_config.json: 0%| | 0.00/177k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "1c7c3bfb5ae4472c9bb6e340c012d302",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"tokenizer.json: 0%| | 0.00/17.1M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "aa6b598305944d5ab2e2b4afaea8063c",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"special_tokens_map.json: 0%| | 0.00/552 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from unsloth import FastVisionModel # FastLanguageModel for LLMs\n",
"import torch\n",
"\n",
"# 4bit pre quantized models we support for 4x faster downloading + no OOMs.\n",
"fourbit_models = [\n",
" \"unsloth/Llama-3.2-11B-Vision-Instruct-bnb-4bit\", # Llama 3.2 vision support\n",
" \"unsloth/Llama-3.2-11B-Vision-bnb-4bit\",\n",
" \"unsloth/Llama-3.2-90B-Vision-Instruct-bnb-4bit\", # Can fit in a 80GB card!\n",
" \"unsloth/Llama-3.2-90B-Vision-bnb-4bit\",\n",
"\n",
" \"unsloth/Pixtral-12B-2409-bnb-4bit\", # Pixtral fits in 16GB!\n",
" \"unsloth/Pixtral-12B-Base-2409-bnb-4bit\", # Pixtral base model\n",
"\n",
" \"unsloth/Qwen2-VL-2B-Instruct-bnb-4bit\", # Qwen2 VL support\n",
" \"unsloth/Qwen2-VL-7B-Instruct-bnb-4bit\",\n",
" \"unsloth/Qwen2-VL-72B-Instruct-bnb-4bit\",\n",
"\n",
" \"unsloth/llava-v1.6-mistral-7b-hf-bnb-4bit\", # Any Llava variant works!\n",
" \"unsloth/llava-1.5-7b-hf-bnb-4bit\",\n",
"] # More models at https://huggingface.co/unsloth\n",
"\n",
"model, tokenizer = FastVisionModel.from_pretrained(\n",
" \"unsloth/Pixtral-12B-2409\",\n",
" load_in_4bit = True, # Use 4bit to reduce memory use. False for 16bit LoRA.\n",
" use_gradient_checkpointing = \"unsloth\", # True or \"unsloth\" for long context\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1c0cd2b0",
"metadata": {
"id": "1c0cd2b0"
},
"outputs": [],
"source": [
"model = FastVisionModel.get_peft_model(\n",
" model,\n",
" # We do NOT finetune vision & attention layers since Pixtral uses more memory!\n",
" finetune_vision_layers = True, # False if not finetuning vision layers\n",
" finetune_language_layers = True, # False if not finetuning language layers\n",
" finetune_attention_modules = False, # False if not finetuning attention layers\n",
" finetune_mlp_modules = True, # False if not finetuning MLP layers\n",
"\n",
" r = 8, # The larger, the higher the accuracy, but might overfit\n",
" lora_alpha = 8, # Recommended alpha == r at least\n",
" lora_dropout = 0,\n",
" bias = \"none\",\n",
" random_state = 3407,\n",
" use_rslora = False, # We support rank stabilized LoRA\n",
" loftq_config = None, # And LoftQ\n",
" # target_modules = \"all-linear\", # Optional now! Can specify a list if needed\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "440fa965",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 177,
"referenced_widgets": [
"453a07e03ee94f528890205d14511da6",
"309ebf7d588244a3ba28d29d56edbc2a",
"dcc1ef7862e240eebefd5985202ef3b2",
"0ef444f87c454640aa657c4c187e94f5",
"d291b920db4b48fb9f3e89bc916db8c8",
"3570f6aec06d461e9259a2bd60c6a16a",
"3ed61e45df71452f844c1f39ea5c9dcf",
"2b6b7fd9d5204198953a0f6fe8333d57",
"e74c5834491b46d5b065665533671407",
"fc9a5b89da594730a09a6bb4c3adb879",
"22b0b4a4585148b2b6f75ecd86ebded3",
"94a24760f2e3453aa615caf5300cd9da",
"52e83aca1e544ffaabc57d149dd0415e",
"b2e5c457d6a246cabcd71459cf2cee8d",
"b8b672b219c347c4a636c1a43f73fda9",
"76e1e2ae0a2944de8eff1c8eea325164",
"6795172d2bb54298ae68cb481cf84822",
"c09587db5ef3473490c1638c359ca945",
"58e75f4e6c3e4ca9a6e6bc6e9865de67",
"0fd6dae874a344678bac899cca709c3b",
"da76163d3abd4ab9b4a7d02efdb15f00",
"dc79ba710e9f4485a6f51d48963c6666",
"9f45d79473ef446ca8f81c08ec82edda",
"c381bddbbb6a4bbd99f90546dfb1867c",
"9ca49f19650848dfbade44d036e166d2",
"348f47ec75d44295b089a0071b747010",
"d7601975774c43e4af927247019c2dab",
"46513f9858a8403b93fc2fb1a0ea8779",
"3d378819a2084a7797e8e8debf9bf815",
"d2080299e24d40cbaecf75aead507415",
"7d64c5f1dac64a49b794e723a5c77620",
"08acfb1a242542d9990577d62118185f",
"6cdfb3c8a1bc45b1ad34dd77feb4d4fe",
"7856e0634b86431382280c591b6f740f",
"cac2e90d5e3449978089a9fe4690cd93",
"01838b1fb6da41e6bee2c632f9873b6e",
"12b8a9e56ff646d4ba7032405183daf3",
"2ef9f2c39bdf4893a4016e0880445e0f",
"d358e59f602245fc96651c018347c448",
"b7aeadfe764542e3ae4dd47e2664e410",
"10523b38a16b4a48b095860653d34a6c",
"ac9cb94447274626afc8580dd17260ad",
"c6bc57fe79f045fabe94281cbe1bd09a",
"05e888e211274b269794cde826c7d1f9",
"6b2c1870e4ae44aba0326535f75c6858",
"c3997e6823fb40349d9c92e32ce28045",
"a4cf715dfb534feb814d426c2cac2b8e",
"f57ddd4b011e428e82a86317d15779aa",
"be6e313fb0b045adb8d8da6702081a0d",
"dc07e208294f47d8b122afc8d415e3c8",
"c2d88ba605ab4c2ab3f9686c5b65b8e8",
"625723d424624ab2ac641b2c369da9e8",
"35f6d9677b67401699e094040eaf8bd2",
"ed9c8e6297654278bb360c13134920cb",
"39d1ac1f430544c087b69e3bdb6ab5d6"
]
},
"id": "440fa965",
"outputId": "54b0ee23-5573-407a-d22f-cda8378461da"
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "453a07e03ee94f528890205d14511da6",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"README.md: 0%| | 0.00/728 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "94a24760f2e3453aa615caf5300cd9da",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"train-00000-of-00001.parquet: 0%| | 0.00/357M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "9f45d79473ef446ca8f81c08ec82edda",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"test-00000-of-00001.parquet: 0%| | 0.00/57.6M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7856e0634b86431382280c591b6f740f",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Generating train split: 0%| | 0/8552 [00:00<?, ? examples/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "6b2c1870e4ae44aba0326535f75c6858",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Generating test split: 0%| | 0/1364 [00:00<?, ? examples/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from datasets import load_dataset\n",
"dataset = load_dataset(\"unsloth/llava-instruct-mix-vsft-mini\", split = \"train\")"
]
},
{
"cell_type": "markdown",
"id": "b9670b46",
"metadata": {
"id": "b9670b46"
},
"source": [
"## Output\n",
"This shows a basic output example of the vision-language model."
]
}
],
"metadata": {
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,616 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "a627af7f",
"metadata": {
"id": "a627af7f"
},
"source": [
"# Qwen2.5-VL (7B) Vision Model"
]
},
{
"cell_type": "markdown",
"id": "6ca9476a",
"metadata": {
"id": "6ca9476a"
},
"source": [
"## Description\n",
"This notebook demonstrates how to use the **Qwen2.5-VL (7B) Vision Model** vision-language model for image input and text generation tasks."
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Qwen2_5_VL_7B_Vision_Model.ipynb)"
],
"metadata": {
"id": "0G9UGDLJk8uV"
},
"id": "0G9UGDLJk8uV"
},
{
"cell_type": "markdown",
"id": "f467ebfe",
"metadata": {
"id": "f467ebfe"
},
"source": [
"## Dependencies\n",
"```python\n",
"!pip install transformers accelerate torch torchvision\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "ea76265d",
"metadata": {
"id": "ea76265d"
},
"source": [
"## Tools\n",
"- 🤗 Transformers\n",
"- PyTorch\n",
"- Vision Model APIs"
]
},
{
"cell_type": "markdown",
"id": "37c57a37",
"metadata": {
"id": "37c57a37"
},
"source": [
"## YAML Prompt\n",
"```yaml\n",
"mode: vision\n",
"model: Qwen2.5-VL (7B) Vision Model\n",
"tasks:\n",
" - image captioning\n",
" - visual question answering\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "7b02bc60",
"metadata": {
"id": "7b02bc60"
},
"source": [
"## Main\n",
"Below is the simplified main execution to load the model and run basic inference."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6c397c49",
"metadata": {
"id": "6c397c49"
},
"outputs": [],
"source": [
"%%capture\n",
"import os\n",
"if \"COLAB_\" not in \"\".join(os.environ.keys()):\n",
" !pip install unsloth\n",
"else:\n",
" # Do this only in Colab notebooks! Otherwise use pip install unsloth\n",
" !pip install --no-deps bitsandbytes accelerate xformers==0.0.29.post3 peft trl triton cut_cross_entropy unsloth_zoo\n",
" !pip install sentencepiece protobuf \"datasets>=3.4.1\" huggingface_hub hf_transfer\n",
" !pip install --no-deps unsloth"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "18b3d67c",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 513,
"referenced_widgets": [
"73fc3ac47de840cda7a07297153404d5",
"8c8b54f4d34a4b59a5a2513bbc082297",
"7bd2abffca3f4193afffd3f1a7c8ff8a",
"9ecdc7e0e9c247c59e9eab93455153b8",
"84f4e9f7ff6f433bbf13078e43ebbe2a",
"7475f8a404624b1b844d8148fabb493b",
"9d4aae9ebe594bd6875a5963eb6d77ed",
"62b6d78abada429393c499e0479eb56e",
"2aecce21a3a04971b4f5c9fd0b059738",
"2af66136423c41c6908c5a61c6fa2e5d",
"8bf92078d48448848402ede49b1b5182",
"78ae8aea29e04420bcfe616061934d98",
"e22b1706b6be49af8e31d2c512ccaaf6",
"71ac48ba667b4af291df3a33e7643c6c",
"7d16f0e5aaec4429a5b8d3c4878ea74a",
"a21de38381c241309bc798be604c3bf5",
"f26f1de0f3f34010ac0d37d6f3ed74b6",
"0af61827920e415daf64cfcb1685ee63",
"77a82cf2255b43e088812087af4d8ead",
"fad668efab014d28877087f38f3c034e",
"e764888263e54f0ba2f603992d678096",
"2dccbbbdfbf645b8b5896953f6e8a59b",
"45385885a26e42d0b1f52eda382fd6f4",
"ccb21e1b7fc14a6ab10689154ab2b94a",
"f5c7ab8d65c4418a943a51a401720f67",
"f6aaa74bce474abcbc9daf0515b6ffbd",
"76bd63e567e94650a82272ca6fd85011",
"d3cac12f194a40a187bbba68da36173c",
"30439a7bf22f416cbc01cfe87e433e1f",
"3265b3490b11426a8aa44d541981a296",
"78a31b91439c4c99a07f8f8d8dfb548f",
"d2a3a751ac2f491c9e7cb7a4092ab0b6",
"b652bb727c1148c4aac9ed751920e3ae",
"14e519d5e0834fd9a70a111140f8429a",
"41f3770e6d864c1794a1fa93feaf8605",
"6aa1670b808b42db894756b904243947",
"5757f1d68b8f4571a05486d846127b14",
"14cbf1b61170470bbb9d63e31d0ca310",
"3324ce12dc3e45fab9984eb83a92eb39",
"0ccabea3b39d4b148d420e26b53d3990",
"2d65a3b83b524eeaafde8e406e90198f",
"d179ef65b2b842d69548302c2f7a31be",
"2362fd437a134c30b147df947ee97128",
"7f22e31fc7174ff2bfa8bc2624d33dc7",
"643db314d8e94feeb9cd8747909eaabe",
"b80bb8f2cc92400aa34934978f9bc865",
"03f0c63c572249aabb7fb61272af1f1b",
"4113f045f9bc440b8dfaed5dfab14c1b",
"86a231a75d4a4586a53e4c7e74c63550",
"573653d0298246868e5d93069ca0fef5",
"c20a42f12c4545dfafdba22267e44d4b",
"4b74060c0bb44a35b847e6752b93e463",
"7e211233455342d48bd60f6d499b91f5",
"520ca077c6854e6fa1e019c0b209eae7",
"8f1fce549e494998b13f523bd793d300",
"bbb5e6a0a8b64d10802fbf3e89778306",
"0cef8128eeba4638bd268f9a1a364427",
"399cc918cec24db7b99af9e5f3c5adb4",
"3a611a2e00be4da6833172d928802fb9",
"0f2f303ae91349e29132055105fcbdec",
"17c08a96e04244a995e658eeb5a69699",
"9269dee0b0104b22b4043d3661f79350",
"a405cbc6d42d4f8f8be7c05f4e34128c",
"e702e948bb34481d995c75be223c4e16",
"c9949e2b99d14fa0bc4cfc88f42c2afb",
"48bbf9b662af47c5b99ebe24a6b70549",
"c1af10a57c0a40cf818d0974facdcc36",
"e4c1ff933c6e4ef49afbedffcdd99d5c",
"3caf3a6d48da403099bcdee89bda6949",
"7e0bbe2417e0420db1502390ba7c6c2d",
"5522658c84dc47a491f5deb08353b631",
"aecb331a01a44c9e92c74840faaf2616",
"caadc7751ff847b4a831dd6b2b53e60b",
"f0dd55c8f71a4f47a91a7018ab89d092",
"7a2d1ba8441e4a368a505c38d2c811ad",
"6657bbba902e43429224ed9c426389fe",
"a25ba73fb99448a3b46ac3571e2db0be",
"c2f518986b724620bbc67f7b6ede6d96",
"ed214eea73f54928af276883ddd53b5e",
"b241468a1d684fbb820baff6b9f9e362",
"0f7da532813445f1be01977cdec364ab",
"de7ac823a59d488995aa37bfbcec2e5b",
"fc5321766b8742ca97c4a839ba30d421",
"c4256f50e38e481083f3d366bfd91d3f",
"f7e4e90fb3fe4bbb85adb039404dd8e2",
"e0f8b5f130064bd69f4f3298e9536b5a",
"20956dab8f3e4f22830b4d9e56a5232a",
"4efe313f923c4ae585fb8a4353cecd97",
"3af59a3e9ac2430da201262fc54b5998",
"ad746cc40cdb461bba8cf04033d4afc5",
"3d09770f22854ca38213d4a64ace6df3",
"910df16ec7494eb68fb1f8ce95046414",
"080c7eed9cc0475980e85a530c91e616",
"e4fe961d149b461fb1d168d226c8aa1d",
"2a588c12d3814de495fa865a63629ba8",
"607a235508e54fdda0aef75311c7a213",
"383e14f14b0d4328a80e6b0283c421fa",
"913324d3476a4d04887d200f91afc553",
"4c0c6892c4f347deb4a85544664ff1e1",
"a863bb17b5984981bf9bd4ff93e438f4",
"b28286deba7c4152a8d2c21ea0d19402",
"fb9e17975b2349de81115173af6ac17a",
"f3b068de4fa6466e88970b73c868de0a",
"2127bee2928e43578b8b51e3c1fdfabf",
"a97f3d8c7bdf4292ae8ed133f059f635",
"67053bf18cd04347a0f2d2ff6134ae88",
"80e56300aee14b4386832aa1618c5d43",
"d096e33830754ea5b2e8f102548b805a",
"a913ea3370404f5f972754715889aced",
"35db2f7869f44aeab422409d27d5f7ec"
]
},
"id": "18b3d67c",
"outputId": "f0d7f72f-8166-439b-96da-ed7e30f8bdb3"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🦥 Unsloth: Will patch your computer to enable 2x faster free finetuning.\n",
"🦥 Unsloth Zoo will now patch everything to make training faster!\n",
"==((====))== Unsloth 2025.3.19: Fast Qwen2_5_Vl patching. Transformers: 4.50.0.\n",
" \\\\ /| Tesla T4. Num GPUs = 1. Max memory: 14.741 GB. Platform: Linux.\n",
"O^O/ \\_/ \\ Torch: 2.6.0+cu124. CUDA: 7.5. CUDA Toolkit: 12.4. Triton: 3.2.0\n",
"\\ / Bfloat16 = FALSE. FA [Xformers = 0.0.29.post3. FA2 = False]\n",
" \"-____-\" Free license: http://github.com/unslothai/unsloth\n",
"Unsloth: Fast downloading is enabled - ignore downloading bars which are red colored!\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "73fc3ac47de840cda7a07297153404d5",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model.safetensors: 0%| | 0.00/5.97G [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "78ae8aea29e04420bcfe616061934d98",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"generation_config.json: 0%| | 0.00/267 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "45385885a26e42d0b1f52eda382fd6f4",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"preprocessor_config.json: 0%| | 0.00/575 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Using a slow image processor as `use_fast` is unset and a slow processor was saved with this model. `use_fast=True` will be the default behavior in v4.50, even if the model was saved with a slow processor. This will result in minor differences in outputs. You'll still be able to use a slow processor with `use_fast=False`.\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "14e519d5e0834fd9a70a111140f8429a",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"tokenizer_config.json: 0%| | 0.00/7.33k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "643db314d8e94feeb9cd8747909eaabe",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"vocab.json: 0%| | 0.00/2.78M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "bbb5e6a0a8b64d10802fbf3e89778306",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"merges.txt: 0%| | 0.00/1.67M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "c1af10a57c0a40cf818d0974facdcc36",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"tokenizer.json: 0%| | 0.00/11.4M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "c2f518986b724620bbc67f7b6ede6d96",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"added_tokens.json: 0%| | 0.00/605 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "3af59a3e9ac2430da201262fc54b5998",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"special_tokens_map.json: 0%| | 0.00/614 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a863bb17b5984981bf9bd4ff93e438f4",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"chat_template.json: 0%| | 0.00/1.05k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from unsloth import FastVisionModel # FastLanguageModel for LLMs\n",
"import torch\n",
"\n",
"# 4bit pre quantized models we support for 4x faster downloading + no OOMs.\n",
"fourbit_models = [\n",
" \"unsloth/Llama-3.2-11B-Vision-Instruct-bnb-4bit\", # Llama 3.2 vision support\n",
" \"unsloth/Llama-3.2-11B-Vision-bnb-4bit\",\n",
" \"unsloth/Llama-3.2-90B-Vision-Instruct-bnb-4bit\", # Can fit in a 80GB card!\n",
" \"unsloth/Llama-3.2-90B-Vision-bnb-4bit\",\n",
"\n",
" \"unsloth/Pixtral-12B-2409-bnb-4bit\", # Pixtral fits in 16GB!\n",
" \"unsloth/Pixtral-12B-Base-2409-bnb-4bit\", # Pixtral base model\n",
"\n",
" \"unsloth/Qwen2-VL-2B-Instruct-bnb-4bit\", # Qwen2 VL support\n",
" \"unsloth/Qwen2-VL-7B-Instruct-bnb-4bit\",\n",
" \"unsloth/Qwen2-VL-72B-Instruct-bnb-4bit\",\n",
"\n",
" \"unsloth/llava-v1.6-mistral-7b-hf-bnb-4bit\", # Any Llava variant works!\n",
" \"unsloth/llava-1.5-7b-hf-bnb-4bit\",\n",
"] # More models at https://huggingface.co/unsloth\n",
"\n",
"model, tokenizer = FastVisionModel.from_pretrained(\n",
" \"unsloth/Qwen2.5-VL-7B-Instruct-bnb-4bit\",\n",
" load_in_4bit = True, # Use 4bit to reduce memory use. False for 16bit LoRA.\n",
" use_gradient_checkpointing = \"unsloth\", # True or \"unsloth\" for long context\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "45f1a7d8",
"metadata": {
"id": "45f1a7d8"
},
"outputs": [],
"source": [
"model = FastVisionModel.get_peft_model(\n",
" model,\n",
" finetune_vision_layers = True, # False if not finetuning vision layers\n",
" finetune_language_layers = True, # False if not finetuning language layers\n",
" finetune_attention_modules = True, # False if not finetuning attention layers\n",
" finetune_mlp_modules = True, # False if not finetuning MLP layers\n",
"\n",
" r = 16, # The larger, the higher the accuracy, but might overfit\n",
" lora_alpha = 16, # Recommended alpha == r at least\n",
" lora_dropout = 0,\n",
" bias = \"none\",\n",
" random_state = 3407,\n",
" use_rslora = False, # We support rank stabilized LoRA\n",
" loftq_config = None, # And LoftQ\n",
" # target_modules = \"all-linear\", # Optional now! Can specify a list if needed\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "915566b6",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 177,
"referenced_widgets": [
"5e4f3f4910d1477b924362c095a0cedd",
"b5a01de096fa4e2daf66e235bd5686bb",
"e9195f3a3e29475f941c302fe2a88a83",
"0d6f6fb66522436786728d8602e2f466",
"94b72e08764c486d8eed43a4557f1d98",
"8e8281a56a3d4879b6b376077890c920",
"630894e18b264f7dae8eddb17304a1cd",
"697fc92abb824cf4a9bc78709640ba54",
"eb6d552d6c1d4e82a521b29b36ae3db0",
"7572f2d06114442ba94fc22761a55346",
"c6dcd15e155949cbb9698e43e55b7a90",
"7365368b63d9425db5d4e5514e6e0586",
"5997909fc34645ce9a03d82ab0932766",
"ea4ebb90b708493c85fa81fecf4d60c0",
"227724312eb045a58616f63c3a5b7407",
"4f58e8a2ddbb4a73a2421ea37c68fea9",
"7e89e5546e394162b7b0f793478527ff",
"db9ea237050045d8861d76bb3b995753",
"3a484309bbe148abb2ef05452850728a",
"5e601d00c0094d999a5b37b9555c111c",
"e7bd6c674af541d08c0acb5e47579156",
"927147d620b0426cb46b49b6d8dc2ffc",
"4ebb36e479884847bcef5736e276dfb9",
"7b5a059a8ef84817851d109fd7e3a7b5",
"0e949ae97d544d65af09cebe63041b8e",
"c817a779a9ff4a848391a7c7dff1e4ca",
"abae462b98c84006b71d4a62c8a47d5a",
"dc1a755aae6c44849d818fd96c046649",
"2650d2ce196e404a98cbfac96d0a9bef",
"36d579fdc2fb4c59b827f5bf7a92abd4",
"fccec1c2a389401eb614f5f1cfb15f0c",
"7b4d303966274c71b50312df12e7b87a",
"ce4bb2dffcf84ae9bf1f8ac86b2d768e",
"639b886f72e24951909e4ffb6cfa247d",
"7b13cf1727a04f5ca6de1f7eb536d800",
"631ce764f4684225a3c1e4455717a555",
"48af93dada914d8b88d5ffffd24ac666",
"4bd339c9d3ee43f39678d2c18baeef53",
"b1b12b8def994e748b08b27abcef4b87",
"bc38022049ce47628d8c215959c38b91",
"331d5d2bc67f44f283fc82481cb60411",
"0a5ad3bd338b4e6ea94a11a199d2f5ba",
"5c41f695158641f485349c20a1405cfd",
"89bc17f1911a43cca7196da232500fd6",
"f5629e8c82c848218f69810e1b21b0e4",
"5244452af0734f3183a7384435f9e1fe",
"69f645decfb64baca11cfbdb9773a458",
"d1788fabe3e34f6eb60fecab3c7490ba",
"8f423066ba8f421495f934a269053cc1",
"569d1435402e4533b0427a4b191b6754",
"b834a7ab12544f9b8305f5728677e921",
"e72ac7c9b7824c81a6e77e6fadad9f9c",
"828ad6e5fcfb44b3b4559ec5682d095d",
"dac611678f4949ae98051bdc975e083f",
"0a21bae13a3c46509db70dbe8e9de5eb"
]
},
"id": "915566b6",
"outputId": "ece64855-55d4-4011-c5b8-33a9bb622734"
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5e4f3f4910d1477b924362c095a0cedd",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"README.md: 0%| | 0.00/519 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7365368b63d9425db5d4e5514e6e0586",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"train-00000-of-00001.parquet: 0%| | 0.00/344M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "4ebb36e479884847bcef5736e276dfb9",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"test-00000-of-00001.parquet: 0%| | 0.00/38.2M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "639b886f72e24951909e4ffb6cfa247d",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Generating train split: 0%| | 0/68686 [00:00<?, ? examples/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f5629e8c82c848218f69810e1b21b0e4",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Generating test split: 0%| | 0/7632 [00:00<?, ? examples/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from datasets import load_dataset\n",
"dataset = load_dataset(\"unsloth/LaTeX_OCR\", split = \"train\")"
]
},
{
"cell_type": "markdown",
"id": "6193435d",
"metadata": {
"id": "6193435d"
},
"source": [
"## Output\n",
"This shows a basic output example of the vision-language model."
]
}
],
"metadata": {
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-146
View File
@@ -1,146 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "a050dfc0",
"metadata": {
"id": "a050dfc0"
},
"source": [
"# Sesame CSM (1B) - Text to Speech"
]
},
{
"cell_type": "markdown",
"id": "7c2c61ec",
"metadata": {
"id": "7c2c61ec"
},
"source": [
"This notebook showcases how to generate speech from text using the Sesame CSM 1B model. This is ideal for converting instructional or conversational content into natural audio output."
]
},
{
"cell_type": "markdown",
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Sesame_CSM_1B_TTS.ipynb)\n"
],
"metadata": {
"id": "5SA94wTb9AH-"
},
"id": "5SA94wTb9AH-"
},
{
"cell_type": "markdown",
"id": "ab27fd8d",
"metadata": {
"id": "ab27fd8d"
},
"source": [
"## 🧩 Dependencies"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ac3a627f",
"metadata": {
"id": "ac3a627f"
},
"outputs": [],
"source": [
"!pip install -q transformers\n",
"!pip install -q torchaudio\n",
"!pip install -q soundfile"
]
},
{
"cell_type": "markdown",
"id": "a382e4d0",
"metadata": {
"id": "a382e4d0"
},
"source": [
"## 🛠️ Tools\n",
"- transformers for loading the model\n",
"- torchaudio for audio processing\n",
"- soundfile for playback"
]
},
{
"cell_type": "markdown",
"id": "7ff6eb6d",
"metadata": {
"id": "7ff6eb6d"
},
"source": [
"## 🧾 YAML Prompt\n",
"```yaml\n",
"task: \"Text to Speech\"\n",
"style: \"Clear, educational\"\n",
"language: \"en\"\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "0ab9cda8",
"metadata": {
"id": "0ab9cda8"
},
"source": [
"## 🧠 Main"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6459f8bd",
"metadata": {
"id": "6459f8bd"
},
"outputs": [],
"source": [
"from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq\n",
"import torchaudio\n",
"import soundfile as sf\n",
"import torch\n",
"\n",
"processor = AutoProcessor.from_pretrained(\"m-a-p/Sesame-CM\")\n",
"model = AutoModelForSpeechSeq2Seq.from_pretrained(\"m-a-p/Sesame-CM\")\n",
"model = model.to(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
"\n",
"text = \"Welcome to the world of voice synthesis using open models!\"\n",
"inputs = processor(text, return_tensors=\"pt\").to(model.device)\n",
"with torch.no_grad():\n",
" outputs = model.generate(**inputs)\n",
"speech = processor.batch_decode(outputs, return_tensors=\"pt\")[0]\n",
"\n",
"sf.write(\"output.wav\", speech.numpy(), 16000)"
]
},
{
"cell_type": "markdown",
"id": "376fe112",
"metadata": {
"id": "376fe112"
},
"source": [
"## 📤 Output\n",
"🖼️ Output Preview (Text Summary):\n",
"\n",
"Prompt: A clear educational text is converted to a .wav file.\n",
"\n",
"🎧 The output audio will say: 'Welcome to the world of voice synthesis using open models!'\n",
"This demonstrates how Sesame-CM can be used for building TTS applications easily."
]
}
],
"metadata": {
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+1 -33
View File
@@ -6,19 +6,11 @@
"id": "IY0bHc5lF46I"
},
"source": [
"# \ud83e\udd16 Qwen Model Agent\n",
"This notebook runs a chatbot agent using the `Qwen/Qwen1.5-1.8B` model via the `transformers` library in Google Colab.\n",
"\n",
"\u2705 Lightweight model (1.8B) so it runs on Colab Free.\n",
"\u2699\ufe0f No extra setup needed beyond `transformers` and `torch`.\n",
=======
"# 🤖 Qwen Model Agent\n",
"This notebook runs a chatbot agent using the `Qwen/Qwen1.5-1.8B` model via the `transformers` library in Google Colab.\n",
"\n",
"✅ Lightweight model (1.8B) so it runs on Colab Free.\n",
"⚙️ No extra setup needed beyond `transformers` and `torch`.\n",
"---"
],
"id": "IY0bHc5lF46I"
@@ -58,18 +50,6 @@
"output_type": "stream",
"name": "stdout",
"text": [
"\u001b[2K \u001b[90m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u001b[0m \u001b[32m363.4/363.4 MB\u001b[0m \u001b[31m2.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u001b[0m \u001b[32m13.8/13.8 MB\u001b[0m \u001b[31m36.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u001b[0m \u001b[32m24.6/24.6 MB\u001b[0m \u001b[31m31.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u001b[0m \u001b[32m883.7/883.7 kB\u001b[0m \u001b[31m23.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u001b[0m \u001b[32m664.8/664.8 MB\u001b[0m \u001b[31m1.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u001b[0m \u001b[32m211.5/211.5 MB\u001b[0m \u001b[31m2.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u001b[0m \u001b[32m56.3/56.3 MB\u001b[0m \u001b[31m15.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u001b[0m \u001b[32m127.9/127.9 MB\u001b[0m \u001b[31m7.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u001b[0m \u001b[32m207.5/207.5 MB\u001b[0m \u001b[31m4.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u001b[0m \u001b[32m21.1/21.1 MB\u001b[0m \u001b[31m81.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
=======
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m363.4/363.4 MB\u001b[0m \u001b[31m2.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.8/13.8 MB\u001b[0m \u001b[31m36.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m24.6/24.6 MB\u001b[0m \u001b[31m31.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
@@ -80,7 +60,6 @@
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m127.9/127.9 MB\u001b[0m \u001b[31m7.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m207.5/207.5 MB\u001b[0m \u001b[31m4.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m21.1/21.1 MB\u001b[0m \u001b[31m81.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25h"
]
}
@@ -94,11 +73,7 @@
{
"cell_type": "markdown",
"source": [
"# \u2705 Use the official BERT Large model"
=======
"# ✅ Use the official BERT Large model"
],
"metadata": {
"id": "PvTxUutEce5s"
@@ -349,8 +324,6 @@
},
"colab": {
"provenance": []
=======
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
@@ -2065,13 +2038,8 @@
}
}
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}
=======
}
}
@@ -269,7 +269,7 @@ async def generate_market_research_report(job_id: str, config: MarketResearchCon
workflow = PraisonAIAgents(
agents=list(agents.values()),
tasks=tasks,
process="sequential",
process="workflow",
verbose=False
)
@@ -296,92 +296,14 @@ async def generate_market_research_report(job_id: str, config: MarketResearchCon
"research_findings": {}
}
# Extract results from each task with comprehensive logging
print(f"DEBUG: Raw results type: {type(results)}")
print(f"DEBUG: Raw results content: {results}")
if isinstance(results, str):
# Sequential process returns a string result directly
print("DEBUG: Sequential process returned string result")
report_data["research_findings"]["synthesis_report"] = {
"content": results,
"agent": "Research Report Synthesizer",
"section": "Complete Market Research Report"
}
print(f"DEBUG: Added synthesis_report with content length: {len(results)}")
elif isinstance(results, dict):
print(f"DEBUG: Results is dict with keys: {list(results.keys())}")
if "task_results" in results:
print(f"DEBUG: Found task_results: {results['task_results']}")
print(f"DEBUG: task_results type: {type(results['task_results'])}")
for task_name, result in results["task_results"].items():
print(f"DEBUG: Processing task '{task_name}', result type: {type(result)}")
print(f"DEBUG: Result content: {result}")
if result:
# Try multiple ways to extract content
content = None
agent_name = "Unknown"
if hasattr(result, 'raw'):
content = result.raw
print(f"DEBUG: Extracted content from result.raw")
elif hasattr(result, 'content'):
content = result.content
print(f"DEBUG: Extracted content from result.content")
elif isinstance(result, str):
content = result
print(f"DEBUG: Result is string, using directly")
else:
content = str(result)
print(f"DEBUG: Converting result to string")
if hasattr(result, 'agent'):
agent_name = result.agent
elif hasattr(result, 'agent_name'):
agent_name = result.agent_name
if content:
report_data["research_findings"][task_name] = {
"content": content,
"agent": agent_name,
"section": f"Task {task_name}"
}
print(f"DEBUG: Added task '{task_name}' with content length: {len(str(content))}")
else:
print(f"DEBUG: No content found for task '{task_name}'")
else:
print(f"DEBUG: Task '{task_name}' result is None or empty")
else:
print("DEBUG: No 'task_results' found in results dict")
# Try to use the whole results as content
report_data["research_findings"]["workflow_output"] = {
"content": str(results),
"agent": "PraisonAI Workflow",
"section": "Complete Workflow Output"
}
print("DEBUG: Added entire results as workflow_output")
else:
print(f"DEBUG: Unexpected results type: {type(results)}")
report_data["research_findings"]["raw_output"] = {
"content": str(results),
"agent": "Unknown",
"section": "Raw Output"
}
print(f"DEBUG: Final research_findings keys: {list(report_data['research_findings'].keys())}")
print(f"DEBUG: Final research_findings count: {len(report_data['research_findings'])}")
# Generate executive summary from synthesis if available
if "synthesis_report" in report_data["research_findings"]:
content = report_data["research_findings"]["synthesis_report"]["content"]
# Extract first few sentences as executive summary
sentences = content.split('. ')[:3]
report_data["executive_summary"] = '. '.join(sentences) + '.' if sentences else "Market research analysis completed."
print("DEBUG: Generated executive summary from synthesis report")
# Extract results from each task
if "task_results" in results:
for task_name, result in results["task_results"].items():
if result:
report_data["research_findings"][task_name] = {
"content": result.raw,
"agent": result.agent if hasattr(result, 'agent') else "Unknown"
}
# Save report to file
report_filename = f"market_research_{job_id}.json"
+19 -101
View File
@@ -549,7 +549,6 @@ class LLM:
})
should_continue = False
tool_results = [] # Store all tool results
for tool_call in tool_calls:
# Handle both object and dict access patterns
if isinstance(tool_call, dict):
@@ -570,7 +569,6 @@ class LLM:
logging.debug(f"[TOOL_EXEC_DEBUG] About to execute tool {function_name} with args: {arguments}")
tool_result = execute_tool_fn(function_name, arguments)
logging.debug(f"[TOOL_EXEC_DEBUG] Tool execution result: {tool_result}")
tool_results.append(tool_result) # Store the result
if verbose:
display_message = f"Agent {agent_name} called function '{function_name}' with arguments: {arguments}\n"
@@ -603,8 +601,7 @@ class LLM:
# If we reach here, no more tool calls needed - get final response
# Make one more call to get the final summary response
# Special handling for Ollama models that don't automatically process tool results
ollama_handled = False
if self.model and self.model.startswith("ollama/") and tool_results:
if self.model and self.model.startswith("ollama/") and tool_result:
# For Ollama models, we need to explicitly ask the model to process the tool results
# First, check if the response is just a JSON tool call
try:
@@ -617,30 +614,13 @@ class LLM:
# Create a prompt that asks the model to process the tool results based on original context
# Extract the original user query from messages
original_query = ""
for msg in reversed(messages): # Look from the end to find the most recent user message
for msg in messages:
if msg.get("role") == "user":
content = msg.get("content", "")
# Handle list content (multimodal)
if isinstance(content, list):
for item in content:
if isinstance(item, dict) and item.get("type") == "text":
original_query = item.get("text", "")
break
else:
original_query = content
if original_query:
break
original_query = msg.get("content", "")
break
# Create a shorter follow-up prompt with all tool results
# If there's only one result, use it directly; otherwise combine them
if len(tool_results) == 1:
results_text = json.dumps(tool_results[0], indent=2)
else:
results_text = json.dumps(tool_results, indent=2)
follow_up_prompt = f"Results:\n{results_text}\nProvide Answer to this Original Question based on the above results: '{original_query}'"
logging.debug(f"[OLLAMA_DEBUG] Original query extracted: {original_query}")
logging.debug(f"[OLLAMA_DEBUG] Follow-up prompt: {follow_up_prompt[:200]}...")
# Create a shorter follow-up prompt
follow_up_prompt = f"Results:\n{json.dumps(tool_result, indent=2)}\nProvide Answer to this Original Question based on the above results: '{original_query}'"
# Make a follow-up call to process the results
follow_up_messages = [
@@ -673,33 +653,12 @@ class LLM:
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
response_text += chunk.choices[0].delta.content
# Set flag to indicate Ollama was handled
ollama_handled = True
final_response_text = response_text.strip()
logging.debug(f"[OLLAMA_DEBUG] Ollama follow-up response: {final_response_text[:200]}...")
# Display the response if we got one
if final_response_text and verbose:
display_interaction(
original_prompt,
final_response_text,
markdown=markdown,
generation_time=time.time() - start_time,
console=console
)
# Return the final response after processing Ollama's follow-up
if final_response_text:
return final_response_text
else:
logging.warning("[OLLAMA_DEBUG] Ollama follow-up returned empty response")
except (json.JSONDecodeError, KeyError):
# Not a JSON response or not a tool call format, continue normally
pass
# If reasoning_steps is True and we haven't handled Ollama already, do a single non-streaming call
if reasoning_steps and not ollama_handled:
# If reasoning_steps is True, do a single non-streaming call
elif reasoning_steps:
resp = litellm.completion(
**self._build_completion_params(
messages=messages,
@@ -729,8 +688,8 @@ class LLM:
console=console
)
# Otherwise do the existing streaming approach if not already handled
elif not ollama_handled:
# Otherwise do the existing streaming approach
else:
# Get response after tool calls with streaming
if verbose:
with Live(display_generating("", current_time), console=console, refresh_per_second=4) as live:
@@ -1266,7 +1225,6 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
"tool_calls": serializable_tool_calls
})
tool_results = [] # Store all tool results
for tool_call in tool_calls:
# Handle both object and dict access patterns
if isinstance(tool_call, dict):
@@ -1285,7 +1243,6 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
tool_call_id = f"tool_{id(tool_call)}"
tool_result = await execute_tool_fn(function_name, arguments)
tool_results.append(tool_result) # Store the result
if verbose:
display_message = f"Agent {agent_name} called function '{function_name}' with arguments: {arguments}\n"
@@ -1304,8 +1261,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
response_text = ""
# Special handling for Ollama models that don't automatically process tool results
ollama_handled = False
if self._is_ollama_provider() and tool_results:
if self._is_ollama_provider() and tool_result:
# For Ollama models, we need to explicitly ask the model to process the tool results
# First, check if the response is just a JSON tool call
try:
@@ -1318,30 +1274,13 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
# Create a prompt that asks the model to process the tool results based on original context
# Extract the original user query from messages
original_query = ""
for msg in reversed(messages): # Look from the end to find the most recent user message
for msg in messages:
if msg.get("role") == "user":
content = msg.get("content", "")
# Handle list content (multimodal)
if isinstance(content, list):
for item in content:
if isinstance(item, dict) and item.get("type") == "text":
original_query = item.get("text", "")
break
else:
original_query = content
if original_query:
break
original_query = msg.get("content", "")
break
# Create a shorter follow-up prompt with all tool results
# If there's only one result, use it directly; otherwise combine them
if len(tool_results) == 1:
results_text = json.dumps(tool_results[0], indent=2)
else:
results_text = json.dumps(tool_results, indent=2)
follow_up_prompt = f"Results:\n{results_text}\nProvide Answer to this Original Question based on the above results: '{original_query}'"
logging.debug(f"[OLLAMA_DEBUG] Original query extracted: {original_query}")
logging.debug(f"[OLLAMA_DEBUG] Follow-up prompt: {follow_up_prompt[:200]}...")
# Create a shorter follow-up prompt
follow_up_prompt = f"Results:\n{json.dumps(tool_result, indent=2)}\nProvide Answer to this Original Question based on the above results: '{original_query}'"
# Make a follow-up call to process the results
follow_up_messages = [
@@ -1374,33 +1313,12 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
):
if chunk and chunk.choices and chunk.choices[0].delta.content:
response_text += chunk.choices[0].delta.content
# Set flag to indicate Ollama was handled
ollama_handled = True
final_response_text = response_text.strip()
logging.debug(f"[OLLAMA_DEBUG] Ollama follow-up response: {final_response_text[:200]}...")
# Display the response if we got one
if final_response_text and verbose:
display_interaction(
original_prompt,
final_response_text,
markdown=markdown,
generation_time=time.time() - start_time,
console=console
)
# Return the final response after processing Ollama's follow-up
if final_response_text:
return final_response_text
else:
logging.warning("[OLLAMA_DEBUG] Ollama follow-up returned empty response")
except (json.JSONDecodeError, KeyError):
# Not a JSON response or not a tool call format, continue normally
pass
# If no special handling was needed or if it's not an Ollama model
if reasoning_steps and not ollama_handled:
elif reasoning_steps:
# Non-streaming call to capture reasoning
resp = await litellm.acompletion(
**self._build_completion_params(
@@ -1430,8 +1348,8 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
generation_time=time.time() - start_time,
console=console
)
elif not ollama_handled:
# Get response after tool calls with streaming if not already handled
else:
# Get response after tool calls with streaming
if verbose:
async for chunk in await litellm.acompletion(
**self._build_completion_params(
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "praisonaiagents"
version = "0.0.107"
version = "0.0.106"
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
requires-python = ">=3.10"
authors = [
+25 -28
View File
@@ -1,36 +1,33 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from praisonaiagents.tools import (
read_file, write_file, list_files, get_file_info,
copy_file, move_file, delete_file
import os
from dotenv import load_dotenv
load_dotenv()
llm_config = {
"model": "openai/gpt-4o-mini",
"api_key": os.getenv('OPENAI_API_KEY'),
"temperature": 0.7,
"max_tokens": 2000
}
blog_agent = Agent(
role="Blog Writer",
goal="Write a blog post about AI",
backstory="Expert at writing blog posts",
llm=llm_config,
)
# Get user input
d = input("Demande: ")
# Create file manager agent
file_manager_agent = Agent(
name="FileManager",
tools=[read_file, write_file, list_files, get_file_info,
copy_file, move_file, delete_file],
llm={
"model": "ollama/llama3.2",
"base_url": "http://localhost:11434" # Ollama default
}
blog_task = Task(
description="Write a blog post about AI trends in 1 paragraph",
expected_output="Well-written blog post about AI trends",
agent=blog_agent
)
# Dynamically create a task based on input
file_task = Task(
name="Q",
description=f"faire '{d}'.",
expected_output=f"'{d}' bien fait.",
agent=file_manager_agent
)
# Run agent with the task
agents = PraisonAIAgents(
agents=[file_manager_agent],
tasks=[file_task],
process="sequential"
agents=[blog_agent],
tasks=[blog_task],
memory=False
)
agents.start()
result = agents.start()
@@ -1,161 +0,0 @@
#!/usr/bin/env python3
"""
Test script to verify Ollama empty response fix for both sync and async methods.
"""
import asyncio
import logging
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
from typing import Dict, Any
# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
# Define a simple tool for testing
def search_tool(query: str) -> Dict[str, Any]:
"""Simulate a search tool that returns results."""
logging.debug(f"[TEST] Search tool called with query: {query}")
results = {
"results": [
{"title": "Result 1", "description": f"Information about {query}"},
{"title": "Result 2", "description": f"More details on {query}"}
],
"total": 2
}
logging.debug(f"[TEST] Search tool returning: {results}")
return results
# Test with both sync and async workflows
async def test_model_async(model_name: str):
print(f"\n{'='*60}")
print(f"Testing ASYNC with model: {model_name}")
print('='*60)
# Create agent with the search tool
agent = Agent(
name="SearchAgent",
role="Information Researcher",
goal="Search for information and provide helpful answers",
backstory="You are an expert at finding and summarizing information.",
llm=model_name,
tools=[search_tool],
verbose=True
)
# Create a task that requires tool usage
task = Task(
name="search_task",
description="Search for information about 'Python programming' and provide a summary of what you found.",
expected_output="A clear summary of the search results",
agent=agent
)
# Create and run the workflow
workflow = PraisonAIAgents(
agents=[agent],
tasks=[task],
verbose=True
)
try:
result = await workflow.astart() # Use async start
print(f"\n{'='*60}")
print(f"ASYNC RESULT for {model_name}:")
print('='*60)
print(result)
# Check if result is empty
if not result or (isinstance(result, dict) and not result.get('task_results', {}).get('search_task', {}).get('output')):
print(f"\n❌ ERROR: Empty response from {model_name} (async)")
return False
else:
print(f"\n✅ SUCCESS: Got valid response from {model_name} (async)")
return True
except Exception as e:
print(f"\n❌ ERROR with {model_name} (async): {e}")
import traceback
traceback.print_exc()
return False
def test_model_sync(model_name: str):
print(f"\n{'='*60}")
print(f"Testing SYNC with model: {model_name}")
print('='*60)
# Create agent with the search tool
agent = Agent(
name="SearchAgent",
role="Information Researcher",
goal="Search for information and provide helpful answers",
backstory="You are an expert at finding and summarizing information.",
llm=model_name,
tools=[search_tool],
verbose=True
)
# Create a task that requires tool usage
task = Task(
name="search_task",
description="Search for information about 'Python programming' and provide a summary of what you found.",
expected_output="A clear summary of the search results",
agent=agent
)
# Create and run the workflow
workflow = PraisonAIAgents(
agents=[agent],
tasks=[task],
verbose=True
)
try:
result = workflow.start() # Use sync start
print(f"\n{'='*60}")
print(f"SYNC RESULT for {model_name}:")
print('='*60)
print(result)
# Check if result is empty
if not result or (isinstance(result, dict) and not result.get('task_results', {}).get('search_task', {}).get('output')):
print(f"\n❌ ERROR: Empty response from {model_name} (sync)")
return False
else:
print(f"\n✅ SUCCESS: Got valid response from {model_name} (sync)")
return True
except Exception as e:
print(f"\n❌ ERROR with {model_name} (sync): {e}")
import traceback
traceback.print_exc()
return False
async def main():
print("Testing Ollama empty response fix for both sync and async...")
# Test sync methods
print("\n1. Testing SYNC methods:")
openai_sync_success = test_model_sync("openai/gpt-4o-mini")
ollama_sync_success = test_model_sync("ollama/llama3.2")
# Test async methods
print("\n2. Testing ASYNC methods:")
openai_async_success = await test_model_async("openai/gpt-4o-mini")
ollama_async_success = await test_model_async("ollama/llama3.2")
# Summary
print(f"\n{'='*60}")
print("TEST SUMMARY:")
print('='*60)
print(f"OpenAI sync test: {'✅ PASSED' if openai_sync_success else '❌ FAILED'}")
print(f"Ollama sync test: {'✅ PASSED' if ollama_sync_success else '❌ FAILED'}")
print(f"OpenAI async test: {'✅ PASSED' if openai_async_success else '❌ FAILED'}")
print(f"Ollama async test: {'✅ PASSED' if ollama_async_success else '❌ FAILED'}")
if ollama_sync_success and ollama_async_success:
print("\n🎉 Ollama empty response issue has been fixed for both sync and async!")
else:
print("\n⚠️ Ollama empty response issue still exists in some cases.")
if __name__ == "__main__":
asyncio.run(main())
@@ -1,101 +0,0 @@
#!/usr/bin/env python3
"""
Test script to verify Ollama empty response fix.
"""
import logging
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
from typing import Dict, Any
# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
# Define a simple tool for testing
def search_tool(query: str) -> Dict[str, Any]:
"""Simulate a search tool that returns results."""
logging.debug(f"[TEST] Search tool called with query: {query}")
results = {
"results": [
{"title": "Result 1", "description": f"Information about {query}"},
{"title": "Result 2", "description": f"More details on {query}"}
],
"total": 2
}
logging.debug(f"[TEST] Search tool returning: {results}")
return results
# Test with both OpenAI and Ollama models
def test_model(model_name: str):
print(f"\n{'='*60}")
print(f"Testing with model: {model_name}")
print('='*60)
# Create agent with the search tool
agent = Agent(
name="SearchAgent",
role="Information Researcher",
goal="Search for information and provide helpful answers",
backstory="You are an expert at finding and summarizing information.",
llm=model_name,
tools=[search_tool],
verbose=True
)
# Create a task that requires tool usage
task = Task(
name="search_task",
description="Search for information about 'Python programming' and provide a summary of what you found.",
expected_output="A clear summary of the search results",
agent=agent
)
# Create and run the workflow
workflow = PraisonAIAgents(
agents=[agent],
tasks=[task],
verbose=True
)
try:
result = workflow.start()
print(f"\n{'='*60}")
print(f"FINAL RESULT for {model_name}:")
print('='*60)
print(result)
# Check if result is empty
if not result or (isinstance(result, dict) and not result.get('task_results', {}).get('search_task', {}).get('output')):
print(f"\n❌ ERROR: Empty response from {model_name}")
return False
else:
print(f"\n✅ SUCCESS: Got valid response from {model_name}")
return True
except Exception as e:
print(f"\n❌ ERROR with {model_name}: {e}")
import traceback
traceback.print_exc()
return False
if __name__ == "__main__":
print("Testing Ollama empty response fix...")
# Test with OpenAI first (as baseline)
print("\n1. Testing with OpenAI (baseline):")
openai_success = test_model("openai/gpt-4o-mini")
# Test with Ollama
print("\n2. Testing with Ollama:")
ollama_success = test_model("ollama/llama3.2")
# Summary
print(f"\n{'='*60}")
print("TEST SUMMARY:")
print('='*60)
print(f"OpenAI test: {'✅ PASSED' if openai_success else '❌ FAILED'}")
print(f"Ollama test: {'✅ PASSED' if ollama_success else '❌ FAILED'}")
if ollama_success:
print("\n🎉 Ollama empty response issue has been fixed!")
else:
print("\n⚠️ Ollama empty response issue still exists.")
+2050 -2052
View File
File diff suppressed because it is too large. Load diff
-107
View File
@@ -1,107 +0,0 @@
#!/usr/bin/env python
from mcp.server.fastmcp import FastMCP
import logging
import datetime
from typing import Dict, List, Union
# Set up logging
logging.basicConfig(level=logging.INFO, filename="weather_server.log")
logger = logging.getLogger("weather-server")
# Initialize FastMCP server for weather tools
mcp = FastMCP("weather-tools")
# Mock weather data for cities
MOCK_WEATHER_DATA = {
"london": {
"temp": 15,
"feels_like": 13,
"temp_min": 12,
"temp_max": 17,
"humidity": 76,
"description": "Cloudy with occasional rain",
"wind_speed": 12,
"country": "GB"
},
"paris": {
"temp": 18,
"feels_like": 17,
"temp_min": 16,
"temp_max": 20,
"humidity": 65,
"description": "Partly cloudy",
"wind_speed": 8,
"country": "FR"
},
"new york": {
"temp": 22,
"feels_like": 24,
"temp_min": 20,
"temp_max": 25,
"humidity": 58,
"description": "Clear sky",
"wind_speed": 10,
"country": "US"
},
"tokyo": {
"temp": 26,
"feels_like": 28,
"temp_min": 24,
"temp_max": 29,
"humidity": 72,
"description": "Humid and warm",
"wind_speed": 7,
"country": "JP"
},
"sydney": {
"temp": 20,
"feels_like": 19,
"temp_min": 17,
"temp_max": 23,
"humidity": 60,
"description": "Sunny with light breeze",
"wind_speed": 15,
"country": "AU"
}
}
@mcp.tool()
def get_weather(location: Union[str, List[str]]) -> Dict:
"""Get current weather data for one or more locations.
Args:
location: City name (str) or list of city names (List[str]) to get weather for
Returns:
Dict with weather data for each location or error message
"""
def get_single_location_weather(loc: str) -> Dict:
"""Helper function to get weather for a single location"""
loc = loc.lower().strip()
if loc in MOCK_WEATHER_DATA:
weather_data = MOCK_WEATHER_DATA[loc].copy()
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
weather_data["time"] = current_time
weather_data["city"] = loc.title()
return weather_data
return {"city": loc.title(), "error": "Location not found in weather database"}
logger.info(f"Getting weather data for {location}")
# Handle list of locations
if isinstance(location, list):
results = {}
for loc in location:
if isinstance(loc, str):
results[loc] = get_single_location_weather(loc)
return {"results": results}
# Handle single location
if isinstance(location, str):
return get_single_location_weather(location)
return {"error": "Invalid location format. Please provide a string or list of strings."}
if __name__ == "__main__":
# Run the MCP server
mcp.run()
+13 -3
View File
@@ -1,6 +1,16 @@
OPENAI_MODEL_NAME="gpt-4o"
# OpenAI / compatible API
OPENAI_API_KEY="Enter your API key"
OPENAI_MODEL_NAME="gpt-4o"
OPENAI_API_BASE="https://api.openai.com/v1"
# AG2 framework (uses same OPENAI_* vars above, or override below)
# MODEL_NAME=gpt-4o-mini
# AWS Bedrock (for ag2_bedrock.yaml example)
# AWS_DEFAULT_REGION=us-east-1
# AWS_ACCESS_KEY_ID=your-access-key
# AWS_SECRET_ACCESS_KEY=your-secret-key
# Chainlit (optional)
CHAINLIT_USERNAME=admin
CHAINLIT_USERNAME=admin
CHAINLIT_AUTH_SECRET="chainlit create-secret to create"
CHAINLIT_AUTH_SECRET="chainlit create-secret to create"
+2 -2
View File
@@ -3,8 +3,8 @@ class Praisonai < Formula
desc "AI tools for various AI applications"
homepage "https://github.com/MervinPraison/PraisonAI"
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.34.tar.gz"
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.34.tar.gz | shasum -a 256`.split.first
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.33.tar.gz"
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.33.tar.gz | shasum -a 256`.split.first
license "MIT"
depends_on "[email protected]"
+164 -2
View File
@@ -41,6 +41,16 @@ try:
except ImportError:
pass
AG2_AVAILABLE = False
try:
import importlib.metadata as _importlib_metadata
_importlib_metadata.distribution('ag2')
from autogen import LLMConfig as _AG2LLMConfig # noqa: F401 — AG2-exclusive class
AG2_AVAILABLE = True
del _AG2LLMConfig, _importlib_metadata
except Exception:
pass
try:
import agentops
AGENTOPS_AVAILABLE = True
@@ -51,7 +61,7 @@ except ImportError:
pass
# Only try to import praisonai_tools if either CrewAI or AutoGen is available
if CREWAI_AVAILABLE or AUTOGEN_AVAILABLE or PRAISONAI_AVAILABLE:
if CREWAI_AVAILABLE or AUTOGEN_AVAILABLE or PRAISONAI_AVAILABLE or AG2_AVAILABLE:
try:
from praisonai_tools import (
CodeDocsSearchTool, CSVSearchTool, DirectorySearchTool, DOCXSearchTool, DirectoryReadTool,
@@ -127,6 +137,8 @@ class AgentsGenerator:
raise ImportError("AutoGen is not installed. Please install it with 'pip install praisonai[autogen]'")
elif framework == "praisonai" and not PRAISONAI_AVAILABLE:
raise ImportError("PraisonAI is not installed. Please install it with 'pip install praisonaiagents'")
elif framework == "ag2" and not AG2_AVAILABLE:
raise ImportError("AG2 is not installed. Please install it with 'pip install praisonai[ag2]'")
def is_function_or_decorated(self, obj):
"""
@@ -274,7 +286,7 @@ class AgentsGenerator:
tools_dict = {}
# Only try to use praisonai_tools if it's available and needed
if PRAISONAI_TOOLS_AVAILABLE and (CREWAI_AVAILABLE or AUTOGEN_AVAILABLE or PRAISONAI_AVAILABLE):
if PRAISONAI_TOOLS_AVAILABLE and (CREWAI_AVAILABLE or AUTOGEN_AVAILABLE or PRAISONAI_AVAILABLE or AG2_AVAILABLE):
tools_dict = {
'CodeDocsSearchTool': CodeDocsSearchTool(),
'CSVSearchTool': CSVSearchTool(),
@@ -327,6 +339,12 @@ class AgentsGenerator:
if AGENTOPS_AVAILABLE:
agentops.init(os.environ.get("AGENTOPS_API_KEY"), default_tags=["praisonai"])
return self._run_praisonai(config, topic, tools_dict)
elif framework == "ag2":
if not AG2_AVAILABLE:
raise ImportError("AG2 is not installed. Please install it with 'pip install praisonai[ag2]'")
if AGENTOPS_AVAILABLE:
agentops.init(os.environ.get("AGENTOPS_API_KEY"), default_tags=["ag2"])
return self._run_ag2(config, topic, tools_dict)
else: # framework=crewai
if not CREWAI_AVAILABLE:
raise ImportError("CrewAI is not installed. Please install it with 'pip install praisonai[crewai]'")
@@ -407,6 +425,150 @@ class AgentsGenerator:
return result
def _run_ag2(self, config, topic, tools_dict):
"""
Run agents using the AG2 framework (community fork of AutoGen, PyPI: ag2).
AG2 installs under the 'autogen' namespace — there is no 'import ag2'.
Uses LLMConfig context manager + AssistantAgent + GroupChat pattern.
Args:
config (dict): Configuration dictionary parsed from YAML
topic (str): The topic/task to process
tools_dict (dict): Dictionary of available tools
Returns:
str: Result prefixed with '### AG2 Output ###'
"""
import re
from autogen import (
AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager, LLMConfig
)
model_config = self.config_list[0] if self.config_list else {}
# Allow YAML top-level llm block to override config_list values
yaml_llm = config.get("llm", {}) or {}
# Also check first role's llm block as a fallback
first_role_llm = {}
for role_details in config.get("roles", {}).values():
first_role_llm = role_details.get("llm", {}) or {}
break
# Priority: YAML top-level llm > first role llm > config_list > env vars
def _resolve(key, env_var=None, default=None):
return (yaml_llm.get(key) or first_role_llm.get(key)
or model_config.get(key)
or (os.environ.get(env_var) if env_var else None)
or default)
api_type = _resolve("api_type", default="openai").lower()
model_name = _resolve("model", default="gpt-4o-mini")
api_key = _resolve("api_key", env_var="OPENAI_API_KEY")
# Fix #3: also check OPENAI_API_BASE for consistency with rest of codebase
base_url = (model_config.get("base_url")
or yaml_llm.get("base_url")
or os.environ.get("OPENAI_BASE_URL")
or os.environ.get("OPENAI_API_BASE"))
# Build LLMConfig — pass a config dict; Bedrock needs no api_key
if api_type == "bedrock":
llm_config_entry = {"api_type": "bedrock", "model": model_name}
else:
llm_config_entry = {"model": model_name}
if api_key:
llm_config_entry["api_key"] = api_key
if base_url and base_url not in ("https://api.openai.com/v1", "https://api.openai.com/v1/"):
llm_config_entry["base_url"] = base_url
llm_config = LLMConfig(llm_config_entry)
user_proxy = UserProxyAgent(
name="User",
human_input_mode="NEVER",
is_termination_msg=lambda x: "TERMINATE" in (x.get("content") or ""),
code_execution_config=False,
)
# Create one AssistantAgent per role, passing llm_config directly
ag2_agent_entries = []
for role, details in config["roles"].items():
agent_name = details.get("role", role).replace("{topic}", topic)
backstory = details.get("backstory", "").replace("{topic}", topic)
agent_name_safe = re.sub(r"[^a-zA-Z0-9_\-]", "_", agent_name)
assistant = AssistantAgent(
name=agent_name_safe,
system_message=backstory + "\nWhen the task is done, reply 'TERMINATE'.",
llm_config=llm_config,
)
ag2_agent_entries.append((role, details, assistant))
# Register tools via AG2 decorator pattern
for role, details, assistant in ag2_agent_entries:
for tool_name in details.get("tools", []):
tool = tools_dict.get(tool_name)
if tool is None:
continue
func = tool if callable(tool) else getattr(tool, "run", None)
if func is None:
continue
def make_tool_fn(f):
def tool_fn(**kwargs):
return f(**kwargs) if callable(f) else str(f)
tool_fn.__name__ = tool_name
return tool_fn
wrapped = make_tool_fn(func)
assistant.register_for_llm(description=f"Tool: {tool_name}")(wrapped)
user_proxy.register_for_execution()(wrapped)
all_assistants = [a for _, _, a in ag2_agent_entries]
if not all_assistants:
return "### AG2 Output ###\nNo agents created from configuration."
# Build initial message from all task descriptions
task_lines = []
for role, details, _ in ag2_agent_entries:
for task_name, task_details in details.get("tasks", {}).items():
desc = task_details.get("description", "").replace("{topic}", topic)
if desc:
task_lines.append(desc)
initial_message = "\n".join(task_lines) if task_lines else topic
groupchat = GroupChat(
agents=[user_proxy] + all_assistants,
messages=[],
max_round=12,
)
manager = GroupChatManager(groupchat=groupchat, llm_config=llm_config)
try:
chat_result = user_proxy.initiate_chat(manager, message=initial_message)
except Exception as e:
return f"### AG2 Error ###\n{str(e)}"
# Prefer ChatResult.summary if available, otherwise scan messages
result_content = ""
summary = getattr(chat_result, "summary", None)
if summary and isinstance(summary, str) and summary.strip():
result_content = re.sub(r'[\s\.\,]*TERMINATE[\s\.\,]*$', '', summary, flags=re.IGNORECASE).strip().rstrip('.')
if not result_content:
for msg in reversed(groupchat.messages):
# Skip the initial user proxy message
if msg.get("name") == "User":
continue
content = (msg.get("content") or "").strip()
if content:
result_content = re.sub(r'[\s\.\,]*TERMINATE[\s\.\,]*$', '', content, flags=re.IGNORECASE).strip().rstrip('.')
if result_content:
break
if not result_content:
result_content = "Task completed."
return f"### AG2 Output ###\n{result_content}"
def _run_crewai(self, config, topic, tools_dict):
"""
Run agents using the CrewAI framework.
+15
View File
@@ -32,6 +32,16 @@ try:
except ImportError:
pass
AG2_AVAILABLE = False
try:
import importlib.metadata as _importlib_metadata
_importlib_metadata.distribution('ag2')
from autogen import LLMConfig as _AG2LLMConfig # noqa: F401 — AG2-exclusive class
AG2_AVAILABLE = True
del _AG2LLMConfig, _importlib_metadata
except Exception:
pass
try:
from praisonai_tools import (
CodeDocsSearchTool, CSVSearchTool, DirectorySearchTool, DOCXSearchTool,
@@ -83,6 +93,11 @@ AutoGen is not installed. Please install with:
Praisonai is not installed. Please install with:
pip install praisonaiagents
""")
elif framework == "ag2" and not AG2_AVAILABLE:
raise ImportError("""
AG2 is not installed. Please install with:
pip install "praisonai[ag2]"
""")
# Only show tools message if using a framework and tools are needed
if (framework in ["crewai", "autogen"]) and not PRAISONAI_TOOLS_AVAILABLE:
+1 -1
View File
@@ -56,7 +56,7 @@ class CloudDeployer:
file.write("FROM python:3.11-slim\n")
file.write("WORKDIR /app\n")
file.write("COPY . .\n")
file.write("RUN pip install flask praisonai==2.2.34 gunicorn markdown\n")
file.write("RUN pip install flask praisonai==2.2.33 gunicorn markdown\n")
file.write("EXPOSE 8080\n")
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
+7 -4
View File
@@ -1,6 +1,6 @@
[project]
name = "PraisonAI"
version = "2.2.34"
version = "2.2.33"
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
readme = "README.md"
license = ""
@@ -12,7 +12,7 @@ dependencies = [
"rich>=13.7",
"markdown>=3.5",
"pyparsing>=3.0.0",
"praisonaiagents>=0.0.107",
"praisonaiagents>=0.0.106",
"python-dotenv>=0.19.0",
"instructor>=1.3.3",
"PyYAML>=6.0",
@@ -92,10 +92,11 @@ call = [
train = []
crewai = ["crewai>=0.32.0", "praisonai-tools>=0.0.15"]
autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.15", "crewai"]
ag2 = ["ag2>=0.11.0", "praisonai-tools>=0.0.15"]
[tool.poetry]
name = "PraisonAI"
version = "2.2.34"
version = "2.2.33"
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
authors = ["Mervin Praison"]
license = ""
@@ -113,12 +114,13 @@ python = ">=3.10,<3.13"
rich = ">=13.7"
markdown = ">=3.5"
pyparsing = ">=3.0.0"
praisonaiagents = ">=0.0.107"
praisonaiagents = ">=0.0.106"
python-dotenv = ">=0.19.0"
instructor = ">=1.3.3"
PyYAML = ">=6.0"
mcp = ">=1.6.0"
pyautogen = {version = ">=0.2.19", optional = true}
ag2 = {version = ">=0.11.0", optional = true}
crewai = {version = ">=0.32.0", optional = true}
praisonai-tools = {version = ">=0.0.15", optional = true}
chainlit = {version = "==2.5.5", optional = true}
@@ -277,6 +279,7 @@ call = [
]
crewai = ["crewai", "praisonai-tools"]
autogen = ["pyautogen", "praisonai-tools", "crewai"]
ag2 = ["ag2", "praisonai-tools"]
[tool.poetry-dynamic-versioning]
enable = true
Whitespace-only changes.
@@ -0,0 +1,477 @@
"""
AG2 Mock Integration Tests — verifies PraisonAI correctly orchestrates AG2 agents.
Uses mocked AG2 responses — no real LLM API calls are made.
Fast: all tests should complete in < 1s each.
Run:
pytest tests/integration/ag2/test_ag2_integration.py -v
"""
import pytest
import os
import sys
from unittest.mock import patch, MagicMock
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../../"))
# Stub heavy dependencies that auto.py (develop branch) imports at module level
# so that tests can import praisonai without a full installation.
for _stub in ("instructor",):
if _stub not in sys.modules:
sys.modules[_stub] = MagicMock()
import importlib as _importlib
if "openai" not in sys.modules:
try:
_importlib.import_module("openai")
except ImportError:
_mock_openai = MagicMock()
_mock_openai.__version__ = "1.0.0"
sys.modules["openai"] = _mock_openai
# ---------------------------------------------------------------------------
# Fixtures
# ---------------------------------------------------------------------------
@pytest.fixture
def single_agent_yaml():
return """
framework: ag2
topic: Write a short poem about Python
roles:
poet:
role: "Creative Poet"
goal: "Write elegant and concise poems"
backstory: "You are a creative poet who loves Python and technology."
tasks:
write_poem:
description: "Write a short 4-line poem about Python programming"
expected_output: "A 4-line poem about Python"
"""
@pytest.fixture
def multi_agent_yaml():
return """
framework: ag2
topic: Explain why open-source AI matters
roles:
researcher:
role: "Research Analyst"
goal: "Research and gather key facts"
backstory: "Expert in technology research and trend analysis."
tasks:
research:
description: "Research why open-source AI matters"
expected_output: "Key facts and data points"
writer:
role: "Technical Writer"
goal: "Write clear technical content"
backstory: "Professional technical writer with 10 years experience."
tasks:
write:
description: "Write a clear explanation of why open-source AI matters"
expected_output: "A 200-word explanation"
"""
@pytest.fixture
def mock_ag2_classes():
"""Mock all AG2 classes used in _run_ag2."""
mock_llm_config = MagicMock()
mock_llm_config.__enter__ = MagicMock(return_value=mock_llm_config)
mock_llm_config.__exit__ = MagicMock(return_value=False)
mock_assistant = MagicMock()
mock_assistant.name = "test_agent"
mock_user_proxy = MagicMock()
mock_user_proxy.name = "User"
mock_groupchat = MagicMock()
mock_groupchat.messages = [
{
"name": "test_agent",
"role": "assistant",
"content": "Task completed successfully. TERMINATE",
}
]
mock_manager = MagicMock()
return {
"llm_config": mock_llm_config,
"assistant": mock_assistant,
"user_proxy": mock_user_proxy,
"groupchat": mock_groupchat,
"manager": mock_manager,
}
# ---------------------------------------------------------------------------
# AG2 import detection
# ---------------------------------------------------------------------------
class TestAG2Import:
@pytest.mark.integration
def test_ag2_distribution_available(self):
"""ag2 PyPI distribution should be findable when installed.
Note: ag2 installs under the 'autogen' namespace — 'import ag2' does NOT work.
Detection uses importlib.metadata to check the 'ag2' distribution name.
"""
import importlib.metadata
try:
dist = importlib.metadata.distribution('ag2')
assert dist.metadata['Name'] == 'ag2'
except importlib.metadata.PackageNotFoundError:
pytest.skip("ag2 not installed — skipping AG2 integration tests")
@pytest.mark.integration
def test_autogen_namespace_importable_with_ag2(self):
"""When ag2 is installed, autogen namespace classes are importable."""
try:
from autogen import AssistantAgent, UserProxyAgent, GroupChat, LLMConfig
assert AssistantAgent is not None
assert UserProxyAgent is not None
assert GroupChat is not None
assert LLMConfig is not None
except ImportError:
pytest.skip("ag2 not installed — autogen namespace not available")
# ---------------------------------------------------------------------------
# Single-agent flow (mocked)
# ---------------------------------------------------------------------------
class TestAG2SingleAgentFlow:
@pytest.mark.integration
def test_single_agent_yaml_initialises_praisonai(self, single_agent_yaml, mock_ag2_classes):
"""PraisonAI initialises correctly with framework='ag2' from YAML."""
import tempfile
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
f.write(single_agent_yaml)
yaml_path = f.name
try:
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
try:
from praisonai import PraisonAI
ai = PraisonAI(agent_file=yaml_path, framework="ag2")
assert ai.framework == "ag2"
except ImportError as e:
pytest.skip(f"PraisonAI not available: {e}")
finally:
os.unlink(yaml_path)
@pytest.mark.integration
def test_single_agent_run_returns_ag2_output(self, mock_ag2_classes):
"""_run_ag2 executes single-agent flow and returns '### AG2 Output ###'."""
config = {
"framework": "ag2",
"topic": "Write a poem",
"roles": {
"poet": {
"role": "Creative Poet",
"goal": "Write poems",
"backstory": "A creative poet.",
"tasks": {
"task1": {
"description": "Write a poem about Python",
"expected_output": "A short poem",
}
},
"tools": [],
}
},
}
m = mock_ag2_classes
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
try:
from praisonai.agents_generator import AgentsGenerator
except ImportError as e:
pytest.skip(f"AgentsGenerator not available: {e}")
gen = AgentsGenerator(
agent_file="agents.yaml",
framework="ag2",
config_list=[{"model": "gpt-4o-mini", "api_key": "sk-test"}],
)
with patch("autogen.LLMConfig", create=True, return_value=m["llm_config"]), \
patch("autogen.AssistantAgent", create=True, return_value=m["assistant"]), \
patch("autogen.UserProxyAgent", create=True, return_value=m["user_proxy"]), \
patch("autogen.GroupChat", create=True, return_value=m["groupchat"]), \
patch("autogen.GroupChatManager", create=True, return_value=m["manager"]):
result = gen._run_ag2(config, "Write a poem", {})
assert "### AG2 Output ###" in result
assert "Task completed successfully" in result
@pytest.mark.integration
def test_single_agent_calls_initiate_chat(self, mock_ag2_classes):
"""user_proxy.initiate_chat is called with the manager and initial message."""
config = {
"framework": "ag2",
"topic": "Test topic",
"roles": {
"agent": {
"role": "Agent",
"goal": "Help",
"backstory": "Helpful agent.",
"tasks": {
"t": {"description": "Do the task", "expected_output": "Done"}
},
"tools": [],
}
},
}
m = mock_ag2_classes
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
try:
from praisonai.agents_generator import AgentsGenerator
except ImportError as e:
pytest.skip(f"AgentsGenerator not available: {e}")
gen = AgentsGenerator(
agent_file="agents.yaml",
framework="ag2",
config_list=[{"model": "gpt-4o-mini", "api_key": "sk-test"}],
)
with patch("autogen.LLMConfig", create=True, return_value=m["llm_config"]), \
patch("autogen.AssistantAgent", create=True, return_value=m["assistant"]), \
patch("autogen.UserProxyAgent", create=True, return_value=m["user_proxy"]), \
patch("autogen.GroupChat", create=True, return_value=m["groupchat"]), \
patch("autogen.GroupChatManager", create=True, return_value=m["manager"]):
gen._run_ag2(config, "Test topic", {})
m["user_proxy"].initiate_chat.assert_called_once()
call_args = m["user_proxy"].initiate_chat.call_args
# First positional arg should be the manager
assert call_args[0][0] is m["manager"]
# message kwarg should be non-empty (task description or topic)
message = call_args[1].get("message", "")
assert message != ""
# ---------------------------------------------------------------------------
# Multi-agent GroupChat flow (mocked)
# ---------------------------------------------------------------------------
class TestAG2MultiAgentGroupChatFlow:
@pytest.mark.integration
def test_multi_agent_creates_correct_number_of_assistants(self, multi_agent_yaml, mock_ag2_classes):
"""Two roles in YAML → two AssistantAgents created."""
config = {
"framework": "ag2",
"topic": "Explain open-source AI",
"roles": {
"researcher": {
"role": "Research Analyst", "goal": "Research", "backstory": "Analyst.",
"tasks": {"r": {"description": "Research it", "expected_output": "Facts"}},
"tools": [],
},
"writer": {
"role": "Technical Writer", "goal": "Write", "backstory": "Writer.",
"tasks": {"w": {"description": "Write it", "expected_output": "Article"}},
"tools": [],
},
},
}
m = mock_ag2_classes
assistant_call_count = [0]
def count_assistant(**kwargs):
assistant_call_count[0] += 1
a = MagicMock()
a.name = kwargs.get("name", f"agent_{assistant_call_count[0]}")
return a
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
try:
from praisonai.agents_generator import AgentsGenerator
except ImportError as e:
pytest.skip(f"AgentsGenerator not available: {e}")
gen = AgentsGenerator(
agent_file="agents.yaml",
framework="ag2",
config_list=[{"model": "gpt-4o-mini", "api_key": "sk-test"}],
)
with patch("autogen.LLMConfig", create=True, return_value=m["llm_config"]), \
patch("autogen.AssistantAgent", create=True, side_effect=count_assistant), \
patch("autogen.UserProxyAgent", create=True, return_value=m["user_proxy"]), \
patch("autogen.GroupChat", create=True, return_value=m["groupchat"]), \
patch("autogen.GroupChatManager", create=True, return_value=m["manager"]):
gen._run_ag2(config, "Explain open-source AI", {})
assert assistant_call_count[0] == 2
@pytest.mark.integration
def test_multi_agent_groupchat_max_round_set(self, mock_ag2_classes):
"""GroupChat is created with max_round parameter."""
config = {
"framework": "ag2",
"topic": "Test",
"roles": {
"a": {
"role": "Agent", "goal": "Help", "backstory": "Helper.",
"tasks": {"t": {"description": "Do", "expected_output": "Done"}},
"tools": [],
}
},
}
m = mock_ag2_classes
groupchat_kwargs = {}
def capture_groupchat(**kwargs):
groupchat_kwargs.update(kwargs)
return m["groupchat"]
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
try:
from praisonai.agents_generator import AgentsGenerator
except ImportError as e:
pytest.skip(f"AgentsGenerator not available: {e}")
gen = AgentsGenerator(
agent_file="agents.yaml",
framework="ag2",
config_list=[{"model": "gpt-4o-mini", "api_key": "sk-test"}],
)
with patch("autogen.LLMConfig", create=True, return_value=m["llm_config"]), \
patch("autogen.AssistantAgent", create=True, return_value=m["assistant"]), \
patch("autogen.UserProxyAgent", create=True, return_value=m["user_proxy"]), \
patch("autogen.GroupChat", create=True, side_effect=capture_groupchat), \
patch("autogen.GroupChatManager", create=True, return_value=m["manager"]):
gen._run_ag2(config, "Test", {})
assert "max_round" in groupchat_kwargs
assert groupchat_kwargs["max_round"] > 0
# ---------------------------------------------------------------------------
# Backward-compatibility: existing autogen/crewai paths unaffected
# ---------------------------------------------------------------------------
class TestAG2BackwardCompatibility:
@pytest.mark.integration
def test_autogen_framework_still_works(self):
"""framework='autogen' dispatches to _run_autogen, not _run_ag2."""
import yaml
with patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", True), \
patch("praisonai.agents_generator.AG2_AVAILABLE", False), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
try:
from praisonai.agents_generator import AgentsGenerator
except ImportError as e:
pytest.skip(f"AgentsGenerator not available: {e}")
gen = AgentsGenerator(
agent_file="agents.yaml",
framework="autogen",
config_list=[{"model": "gpt-4o-mini", "api_key": "sk-test"}],
)
assert gen.framework == "autogen"
gen.agent_yaml = yaml.dump({
"framework": "autogen",
"topic": "Test",
"roles": {
"agent": {
"role": "Agent", "goal": "Help", "backstory": "Helper.",
"tasks": {"t": {"description": "Do", "expected_output": "Done"}},
"tools": [],
}
},
})
# Verify _run_ag2 is NOT called when framework='autogen'
with patch.object(gen, "_run_ag2") as mock_run_ag2, \
patch.object(gen, "_run_autogen", return_value="autogen result") as mock_run_autogen:
gen.generate_crew_and_kickoff()
mock_run_ag2.assert_not_called()
mock_run_autogen.assert_called_once()
@pytest.mark.integration
def test_ag2_framework_dispatches_to_run_ag2(self, mock_ag2_classes):
"""framework='ag2' dispatches to _run_ag2 and NOT to _run_autogen."""
import yaml
m = mock_ag2_classes
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
try:
from praisonai.agents_generator import AgentsGenerator
except ImportError as e:
pytest.skip(f"AgentsGenerator not available: {e}")
gen = AgentsGenerator(
agent_file="agents.yaml",
framework="ag2",
config_list=[{"model": "gpt-4o-mini", "api_key": "sk-test"}],
)
gen.agent_yaml = yaml.dump({
"framework": "ag2",
"topic": "Test",
"roles": {
"agent": {
"role": "Agent", "goal": "Help", "backstory": "Helper.",
"tasks": {"t": {"description": "Do", "expected_output": "Done"}},
"tools": [],
}
},
})
with patch.object(gen, "_run_autogen") as mock_autogen, \
patch("autogen.LLMConfig", create=True, return_value=m["llm_config"]), \
patch("autogen.AssistantAgent", create=True, return_value=m["assistant"]), \
patch("autogen.UserProxyAgent", create=True, return_value=m["user_proxy"]), \
patch("autogen.GroupChat", create=True, return_value=m["groupchat"]), \
patch("autogen.GroupChatManager", create=True, return_value=m["manager"]):
result = gen.generate_crew_and_kickoff()
mock_autogen.assert_not_called()
assert "### AG2 Output ###" in result
if __name__ == "__main__":
pytest.main([__file__, "-v"])
@@ -0,0 +1,98 @@
"""
Example of AG2 tool registration for use with PraisonAI's --framework ag2.
AG2 (community fork of AutoGen, PyPI package: ag2) installs under the
'autogen' namespace but is a distinct package from pyautogen/pyautogen2.
Usage with PraisonAI:
pip install "praisonai[ag2]"
praisonai --framework ag2 agents.yaml
Standalone run:
python tests/source/ag2_function_tools.py
"""
from typing import Annotated, Literal
import os
# ag2 installs under the 'autogen' namespace
from autogen import (
AssistantAgent,
UserProxyAgent,
GroupChat,
GroupChatManager,
LLMConfig,
)
Operator = Literal["+", "-", "*", "/"]
def calculator(
a: Annotated[int, "First operand"],
b: Annotated[int, "Second operand"],
operator: Annotated[Operator, "Arithmetic operator: +, -, *, /"],
) -> int:
"""Perform basic arithmetic operations."""
if operator == "+":
return a + b
elif operator == "-":
return a - b
elif operator == "*":
return a * b
elif operator == "/":
if b == 0:
raise ValueError("Division by zero")
return int(a / b)
else:
raise ValueError(f"Invalid operator: {operator}")
# Build LLMConfig — AG2 uses a context manager pattern so agents
# created inside the 'with' block automatically inherit the config.
llm_config = LLMConfig(
api_type="openai",
model=os.environ.get("MODEL_NAME", "gpt-4o-mini"),
api_key=os.environ.get("OPENAI_API_KEY"),
)
# Create AssistantAgent inside llm_config context
with llm_config:
assistant = AssistantAgent(
name="Calculator_Assistant",
system_message=(
"You are a helpful AI assistant that can perform arithmetic calculations. "
"Use the calculator tool when math operations are needed. "
"Return 'TERMINATE' when the task is done."
),
)
# UserProxyAgent does not use LLM — created outside context
user_proxy = UserProxyAgent(
name="User",
human_input_mode="NEVER",
is_termination_msg=lambda msg: (
msg.get("content") is not None and "TERMINATE" in msg["content"]
),
code_execution_config=False,
)
# AG2 tool registration pattern:
# @agent.register_for_llm(description="...") — exposes tool schema to the LLM
# @user_proxy.register_for_execution() — tells user_proxy to execute it
@assistant.register_for_llm(description="A simple calculator for arithmetic operations.")
@user_proxy.register_for_execution()
def calculator_tool(
a: Annotated[int, "First operand"],
b: Annotated[int, "Second operand"],
operator: Annotated[Operator, "Arithmetic operator"],
) -> int:
return calculator(a, b, operator)
if __name__ == "__main__":
chat_result = user_proxy.initiate_chat(
assistant,
message="What is (44232 + 13312 / (232 - 32)) * 5?",
)
print(f"\nResult: {chat_result.summary}")
@@ -0,0 +1,542 @@
"""
Unit tests for the AG2 framework integration in PraisonAI.
Tests cover:
- AG2 availability detection (AG2_AVAILABLE flag)
- Framework validation in AgentsGenerator.__init__
- _run_ag2 method: config parsing, agent creation, tool handling
- LLMConfig construction (OpenAI and Bedrock paths)
All external calls are mocked — no real LLM API calls made.
"""
import pytest
import os
import sys
from unittest.mock import patch, MagicMock, call
import importlib
# Ensure src is on path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../"))
# Stub heavy dependencies that auto.py (develop branch) imports at module level
# so that tests can import praisonai without a full installation.
for _stub in ("instructor",):
if _stub not in sys.modules:
sys.modules[_stub] = MagicMock()
# openai is installed (required by ag2/autogen internals), but auto.py also
# imports it at module level. Ensure it's really loaded, not a mock.
import importlib as _importlib
if "openai" not in sys.modules:
try:
_importlib.import_module("openai")
except ImportError:
_mock_openai = MagicMock()
_mock_openai.__version__ = "1.0.0"
sys.modules["openai"] = _mock_openai
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _make_config(roles=None, framework="ag2", topic="Test topic"):
"""Build a minimal agents config dict."""
if roles is None:
roles = {
"researcher": {
"role": "Researcher",
"goal": "Research things",
"backstory": "You are a researcher.",
"tasks": {
"task1": {
"description": "Research {topic}",
"expected_output": "A research report",
}
},
"tools": [],
}
}
return {"framework": framework, "topic": topic, "roles": roles}
# ---------------------------------------------------------------------------
# AG2_AVAILABLE flag detection
# ---------------------------------------------------------------------------
class TestAG2AvailabilityFlag:
def test_ag2_available_false_when_not_installed(self):
"""AG2_AVAILABLE is False when 'ag2' distribution is not found."""
import importlib.metadata as meta
original_fn = meta.distribution
def raise_not_found(name):
if name == 'ag2':
raise meta.PackageNotFoundError('ag2')
return original_fn(name)
# Verify detection logic directly without relying on cached module state
ag2_detected = True
try:
with patch('importlib.metadata.distribution', side_effect=raise_not_found):
meta.distribution('ag2')
except meta.PackageNotFoundError:
ag2_detected = False
assert ag2_detected is False
def test_ag2_available_true_when_installed(self):
"""AG2_AVAILABLE is True when 'ag2' distribution and LLMConfig are present."""
import importlib.metadata as meta
try:
dist = meta.distribution('ag2')
assert dist is not None
from autogen import LLMConfig # noqa: F401
except (meta.PackageNotFoundError, ImportError):
pytest.skip("ag2 not installed — skipping")
# ---------------------------------------------------------------------------
# AgentsGenerator.__init__ framework validation
# ---------------------------------------------------------------------------
class TestAgentsGeneratorAG2Validation:
def _make_generator(self, framework, ag2_available=True):
"""Create AgentsGenerator with mocked availability flags."""
with patch("praisonai.agents_generator.AG2_AVAILABLE", ag2_available), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
from praisonai.agents_generator import AgentsGenerator
return AgentsGenerator(
agent_file="agents.yaml",
framework=framework,
config_list=[{"model": "gpt-4o-mini", "api_key": "test-key"}],
)
def test_ag2_framework_accepted_when_available(self):
"""No ImportError when framework='ag2' and AG2 is installed."""
gen = self._make_generator("ag2", ag2_available=True)
assert gen.framework == "ag2"
def test_ag2_framework_raises_when_not_available(self):
"""ImportError raised with helpful message when ag2 not installed."""
with pytest.raises(ImportError, match="AG2 is not installed"):
self._make_generator("ag2", ag2_available=False)
def test_autogen_framework_unaffected(self):
"""Existing autogen framework path still works independently."""
with patch("praisonai.agents_generator.AG2_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", True), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
from praisonai.agents_generator import AgentsGenerator
gen = AgentsGenerator(
agent_file="agents.yaml",
framework="autogen",
config_list=[{"model": "gpt-4o-mini", "api_key": "test-key"}],
)
assert gen.framework == "autogen"
# ---------------------------------------------------------------------------
# _run_ag2: LLMConfig construction
# ---------------------------------------------------------------------------
class TestRunAG2LLMConfig:
def _make_gen_with_config(self, config_list):
"""Build an AgentsGenerator instance with given config_list."""
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
from praisonai.agents_generator import AgentsGenerator
return AgentsGenerator(
agent_file="agents.yaml",
framework="ag2",
config_list=config_list,
)
@patch("praisonai.agents_generator.AG2_AVAILABLE", True)
def test_openai_llm_config_constructed(self):
"""LLMConfig is built with api_type='openai' for standard config."""
gen = self._make_gen_with_config([
{"model": "gpt-4o-mini", "api_key": "sk-test", "api_type": "openai"}
])
mock_llm_config = MagicMock()
mock_llm_config.__enter__ = MagicMock(return_value=mock_llm_config)
mock_llm_config.__exit__ = MagicMock(return_value=False)
mock_assistant = MagicMock()
mock_user_proxy = MagicMock()
mock_groupchat = MagicMock()
mock_groupchat.messages = [{"name": "Researcher", "content": "Done. TERMINATE", "role": "assistant"}]
mock_manager = MagicMock()
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("autogen.LLMConfig", create=True, return_value=mock_llm_config) as mock_llmcfg, \
patch("autogen.AssistantAgent", create=True, return_value=mock_assistant), \
patch("autogen.UserProxyAgent", create=True, return_value=mock_user_proxy), \
patch("autogen.GroupChat", create=True, return_value=mock_groupchat), \
patch("autogen.GroupChatManager", create=True, return_value=mock_manager):
config = _make_config()
gen._run_ag2(config, "Test topic", {})
mock_llmcfg.assert_called_once()
# LLMConfig is called with a positional dict arg
call_args = mock_llmcfg.call_args[0][0]
assert call_args.get("model") == "gpt-4o-mini"
assert call_args.get("api_key") == "sk-test"
@patch("praisonai.agents_generator.AG2_AVAILABLE", True)
def test_bedrock_llm_config_constructed(self):
"""LLMConfig uses api_type='bedrock' when config specifies bedrock."""
gen = self._make_gen_with_config([
{
"model": "anthropic.claude-3-5-sonnet-20241022-v2:0",
"api_type": "bedrock",
}
])
mock_llm_config = MagicMock()
mock_llm_config.__enter__ = MagicMock(return_value=mock_llm_config)
mock_llm_config.__exit__ = MagicMock(return_value=False)
mock_assistant = MagicMock()
mock_user_proxy = MagicMock()
mock_groupchat = MagicMock()
mock_groupchat.messages = [{"name": "Agent", "content": "Report ready. TERMINATE", "role": "assistant"}]
mock_manager = MagicMock()
with patch("autogen.LLMConfig", create=True, return_value=mock_llm_config) as mock_llmcfg, \
patch("autogen.AssistantAgent", create=True, return_value=mock_assistant), \
patch("autogen.UserProxyAgent", create=True, return_value=mock_user_proxy), \
patch("autogen.GroupChat", create=True, return_value=mock_groupchat), \
patch("autogen.GroupChatManager", create=True, return_value=mock_manager):
config = _make_config()
gen._run_ag2(config, "AWS deployment", {})
mock_llmcfg.assert_called_once()
# LLMConfig is called with a positional dict arg
call_args = mock_llmcfg.call_args[0][0]
assert call_args.get("api_type") == "bedrock"
assert "api_key" not in call_args # no api_key for bedrock
# ---------------------------------------------------------------------------
# _run_ag2: agent and GroupChat creation
# ---------------------------------------------------------------------------
class TestRunAG2AgentCreation:
def _make_gen(self):
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
from praisonai.agents_generator import AgentsGenerator
return AgentsGenerator(
agent_file="agents.yaml",
framework="ag2",
config_list=[{"model": "gpt-4o-mini", "api_key": "sk-test"}],
)
def test_assistant_created_per_role(self):
"""One AssistantAgent is created for each role in the config."""
gen = self._make_gen()
config = _make_config(roles={
"role_a": {
"role": "Agent A", "goal": "Goal A", "backstory": "Backstory A",
"tasks": {"t1": {"description": "Do A", "expected_output": "A done"}},
"tools": [],
},
"role_b": {
"role": "Agent B", "goal": "Goal B", "backstory": "Backstory B",
"tasks": {"t2": {"description": "Do B", "expected_output": "B done"}},
"tools": [],
},
})
mock_llm_config = MagicMock()
mock_llm_config.__enter__ = MagicMock(return_value=mock_llm_config)
mock_llm_config.__exit__ = MagicMock(return_value=False)
created_agents = []
def fake_assistant(**kwargs):
m = MagicMock()
m.name = kwargs.get("name", "agent")
created_agents.append(m)
return m
mock_user_proxy = MagicMock()
mock_groupchat = MagicMock()
mock_groupchat.messages = [{"name": "Agent A", "content": "Done. TERMINATE", "role": "assistant"}]
mock_manager = MagicMock()
with patch("autogen.LLMConfig", create=True, return_value=mock_llm_config), \
patch("autogen.AssistantAgent", create=True, side_effect=fake_assistant), \
patch("autogen.UserProxyAgent", create=True, return_value=mock_user_proxy), \
patch("autogen.GroupChat", create=True, return_value=mock_groupchat), \
patch("autogen.GroupChatManager", create=True, return_value=mock_manager):
gen._run_ag2(config, "Test", {})
assert len(created_agents) == 2
def test_groupchat_includes_user_proxy_and_assistants(self):
"""GroupChat receives user_proxy + all assistants."""
gen = self._make_gen()
config = _make_config()
mock_llm_config = MagicMock()
mock_llm_config.__enter__ = MagicMock(return_value=mock_llm_config)
mock_llm_config.__exit__ = MagicMock(return_value=False)
mock_assistant = MagicMock()
mock_assistant.name = "Researcher"
mock_user_proxy = MagicMock()
mock_user_proxy.name = "User"
mock_groupchat = MagicMock()
mock_groupchat.messages = [{"name": "Researcher", "content": "Done. TERMINATE", "role": "assistant"}]
mock_manager = MagicMock()
groupchat_call_args = {}
def capture_groupchat(**kwargs):
groupchat_call_args.update(kwargs)
return mock_groupchat
with patch("autogen.LLMConfig", create=True, return_value=mock_llm_config), \
patch("autogen.AssistantAgent", create=True, return_value=mock_assistant), \
patch("autogen.UserProxyAgent", create=True, return_value=mock_user_proxy), \
patch("autogen.GroupChat", create=True, side_effect=capture_groupchat), \
patch("autogen.GroupChatManager", create=True, return_value=mock_manager):
gen._run_ag2(config, "Test", {})
agents_in_groupchat = groupchat_call_args.get("agents", [])
assert mock_user_proxy in agents_in_groupchat
assert mock_assistant in agents_in_groupchat
def test_empty_roles_returns_no_agents_message(self):
"""Returns a clear message when no roles are defined in config."""
gen = self._make_gen()
config = _make_config(roles={})
mock_llm_config = MagicMock()
mock_llm_config.__enter__ = MagicMock(return_value=mock_llm_config)
mock_llm_config.__exit__ = MagicMock(return_value=False)
mock_user_proxy = MagicMock()
with patch("autogen.LLMConfig", create=True, return_value=mock_llm_config), \
patch("autogen.AssistantAgent"), \
patch("autogen.UserProxyAgent", create=True, return_value=mock_user_proxy):
result = gen._run_ag2(config, "Test", {})
assert "No agents" in result
# ---------------------------------------------------------------------------
# _run_ag2: system message composition
# ---------------------------------------------------------------------------
class TestRunAG2SystemMessage:
def _make_gen(self):
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
from praisonai.agents_generator import AgentsGenerator
return AgentsGenerator(
agent_file="agents.yaml",
framework="ag2",
config_list=[{"model": "gpt-4o-mini", "api_key": "sk-test"}],
)
def test_system_message_contains_backstory(self):
"""AssistantAgent system_message includes the backstory from YAML."""
gen = self._make_gen()
config = _make_config(roles={
"agent1": {
"role": "Expert",
"goal": "Help users",
"backstory": "A unique backstory for testing purposes.",
"tasks": {"t": {"description": "Do it", "expected_output": "Done"}},
"tools": [],
}
})
mock_llm_config = MagicMock()
mock_llm_config.__enter__ = MagicMock(return_value=mock_llm_config)
mock_llm_config.__exit__ = MagicMock(return_value=False)
mock_user_proxy = MagicMock()
mock_groupchat = MagicMock()
mock_groupchat.messages = [{"name": "Expert", "content": "Done. TERMINATE", "role": "assistant"}]
mock_manager = MagicMock()
assistant_kwargs = {}
def capture_assistant(**kwargs):
assistant_kwargs.update(kwargs)
m = MagicMock()
m.name = kwargs.get("name", "agent")
return m
with patch("autogen.LLMConfig", create=True, return_value=mock_llm_config), \
patch("autogen.AssistantAgent", create=True, side_effect=capture_assistant), \
patch("autogen.UserProxyAgent", create=True, return_value=mock_user_proxy), \
patch("autogen.GroupChat", create=True, return_value=mock_groupchat), \
patch("autogen.GroupChatManager", create=True, return_value=mock_manager):
gen._run_ag2(config, "Test", {})
assert "A unique backstory for testing purposes." in assistant_kwargs.get("system_message", "")
assert "TERMINATE" in assistant_kwargs.get("system_message", "")
def test_agent_name_sanitised(self):
"""Agent names with special characters are sanitised for AG2 compatibility."""
gen = self._make_gen()
config = _make_config(roles={
"agent1": {
"role": "AI & ML Expert (2024)", # contains special chars
"goal": "Help",
"backstory": "Expert.",
"tasks": {"t": {"description": "Do it", "expected_output": "Done"}},
"tools": [],
}
})
mock_llm_config = MagicMock()
mock_llm_config.__enter__ = MagicMock(return_value=mock_llm_config)
mock_llm_config.__exit__ = MagicMock(return_value=False)
mock_user_proxy = MagicMock()
mock_groupchat = MagicMock()
mock_groupchat.messages = [{"name": "AI___ML_Expert__2024_", "content": "Done. TERMINATE", "role": "assistant"}]
mock_manager = MagicMock()
created_name = {}
def capture_assistant(**kwargs):
created_name["name"] = kwargs.get("name", "")
m = MagicMock()
m.name = created_name["name"]
return m
with patch("autogen.LLMConfig", create=True, return_value=mock_llm_config), \
patch("autogen.AssistantAgent", create=True, side_effect=capture_assistant), \
patch("autogen.UserProxyAgent", create=True, return_value=mock_user_proxy), \
patch("autogen.GroupChat", create=True, return_value=mock_groupchat), \
patch("autogen.GroupChatManager", create=True, return_value=mock_manager):
gen._run_ag2(config, "Test", {})
name = created_name.get("name", "")
# Should not contain special chars that would break AG2
import re
assert re.match(r"^[a-zA-Z0-9_\-]+$", name), f"Name '{name}' contains invalid characters"
# ---------------------------------------------------------------------------
# _run_ag2: output extraction
# ---------------------------------------------------------------------------
class TestRunAG2OutputExtraction:
def _make_gen(self):
with patch("praisonai.agents_generator.AG2_AVAILABLE", True), \
patch("praisonai.agents_generator.CREWAI_AVAILABLE", False), \
patch("praisonai.agents_generator.AUTOGEN_AVAILABLE", False), \
patch("praisonai.agents_generator.PRAISONAI_AVAILABLE", True):
from praisonai.agents_generator import AgentsGenerator
return AgentsGenerator(
agent_file="agents.yaml",
framework="ag2",
config_list=[{"model": "gpt-4o-mini", "api_key": "sk-test"}],
)
def _run_with_messages(self, messages):
gen = self._make_gen()
config = _make_config()
mock_llm_config = MagicMock()
mock_assistant = MagicMock()
mock_assistant.name = "Researcher"
mock_user_proxy = MagicMock()
# chat_result with no summary so extraction falls back to messages
mock_chat_result = MagicMock()
mock_chat_result.summary = None
mock_user_proxy.initiate_chat.return_value = mock_chat_result
mock_groupchat = MagicMock()
mock_groupchat.messages = messages
mock_manager = MagicMock()
with patch("autogen.LLMConfig", create=True, return_value=mock_llm_config), \
patch("autogen.AssistantAgent", create=True, return_value=mock_assistant), \
patch("autogen.UserProxyAgent", create=True, return_value=mock_user_proxy), \
patch("autogen.GroupChat", create=True, return_value=mock_groupchat), \
patch("autogen.GroupChatManager", create=True, return_value=mock_manager):
return gen._run_ag2(config, "Test", {})
def test_output_prefixed_with_ag2_header(self):
"""Result always starts with '### AG2 Output ###'."""
result = self._run_with_messages([
{"name": "Researcher", "content": "Here are my findings. TERMINATE", "role": "assistant"}
])
assert result.startswith("### AG2 Output ###")
def test_terminate_marker_stripped_from_output(self):
"""TERMINATE keyword is removed from the extracted output."""
result = self._run_with_messages([
{"name": "Researcher", "content": "Detailed findings here. TERMINATE", "role": "assistant"}
])
assert "TERMINATE" not in result
assert "Detailed findings here" in result
def test_user_messages_skipped_in_extraction(self):
"""User proxy messages are not included in the extracted output."""
result = self._run_with_messages([
{"name": "User", "content": "This is the user message", "role": "user"},
{"name": "Researcher", "content": "This is the agent response. TERMINATE", "role": "assistant"},
])
assert "This is the user message" not in result
assert "This is the agent response" in result
def test_execution_error_returns_error_message(self):
"""Exception during initiate_chat returns a '### AG2 Error ###' message."""
gen = self._make_gen()
config = _make_config()
mock_llm_config = MagicMock()
mock_llm_config.__enter__ = MagicMock(return_value=mock_llm_config)
mock_llm_config.__exit__ = MagicMock(return_value=False)
mock_assistant = MagicMock()
mock_assistant.name = "Researcher"
mock_user_proxy = MagicMock()
mock_user_proxy.initiate_chat.side_effect = RuntimeError("Connection failed")
mock_groupchat = MagicMock()
mock_groupchat.messages = []
mock_manager = MagicMock()
with patch("autogen.LLMConfig", create=True, return_value=mock_llm_config), \
patch("autogen.AssistantAgent", create=True, return_value=mock_assistant), \
patch("autogen.UserProxyAgent", create=True, return_value=mock_user_proxy), \
patch("autogen.GroupChat", create=True, return_value=mock_groupchat), \
patch("autogen.GroupChatManager", create=True, return_value=mock_manager):
result = gen._run_ag2(config, "Test", {})
assert "### AG2 Error ###" in result
assert "Connection failed" in result
if __name__ == "__main__":
pytest.main([__file__, "-v"])
+2582 -2584
View File
File diff suppressed because it is too large. Load diff