Skip to content

Commit 1bd3afd

Browse files
committed
WIP
1 parent 4626a56 commit 1bd3afd

File tree

1 file changed

+58
-62
lines changed

1 file changed

+58
-62
lines changed

examples/investment_portfolio.exs

Lines changed: 58 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ defmodule MockInvestmentProvider do
2424
- Client risk preferences
2525
- Previous tool execution outcomes
2626
27-
Unlike static DAG workflows, it dynamically chooses the next steps based on
27+
Unlike static DAG workflows, it dynamically chooses the next steps based on
2828
the evolving context and state.
2929
"""
3030

@@ -261,20 +261,6 @@ defmodule MockInvestmentProvider do
261261
]
262262
}}
263263

264-
"portfolio_backtester" ->
265-
{:ok,
266-
%{
267-
"choices" => [
268-
%{
269-
"message" => %{
270-
"content" =>
271-
"I couldn't complete the detailed backtest. Let me provide a simplified analysis instead.",
272-
"content_only" => true
273-
}
274-
}
275-
]
276-
}}
277-
278264
_ ->
279265
{:ok,
280266
%{
@@ -476,7 +462,7 @@ defmodule MockInvestmentProvider do
476462
end
477463
end
478464

479-
defp determine_risk_preference(question, current_profile) do
465+
defp determine_risk_preference(question, _current_profile) do
480466
question = String.downcase(question)
481467

482468
cond do
@@ -543,7 +529,7 @@ defmodule MockInvestmentProvider do
543529
# Response generation functions
544530
#
545531

546-
defp generate_contextual_response(context, question) do
532+
defp generate_contextual_response(context, _question) do
547533
cond do
548534
context.has_portfolio and context.has_backtest ->
549535
portfolio = context.portfolio
@@ -808,7 +794,7 @@ defmodule LLMAgent.Examples.InvestmentTools do
808794
fallback = Map.get(params, "fallback", false)
809795

810796
# Use ETFs provided in request or default set
811-
provided_etfs = Map.get(params, "etfs", nil)
797+
_provided_etfs = Map.get(params, "etfs", nil)
812798

813799
allocations =
814800
case {risk_profile, fallback} do
@@ -1029,16 +1015,16 @@ defmodule LLMAgent.Examples.InvestmentDemo do
10291015
5. Simulate performance in different market scenarios
10301016
10311017
When providing recommendations, consider:
1032-
- Current market conditions: #{Store.get(store_name, :market_volatility)}
1033-
- Interest rate environment: #{Store.get(store_name, :interest_rate_trend)}
1034-
- Economic outlook: #{Store.get(store_name, :economic_outlook)}
1018+
- Current market conditions: #{elem(Store.get(store_name, :market_volatility), 1)}
1019+
- Interest rate environment: #{elem(Store.get(store_name, :interest_rate_trend), 1)}
1020+
- Economic outlook: #{elem(Store.get(store_name, :economic_outlook), 1)}
10351021
10361022
Tailor your analysis approach to the client's knowledge level and goals.
10371023
Present your findings clearly with both technical detail and plain language explanations.
10381024
"""
10391025

10401026
# 5. Create conversation flow with investment tools
1041-
{flow, state} =
1027+
{flow, _fresh_state} =
10421028
Flows.tool_agent(
10431029
system_prompt,
10441030
LLMAgent.Examples.InvestmentTools.get_tools(),
@@ -1103,13 +1089,20 @@ defmodule LLMAgent.Examples.InvestmentDemo do
11031089
signal = Signals.user_message(input)
11041090

11051091
# Process through the investment flow
1106-
case Flow.process(flow, signal, current_state) do
1107-
{result, new_state} ->
1108-
display_response(result)
1092+
case flow.(signal, current_state) do
1093+
{:emit, %{type: :response} = response_signal, new_state} ->
1094+
display_response({:emit, response_signal})
11091095

11101096
# Store conversation progress in the store for stateful decisions
11111097
Store.put(store_name, :last_client_message, input)
1112-
store_result_data(store_name, result)
1098+
1099+
new_state
1100+
1101+
{:emit, %{type: :tool_result} = tool_signal, new_state} ->
1102+
display_response({:emit, tool_signal})
1103+
1104+
# Store tool result data
1105+
store_result_data(store_name, {:emit, tool_signal})
11131106

11141107
new_state
11151108

@@ -1120,6 +1113,10 @@ defmodule LLMAgent.Examples.InvestmentDemo do
11201113
Store.put(store_name, :last_error, error)
11211114

11221115
current_state
1116+
1117+
unexpected ->
1118+
IO.puts("Unexpected result: #{inspect(unexpected)}")
1119+
current_state
11231120
end
11241121
end)
11251122
end)
@@ -1128,19 +1125,18 @@ defmodule LLMAgent.Examples.InvestmentDemo do
11281125
IO.puts("\n=== Investment Agent Architecture ===")
11291126

11301127
IO.puts("""
1131-
11321128
This example demonstrates how LLMAgent builds dynamic workflows:
11331129
11341130
1. Signal-Based Decision Making:
1135-
The agent doesn't follow a predefined DAG, but instead makes decisions
1131+
The agent doesn't follow a predefined DAG, but instead makes decisions
11361132
based on evolving context and conversation state.
11371133
11381134
2. Tool Chaining with LLM Intelligence:
11391135
Unlike rule-based systems, the agent intelligently chains tools based on:
11401136
- Results of previous tool executions
11411137
- Client request analysis
11421138
- Contextual state information
1143-
1139+
11441140
3. Dynamic Path Selection:
11451141
The agent dynamically determines:
11461142
- Which tool to use next
@@ -1150,7 +1146,7 @@ defmodule LLMAgent.Examples.InvestmentDemo do
11501146
11511147
4. State Management:
11521148
The Store component maintains state across interactions:
1153-
- #{inspect(Store.get_all(store_name) |> Enum.count())} state keys tracked
1149+
- #{length(elem(Store.get_all(store_name), 1))} state keys tracked
11541150
- Analysis history preserved
11551151
- Tool results maintained for context
11561152
""")
@@ -1159,44 +1155,45 @@ defmodule LLMAgent.Examples.InvestmentDemo do
11591155
IO.puts("\nTo implement similar agents in your application, follow this pattern:")
11601156

11611157
IO.puts("""
1162-
11631158
1. Define domain-specific tools:
1164-
```elixir
1165-
tools = [
1166-
%{
1167-
name: "etf_screener",
1168-
description: "Screen ETFs based on criteria",
1169-
parameters: %{...},
1170-
execute: &screen_etfs/1
1171-
}
1172-
]
1173-
```
1174-
1159+
```elixir
1160+
tools = [
1161+
%{
1162+
name: "portfolio_analyzer",
1163+
description: "Analyze investment portfolios based on risk profile and goals",
1164+
parameters: %{
1165+
type: "object",
1166+
properties: %{
1167+
risk_profile: %{type: "string", enum: ["Conservative", "Moderate", "Aggressive"]}
1168+
}
1169+
}
1170+
}
1171+
]
1172+
```
1173+
11751174
2. Initialize store and create the agent:
1176-
```elixir
1177-
store_name = MyApp.InvestmentStore
1178-
{:ok, _} = LLMAgent.Store.start_link(name: store_name)
1179-
{flow, state} = LLMAgent.Flows.tool_agent(system_prompt, tools, store_name: store_name)
1180-
```
1181-
1175+
```elixir
1176+
store_name = MyApp.InvestmentStore
1177+
{flow, state} = LLMAgent.Flows.tool_agent(system_prompt, tools, store_name: store_name)
1178+
```
1179+
11821180
3. Process client requests:
1183-
```elixir
1184-
{result, new_state} = AgentForge.Flow.process(flow, Signals.user_message(request), state)
1185-
```
1186-
1181+
```elixir
1182+
{result, new_state} = AgentForge.Flow.process(flow, Signals.user_message(request), state)
1183+
```
1184+
11871185
4. Access stateful information:
1188-
```elixir
1189-
portfolio = AgentForge.Store.get(store_name, :current_portfolio)
1190-
history = LLMAgent.Store.get_llm_history(store_name)
1191-
```
1186+
```elixir
1187+
portfolio = AgentForge.Store.get(store_name, :current_portfolio)
1188+
history = LLMAgent.Store.get_llm_history(store_name)
11921189
""")
11931190
end
11941191

11951192
# Helper functions for demo
11961193

11971194
# Reset store between scenarios
11981195
defp reset_store(store_name) do
1199-
# Preserve system settings but clear scenario-specific data
1196+
# Reset store but preserve specific keys
12001197
preserved_keys = [
12011198
:market_volatility,
12021199
:interest_rate_trend,
@@ -1207,13 +1204,12 @@ defmodule LLMAgent.Examples.InvestmentDemo do
12071204
# Save values we want to keep
12081205
preserved_values =
12091206
preserved_keys
1210-
|> Enum.map(fn key -> {key, Store.get(store_name, key)} end)
1207+
|> Enum.map(fn key -> {key, elem(Store.get(store_name, key), 1)} end)
12111208
|> Map.new()
12121209

1213-
# Clear everything
1214-
Store.clear(store_name)
1210+
IO.puts("\n--- Resetting conversation state ---\n")
12151211

1216-
# Restore preserved values
1212+
# We will simply reset the values we want to keep
12171213
Enum.each(preserved_values, fn {key, value} ->
12181214
Store.put(store_name, key, value)
12191215
end)
@@ -1239,7 +1235,7 @@ defmodule LLMAgent.Examples.InvestmentDemo do
12391235

12401236
"market_simulator" ->
12411237
Store.put(store_name, :market_scenarios, [
1242-
result | Store.get(store_name, :market_scenarios) || []
1238+
result | elem(Store.get(store_name, :market_scenarios), 1) || []
12431239
])
12441240

12451241
_ ->

0 commit comments

Comments
 (0)