Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
pip install pytest pytest-cov black flake8 mypy
pip install -e ".[dev]"

- name: Lint with flake8
run: |
Expand All @@ -56,7 +55,6 @@ jobs:
- name: Test with pytest
run: |
pytest tests/ --cov=multimodal_agent_framework --cov-report=xml --cov-report=term-missing
continue-on-error: true # Allow tests to fail if no tests exist yet

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
Expand Down Expand Up @@ -92,6 +90,33 @@ jobs:
run: |
twine check dist/*

- name: Test installation from wheel
run: |
# Create fresh environment and test installation
python -m venv test_install_env
source test_install_env/bin/activate
pip install dist/*.whl

# Run installation tests
python -c "
from multimodal_agent_framework import MultiModalAgent, Reviewer, generate_function_schema
from multimodal_agent_framework.connectors import OpenAIConnector
print('✅ All critical imports successful')

# Test function schema generator
def test_func(x: int): return x * 2
schema = generate_function_schema(test_func)
assert schema['name'] == 'test_func'
print('✅ Function schema generator works')

# Test reviewer
reviewer = Reviewer('test prompt')
assert reviewer.review_prompt == 'test prompt'
print('✅ Reviewer works')

print('🎉 Package installation verification successful!')
"

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
Expand Down
29 changes: 27 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,36 @@ agent = MultiModalAgent(

## Development

### Setup
```bash
git clone <repository-url>
cd AgentFramework
cd multimodalagentframework
pip install -r requirements.txt
pip install -e .
pip install -e .[dev] # Install with development dependencies
```

### Running Tests
```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=multimodal_agent_framework

# Run specific test file
pytest tests/test_function_schema_generator.py
```

### Code Quality
```bash
# Format code
black .

# Check formatting (run before committing)
black --check .

# Type checking
mypy multimodal_agent_framework/
```

## License
Expand Down
2 changes: 1 addition & 1 deletion examples/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""Examples for the multimodal agent framework."""
"""Examples for the multimodal agent framework."""
48 changes: 23 additions & 25 deletions examples/conversation_handoff_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
OpenAIConnector,
ClaudeConnector,
get_openai_client,
get_claude_client
get_claude_client,
)


Expand All @@ -27,7 +27,7 @@ def demonstrate_conversation_handoff():
name="OpenAI_Analyst",
system_prompt="""You are a technical analyst. Analyze problems methodically and provide
detailed technical explanations. Be thorough in your reasoning.""",
connector=OpenAIConnector(get_openai_client())
connector=OpenAIConnector(get_openai_client()),
)

# Initialize Claude agent for review/opinion
Expand All @@ -36,7 +36,7 @@ def demonstrate_conversation_handoff():
system_prompt="""You are a critical reviewer and second opinion provider. Review the
previous conversation and provide your perspective, critique, or alternative viewpoint.
Be constructive but don't hesitate to disagree if you have a different opinion.""",
connector=ClaudeConnector(get_claude_client())
connector=ClaudeConnector(get_claude_client()),
)

# Step 1: Ask OpenAI agent a technical question
Expand All @@ -48,8 +48,7 @@ def demonstrate_conversation_handoff():
"""

openai_response, openai_chat_history = openai_agent.execute_user_ask(
user_input=question,
model="gpt-5-nano"
user_input=question, model="gpt-5-nano"
)

print(f"OpenAI Response:\n{openai_response}\n")
Expand All @@ -60,9 +59,7 @@ def demonstrate_conversation_handoff():
followup = "What about the deployment and monitoring complexity differences?"

openai_response2, updated_chat_history = openai_agent.execute_user_ask(
user_input=followup,
chat_history=openai_chat_history,
model="gpt-5-nano"
user_input=followup, chat_history=openai_chat_history, model="gpt-5-nano"
)

print(f"OpenAI Follow-up Response:\n{openai_response2}\n")
Expand All @@ -86,7 +83,7 @@ def demonstrate_conversation_handoff():
claude_response, final_chat_history = claude_agent.execute_user_ask(
user_input=claude_review_prompt,
chat_history=updated_chat_history, # Pass the OpenAI conversation history
model="claude-3-5-sonnet-20241022"
model="claude-3-5-sonnet-20241022",
)

print(f"Claude's Review:\n{claude_response}\n")
Expand All @@ -95,14 +92,14 @@ def demonstrate_conversation_handoff():
# Step 4: Show the complete conversation flow
print("\n=== Complete Conversation Flow ===")
for i, message in enumerate(final_chat_history):
role = message.get('role', 'unknown')
content = message.get('content', '')
role = message.get("role", "unknown")
content = message.get("content", "")
if isinstance(content, list):
# Handle multimodal content
text_content = ""
for item in content:
if isinstance(item, dict) and item.get('type') == 'text':
text_content += item.get('text', '')
if isinstance(item, dict) and item.get("type") == "text":
text_content += item.get("text", "")
content = text_content

print(f"\n[{i+1}] {role.upper()}:")
Expand All @@ -122,14 +119,14 @@ def demonstrate_multi_agent_discussion():
name="OpenAI_Optimist",
system_prompt="""You are an optimistic technology enthusiast. You tend to focus on
the benefits and potential of new technologies. Be encouraging and highlight opportunities.""",
connector=OpenAIConnector(get_openai_client())
connector=OpenAIConnector(get_openai_client()),
)

claude_agent = MultiModalAgent(
name="Claude_Skeptic",
system_prompt="""You are a thoughtful skeptic. You consider risks, challenges, and
potential downsides. You're not negative, but you ensure all perspectives are considered.""",
connector=ClaudeConnector(get_claude_client())
connector=ClaudeConnector(get_claude_client()),
)

# Start discussion
Expand All @@ -139,26 +136,25 @@ def demonstrate_multi_agent_discussion():

# Round 1: OpenAI's perspective
openai_response, chat_history = openai_agent.execute_user_ask(
user_input=topic,
model="gpt-4o"
user_input=topic, model="gpt-4o"
)
print(f"OpenAI (Optimist) says:\n{openai_response}\n")

# Round 1: Claude's counter-perspective
claude_prompt = "Please respond to the previous argument. What are your thoughts and concerns?"
claude_prompt = (
"Please respond to the previous argument. What are your thoughts and concerns?"
)
claude_response, chat_history = claude_agent.execute_user_ask(
user_input=claude_prompt,
chat_history=chat_history,
model="claude-3-5-sonnet-20241022"
model="claude-3-5-sonnet-20241022",
)
print(f"Claude (Skeptic) responds:\n{claude_response}\n")

# Round 2: OpenAI addresses Claude's concerns
openai_counter = "Please address the concerns raised and provide counter-arguments."
openai_response2, chat_history = openai_agent.execute_user_ask(
user_input=openai_counter,
chat_history=chat_history,
model="gpt-5-nano"
user_input=openai_counter, chat_history=chat_history, model="gpt-5-nano"
)
print(f"OpenAI counters:\n{openai_response2}\n")

Expand All @@ -169,7 +165,7 @@ def demonstrate_multi_agent_discussion():
final_response, final_history = claude_agent.execute_user_ask(
user_input=synthesis_prompt,
chat_history=chat_history,
model="claude-3-5-sonnet-latest"
model="claude-3-5-sonnet-latest",
)
print(f"Final Synthesis:\n{final_response}\n")

Expand All @@ -187,10 +183,12 @@ def demonstrate_multi_agent_discussion():
print(f"\n=== Summary ===")
print(f"First example generated {len(chat_history1)} total messages")
print(f"Second example generated {len(chat_history2)} total messages")
print("Both examples demonstrate successful conversation handoff between different AI providers!")
print(
"Both examples demonstrate successful conversation handoff between different AI providers!"
)

except Exception as e:
print(f"Error running examples: {e}")
print("Make sure you have set your API keys in environment variables:")
print("- OPENAI_API_KEY")
print("- ANTHROPIC_API_KEY")
print("- ANTHROPIC_API_KEY")
Loading
Loading