Ready for first real test
This commit is contained in:
1 parent
acddf9135f
commit
b91c81ebdf
46 files changed
+34903
-26
No files matched your search
+31
-11
@@ -41,11 +41,22 @@ RESEARCH_KICKOFF = (
|
||||
"call get_option_chain(underlying, 'call' or 'put') and copy an exact contract_symbol."
|
||||
)
|
||||
|
||||
DEEPEN_NUDGE = (
|
||||
"You're not finished. Keep researching before finalizing: evaluate additional candidate "
|
||||
"tickers you haven't examined yet, pull bars/news/fundamentals for them, verify with "
|
||||
"web_search, and stress-test your leading ideas against the alternatives. Continue using tools."
|
||||
)
|
||||
# Rotating directive nudges — cycled so a long (~2hr) research session stays PRODUCTIVE
|
||||
# (does new, varied work) instead of looping "am I done?". Keep using tools.
|
||||
DEEPEN_NUDGES = [
|
||||
"Not done yet. Screen 5-10 MORE candidate tickers in your style you haven't examined; pull "
|
||||
"get_bars / get_news / get_fundamentals on them.",
|
||||
"Build the BEAR case for your current top pick: what would make it wrong? Find data that "
|
||||
"challenges your thesis (web_search + web_fetch recent coverage).",
|
||||
"Use run_analysis to write a real script: fetch prices with yfinance, compute momentum / "
|
||||
"moving averages / volatility / correlations, and save a chart to back your best idea.",
|
||||
"Zoom out: check the macro + sector context (rates, the sector ETF, peers) via web_search and "
|
||||
"get_bars. Does it support or undercut your picks?",
|
||||
"Compare your leading picks head-to-head against 2-3 sector peers on valuation and momentum "
|
||||
"(get_fundamentals + run_analysis). Are you picking the best expression of the thesis?",
|
||||
"Re-examine catalysts and timing for each candidate (earnings dates, events via get_news / "
|
||||
"web_search) and refine entry, stop, and take-profit levels with run_python.",
|
||||
]
|
||||
|
||||
FINALIZE_PROMPT = (
|
||||
"Research complete. Return a JSON object of the form {{\"picks\": [ ... ]}} containing about "
|
||||
@@ -176,6 +187,7 @@ def run_agent(
|
||||
deadline_ts: float,
|
||||
step_budget: int,
|
||||
min_steps: int = 0,
|
||||
min_seconds: float = 0.0,
|
||||
checkpointer=None,
|
||||
model_name: str = "",
|
||||
) -> AgentOutput:
|
||||
@@ -195,6 +207,7 @@ def run_agent(
|
||||
running_summary = ""
|
||||
reasoning_trace: list[str] = []
|
||||
steps_used = 0
|
||||
nudge_count = 0
|
||||
ended_reason = "natural"
|
||||
|
||||
def snapshot(status: AgentStatus, picks: list[Pick] | None = None, errors=None) -> AgentOutput:
|
||||
@@ -229,11 +242,16 @@ def run_agent(
|
||||
|
||||
tool_calls = getattr(ai, "tool_calls", None)
|
||||
if not tool_calls:
|
||||
# Force depth: if the model wants to stop early, nudge it to keep researching
|
||||
# until it has done at least min_steps (still bounded by the wall-clock deadline).
|
||||
if steps_used < min_steps and time.time() < deadline_ts:
|
||||
messages.append(HumanMessage(content=DEEPEN_NUDGE))
|
||||
reasoning_trace.append(f"[nudge] deepen research ({steps_used}/{min_steps} steps)")
|
||||
# Force depth: if the model tries to finalize before the TIME floor (or step floor),
|
||||
# inject a rotating directive nudge so it keeps doing NEW research. Bounded by deadline.
|
||||
elapsed = time.time() - start
|
||||
if (elapsed < min_seconds or steps_used < min_steps) and time.time() < deadline_ts:
|
||||
nudge = DEEPEN_NUDGES[nudge_count % len(DEEPEN_NUDGES)]
|
||||
nudge_count += 1
|
||||
messages.append(HumanMessage(content=nudge))
|
||||
reasoning_trace.append(
|
||||
f"[nudge #{nudge_count}] {elapsed/60:.0f}/{min_seconds/60:.0f}min elapsed, step {steps_used}"
|
||||
)
|
||||
continue
|
||||
if ai.content:
|
||||
reasoning_trace.append(f"[note] {str(ai.content)[:200]}")
|
||||
@@ -241,7 +259,9 @@ def run_agent(
|
||||
break
|
||||
|
||||
for tc in tool_calls:
|
||||
name, args = tc["name"], tc.get("args", {}) or {}
|
||||
# gpt-oss can leak harmony channel tokens into the tool name (e.g. "get_bars<|channel|>")
|
||||
name = tc["name"].split("<|")[0].strip()
|
||||
args = tc.get("args", {}) or {}
|
||||
tool = tools_by_name.get(name)
|
||||
try:
|
||||
result = tool.invoke(args) if tool else f"ERROR: unknown tool {name}"
|
||||
|
||||
Reference in new issue
Block a user