Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
8961b02
initial changes
allenanie Oct 3, 2025
949d8ff
make context optional
allenanie Oct 3, 2025
e36dd7c
finish adding image support to optoprime_v2
allenanie Oct 3, 2025
7dcb880
Finish updating OPRO to accept additional context
allenanie Oct 3, 2025
8a31e8b
add context prompt into pickle save/load. Modify `test_priority_searc…
allenanie Oct 5, 2025
f8a0958
merge experimental branch updates
allenanie Oct 5, 2025
c271d9c
comment out the small-LLM test
allenanie Oct 5, 2025
709a08a
Merge branch 'experimental' of https://github.com/AgentOpt/OpenTrace …
allenanie Oct 6, 2025
148d4bc
add multi-modal support for the LLM model as well
allenanie Oct 6, 2025
b340d91
update the image-context prompt on optimizer. Make LLM module better.
allenanie Oct 6, 2025
acae873
fix a bug on QueryModel not handling Node as input
allenanie Oct 6, 2025
1791b15
add three types of image loading: from numpy array, from url, from lo…
allenanie Nov 10, 2025
502dd7a
Merge branch 'experimental' into features/multimodal_opt
allenanie Nov 10, 2025
51dfc4b
Update opto/optimizers/optoprime_v2.py
allenanie Nov 10, 2025
978fdf6
Initial plan
Copilot Nov 10, 2025
1fda4d7
Merge pull request #54 from AgentOpt/copilot/sub-pr-50
allenanie Nov 10, 2025
34f9747
Update opto/optimizers/optoprime_v2.py
allenanie Nov 10, 2025
0118979
Update opto/optimizers/optoprime_v2.py
allenanie Nov 10, 2025
a32136e
Update opto/optimizers/opro_v2.py
allenanie Nov 10, 2025
52d5eb0
Update opto/features/flows/types.py
allenanie Nov 10, 2025
d502eeb
Update opto/optimizers/optoprime_v2.py
allenanie Nov 10, 2025
e511a85
Update opto/features/flows/compose.py
allenanie Nov 10, 2025
2633ac7
Update opto/optimizers/optoprime_v2.py
allenanie Nov 10, 2025
bbe1b40
partial commit
allenanie Nov 10, 2025
d2fe092
Merge branch 'features/multimodal_opt' of https://github.com/AgentOpt…
allenanie Nov 10, 2025
ee6537c
Merge branch 'experimental' of https://github.com/AgentOpt/OpenTrace …
allenanie Nov 21, 2025
a4057ef
add a `is_image` check to Node
allenanie Nov 22, 2025
f6ce6b7
add parameter check to ensure 1 image can be parameter
allenanie Nov 22, 2025
aa96807
fix the import error
allenanie Nov 22, 2025
172d00f
refactored/moved out image data check
allenanie Nov 26, 2025
40dfdab
fix a few optimizer test issues, update setup dependencies to include…
allenanie Dec 1, 2025
85edcdc
add protected rounds
allenanie Dec 1, 2025
82a590d
add content block
allenanie Dec 1, 2025
f3668fc
intermediate commit
allenanie Dec 2, 2025
6bace1c
update actual call to ensure API correctness
allenanie Dec 2, 2025
79b9d58
fix opro_v3 issues
allenanie Dec 2, 2025
3d3f8a1
update python dependency
allenanie Dec 2, 2025
240f319
update the tests (it was broken before)
allenanie Dec 3, 2025
a077717
add new workflow tests conditions to avoid long build time on experim…
allenanie Dec 16, 2025
e01ddc8
partial refactoring. Reworked `add_context` to support interleaved im…
allenanie Dec 16, 2025
a8a0c3a
continued refactoring...
allenanie Dec 17, 2025
7ff308d
Adding prompt template to accommondate multi-modal fill-in
allenanie Dec 17, 2025
5ee4860
final update to both backbone and adding context.
allenanie Dec 17, 2025
f451250
updating to take feedback as image.
allenanie Dec 17, 2025
1122d8b
image as feedback is now roughly correct
allenanie Dec 17, 2025
781b7ce
remove not needed files
allenanie Dec 17, 2025
095e7f7
add back minibatch.ipynb
allenanie Dec 17, 2025
7221e61
refactored LLMFactory -- removing "cheap", "premium" descriptions bec…
allenanie Dec 22, 2025
8becf51
Add GoogleGenAILLM backend. Reworked the LLM logic. Added test cases …
allenanie Dec 27, 2025
8777528
fix test errors
allenanie Dec 27, 2025
2252ccd
updated google genai llm to turn litellm format history messages into…
allenanie Dec 27, 2025
c171201
amend
allenanie Dec 27, 2025
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
30 changes: 15 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
name: CI
name: Full CI (with Ollama)

on:
push:
branches: [ main, dev, experimental, ci-multi ]
pull_request:
branches: [ main, dev, experimental, ci-multi ]
branches: [ main ]
# Manual trigger for testing or major releases
workflow_dispatch:

jobs:
test:
full-test:
runs-on: ubuntu-latest
timeout-minutes: 180

steps:
- name: Checkout code
uses: actions/checkout@v4

# 1) Restore any cached Ollama data (~2 GB)
# 1) Restore any cached Ollama data
- name: Restore Ollama cache
uses: actions/cache@v4
with:
path: ~/.ollama
key: qwen3-4b-gguf-v1
key: qwen3-vl-2b-v1

# 2) Install Ollama
- name: Install Ollama
Expand All @@ -43,13 +43,13 @@ jobs:
run: |
sudo systemctl enable --now ollama

# 5) Pull the phi4-mini:3.8b model (uses cache if present)
- name: Pull phi4-mini:3.8b model
run: ollama pull phi4-mini:3.8b
# 5) Pull the qwen3-vl:2b model - supports multimodal/vision with OpenAI-compatible API
- name: Pull qwen3-vl:2b model (multimodal)
run: ollama pull qwen3-vl:2b

# 6) Set up Python & install dependencies
- uses: actions/setup-python@v5
with: { python-version: "3.10" }
with: { python-version: "3.13" }
- name: Install Python deps
run: |
pip install -e .
Expand All @@ -60,13 +60,13 @@ jobs:
run: |
echo "OPENAI_API_KEY=ollama" >> $GITHUB_ENV
echo "OPENAI_API_BASE=http://localhost:11434/v1" >> $GITHUB_ENV
echo "TRACE_LITELLM_MODEL=openai/phi4-mini:3.8b" >> $GITHUB_ENV
echo "TRACE_LITELLM_MODEL=openai/qwen3-vl:2b" >> $GITHUB_ENV

# 8) Run all Trace unit tests
- name: Run unit tests
run: pytest tests/unit_tests/

# 9) Run basic tests for each optimizer (some will fail due to the small LLM model chosen for free GitHub CI)
- name: Run optimizers test suite
run: pytest tests/llm_optimizers_tests/test_optimizer.py || true
continue-on-error: true
# - name: Run optimizers test suite
# run: pytest tests/llm_optimizers_tests/test_optimizer.py || true
# continue-on-error: true
4 changes: 2 additions & 2 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:

steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.13
uses: actions/setup-python@v3
with:
python-version: "3.10"
python-version: "3.13"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Unit Tests

on:
push:
branches: [ experimental, dev ]
pull_request:
branches: [ main, experimental, dev ]

jobs:
unit-tests:
runs-on: ubuntu-latest
timeout-minutes: 15

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"

- name: Install Python dependencies
run: |
pip install -e .
pip install pytest numpy

- name: Run unit tests
run: pytest tests/unit_tests/ -v

22 changes: 11 additions & 11 deletions docs/tutorials/minibatch.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -601,11 +601,11 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[Step 1] \u001b[92mAverage test score: 1.0\u001b[0m\n",
"[Step 1] \u001B[92mAverage test score: 1.0\u001B[0m\n",
"Epoch: 0. Iteration: 1\n",
"[Step 1] Instantaneous train score: 1.0\n",
"[Step 1] Average train score: 1.0\n",
"[Step 1] \u001b[91mParameter: str:20: You're a helpful agent\u001b[0m\n"
"[Step 1] \u001B[91mParameter: str:20: You're a helpful agent\u001B[0m\n"
]
},
{
Expand Down Expand Up @@ -641,11 +641,11 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[Step 2] \u001b[92mAverage test score: 1.0\u001b[0m\n",
"[Step 2] \u001B[92mAverage test score: 1.0\u001B[0m\n",
"Epoch: 0. Iteration: 2\n",
"[Step 2] Instantaneous train score: 1.0\n",
"[Step 2] Average train score: 1.0\n",
"[Step 2] \u001b[91mParameter: str:20: You're a helpful agent\u001b[0m\n"
"[Step 2] \u001B[91mParameter: str:20: You're a helpful agent\u001B[0m\n"
]
},
{
Expand Down Expand Up @@ -677,11 +677,11 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[Step 3] \u001b[92mAverage test score: 1.0\u001b[0m\n",
"[Step 3] \u001B[92mAverage test score: 1.0\u001B[0m\n",
"Epoch: 0. Iteration: 3\n",
"[Step 3] Instantaneous train score: 1.0\n",
"[Step 3] Average train score: 1.0\n",
"[Step 3] \u001b[91mParameter: str:20: You're a helpful agent\u001b[0m\n"
"[Step 3] \u001B[91mParameter: str:20: You're a helpful agent\u001B[0m\n"
]
},
{
Expand Down Expand Up @@ -714,11 +714,11 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[Step 4] \u001b[92mAverage test score: 1.0\u001b[0m\n",
"[Step 4] \u001B[92mAverage test score: 1.0\u001B[0m\n",
"Epoch: 0. Iteration: 4\n",
"[Step 4] Instantaneous train score: 1.0\n",
"[Step 4] Average train score: 1.0\n",
"[Step 4] \u001b[91mParameter: str:20: You're a helpful agent\u001b[0m\n"
"[Step 4] \u001B[91mParameter: str:20: You're a helpful agent\u001B[0m\n"
]
},
{
Expand Down Expand Up @@ -751,11 +751,11 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[Step 5] \u001b[92mAverage test score: 1.0\u001b[0m\n",
"[Step 5] \u001B[92mAverage test score: 1.0\u001B[0m\n",
"Epoch: 0. Iteration: 5\n",
"[Step 5] Instantaneous train score: 1.0\n",
"[Step 5] Average train score: 1.0\n",
"[Step 5] \u001b[91mParameter: str:20: You're a helpful agent\u001b[0m\n",
"[Step 5] \u001B[91mParameter: str:20: You're a helpful agent\u001B[0m\n",
"FINISHED TRAINING\n"
]
},
Expand Down Expand Up @@ -831,4 +831,4 @@
},
"nbformat": 4,
"nbformat_minor": 2
}
}
18 changes: 13 additions & 5 deletions opto/features/flows/compose.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import opto.trace as trace
from typing import Union, get_type_hints, Any, Dict, List, Optional
from opto.utils.llm import AbstractModel, LLM
from opto.features.flows.types import MultiModalPayload, QueryModel
import contextvars

"""
Expand Down Expand Up @@ -157,6 +158,7 @@ def __init__(self,
system_prompt: The system prompt to use for LLM calls. If None and the class has a docstring, the docstring will be used.
llm: The LLM model to use for inference
chat_history_on: if on, maintain chat history for multi-turn conversations
model_name: override the default name of the model
"""
if system_prompt is None:
system_prompt = "You are a helpful assistant."
Expand All @@ -178,7 +180,9 @@ def __init__(self,
self.model_name = model_name if model_name else f"{self.__class__.__name__}{len(current_llm_sessions)}"
current_llm_sessions.append(1) # just a marker

def forward(self, user_query: str, chat_history_on: Optional[bool] = None) -> str:
def forward(self, user_query: str,
payload: Optional[MultiModalPayload] = None,
chat_history_on: Optional[bool] = None) -> str:
"""This function takes user_query as input, and returns the response from the LLM, with the system prompt prepended.
This method will always save chat history.

Expand All @@ -187,17 +191,19 @@ def forward(self, user_query: str, chat_history_on: Optional[bool] = None) -> st
If chat_history_on is True, the chat history will be included in the LLM input.

Args:
user_query: The user query to send to the LLM
user_query: The user query to send to the LLM. This should be a string containing the user's input or question.

Returns:
str: For direct pattern
"""
chat_history_on = self.chat_history_on if chat_history_on is None else chat_history_on

user_message = QueryModel(query=user_query, multimodal_payload=payload).query

messages = [{"role": "system", "content": self.system_prompt.data}]
if chat_history_on:
messages.extend(self.chat_history.get_messages())
messages.append({"role": "user", "content": user_query})
messages.append({"role": "user", "content": user_message})

response = self.llm(messages=messages)

Expand Down Expand Up @@ -225,5 +231,7 @@ def call_llm(*messages) -> str:

return response_node

def chat(self, user_query: str) -> str:
return self.forward(user_query)
def chat(self, user_query: str, payload: Optional[MultiModalPayload] = None, chat_history_on: Optional[bool] = None) -> str:
"""Note that chat/forward always assumes it's a single turn of the conversation. History/context management will be accomplished
through other APIs"""
return self.forward(user_query, payload, chat_history_on)
Loading