stillerman HF Staff commited on
Commit
2d4d9a8
Β·
1 Parent(s): 44bd370

working agent

Browse files
Files changed (2) hide show
  1. .gitignore +2 -1
  2. agent.py +156 -106
.gitignore CHANGED
@@ -1,3 +1,4 @@
1
  *.bz2
2
  data
3
- __pycache__
 
 
1
  *.bz2
2
  data
3
+ __pycache__
4
+ .env
agent.py CHANGED
@@ -1,136 +1,186 @@
1
- # LLM agent player using HuggingFace's smolagent
2
- from wiki_run_engine import WikiRunEnvironment
3
  from rich.console import Console
 
 
 
 
 
 
 
 
 
4
 
5
- console = Console()
6
-
7
- try:
8
- from smolagent import Agent, AgentConfig
9
- except ImportError:
10
- console.print("[red]smolagent package not found. Please install with 'uv pip install smolagent'[/red]")
11
- raise
12
 
13
- class AgentPlayer:
14
- def __init__(self, wiki_data_path, model_name="HuggingFaceH4/zephyr-7b-beta"):
15
- """Initialize agent player"""
16
  self.env = WikiRunEnvironment(wiki_data_path)
 
 
17
 
18
- # Initialize LLM agent
19
- config = AgentConfig(
20
- model=model_name,
21
- output_parser="json"
22
- )
23
- self.agent = Agent(config)
24
-
25
- def play(self, start_article=None, target_article=None, max_steps=20):
26
- """Play a game of Wiki Run using the LLM agent"""
27
- # Reset environment
28
  state = self.env.reset(start_article, target_article)
29
 
30
- console.print("[bold]Agent Wiki Run[/bold]")
31
- console.print(f"Starting article: [cyan]{state['current_article']}[/cyan]")
32
- console.print(f"Target article: [red]{state['target_article']}[/red]")
33
- console.print()
34
 
35
- steps = 0
36
- while not state['is_complete'] and steps < max_steps:
37
- console.print(f"[bold]Step {steps + 1}:[/bold]")
38
- console.print(f"Current article: [cyan]{state['current_article']}[/cyan]")
39
-
40
- # Create prompt for agent
41
- prompt = self._create_agent_prompt(state)
42
-
43
- # Get agent's decision
44
- tool_result = self.agent.run(
45
- prompt,
46
- tools=[
47
- {
48
- "name": "choose_next_article",
49
- "description": "Choose the next Wikipedia article to navigate to",
50
- "parameters": {
51
- "type": "object",
52
- "properties": {
53
- "article": {
54
- "type": "string",
55
- "description": "The title of the next article to navigate to"
56
- },
57
- "reasoning": {
58
- "type": "string",
59
- "description": "Explanation of why this article was chosen"
60
- }
61
- },
62
- "required": ["article", "reasoning"]
63
- }
64
- }
65
- ]
66
- )
67
 
68
- # Extract agent's choice
69
- choice = tool_result.get("choose_next_article", {})
70
- next_article = choice.get("article", "")
71
- reasoning = choice.get("reasoning", "")
72
 
73
- console.print(f"[yellow]Agent reasoning: {reasoning}[/yellow]")
74
- console.print(f"Agent chooses: [green]{next_article}[/green]")
75
-
76
- # Verify the choice is valid
77
- if next_article in state['available_links']:
78
- state, message = self.env.step(next_article)
79
- if message:
80
- console.print(f"[bold]{message}[/bold]")
81
- else:
82
- console.print("[red]Invalid choice! Agent selected an article that's not in the available links.[/red]")
83
- # Choose a random valid link as fallback
84
- import random
85
- next_article = random.choice(state['available_links'])
86
- console.print(f"[yellow]Falling back to random choice: {next_article}[/yellow]")
87
- state, _ = self.env.step(next_article)
88
 
89
- steps += 1
90
- console.print()
91
-
92
- # Game complete
93
- if state['is_complete']:
94
- console.print("[bold green]Success! Agent reached the target article![/bold green]")
95
- else:
96
- console.print("[bold red]Failed to reach target within step limit.[/bold red]")
97
-
98
- console.print(f"Steps taken: [bold]{state['steps_taken']}[/bold]")
99
- console.print(f"Path: [italic]{' β†’ '.join(state['path_taken'])}[/italic]")
100
-
 
 
 
 
101
  return state
102
 
103
- def _create_agent_prompt(self, state):
104
- """Create prompt for the agent"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  current = state['current_article']
106
  target = state['target_article']
107
- links = state['available_links']
 
 
108
 
109
- prompt = f"""You are playing the Wiki Run game. Your goal is to navigate from the current Wikipedia article to the target article using only the available links.
110
-
111
  Current article: {current}
112
  Target article: {target}
 
 
113
 
114
- Available links (choose one):
115
- {', '.join(links)}
116
-
117
- Choose the link that you think will get you closest to the target article. Consider:
118
- 1. Direct connections to the target
119
- 2. Articles that might be in the same category as the target
120
- 3. General articles that might have many links to other topics
121
 
122
- Use the choose_next_article tool to make your selection."""
 
 
 
123
 
124
- return prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
  if __name__ == "__main__":
127
  import sys
128
 
129
  if len(sys.argv) < 2:
130
- console.print("[red]Please provide the path to Wikipedia data[/red]")
 
131
  console.print("Usage: python agent.py <wiki_data_path>")
132
  sys.exit(1)
 
 
 
 
133
 
134
  wiki_data_path = sys.argv[1]
135
- agent = AgentPlayer(wiki_data_path)
136
- agent.play()
 
 
1
+ import litellm
 
2
  from rich.console import Console
3
+ from rich.panel import Panel
4
+ from rich.markdown import Markdown
5
+ from rich.table import Table
6
+ from rich.box import SIMPLE
7
+ from wiki_run_engine import WikiRunEnvironment
8
+ from langsmith import traceable
9
+ import os
10
+ from openai import OpenAI
11
+ from langsmith.wrappers import wrap_openai
12
 
13
+ openai_client = wrap_openai(OpenAI())
 
 
 
 
 
 
14
 
15
+ class WikiRunAgent:
16
+ def __init__(self, wiki_data_path, model="gemini/gemini-2.5-pro-exp-03-25"):
 
17
  self.env = WikiRunEnvironment(wiki_data_path)
18
+ self.model = model
19
+ self.console = Console()
20
 
21
+ @traceable(name="WikiRun Game")
22
+ def run_game(self, start_article=None, target_article=None):
23
+ """Play the WikiRun game with LLM agent"""
 
 
 
 
 
 
 
24
  state = self.env.reset(start_article, target_article)
25
 
26
+ self.console.print(Panel(f"[bold cyan]Starting WikiRun![/bold cyan]"))
27
+ self.console.print(f"[bold green]Starting at:[/bold green] {state['current_article']}")
28
+ self.console.print(f"[bold red]Target:[/bold red] {state['target_article']}\n")
 
29
 
30
+ while not state['is_complete']:
31
+ # Display current game status
32
+ self._display_game_status(state)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
+ # Get LLM's choice
35
+ choice = self._get_llm_choice(state)
36
+ self.console.print(f"\n[bold yellow]Agent chooses:[/bold yellow] {choice}")
 
37
 
38
+ # Process the choice
39
+ available_links = self._get_available_links(state['available_links'])
40
+ if not available_links:
41
+ self.console.print("[bold red]No available links to choose from![/bold red]")
42
+ break
 
 
 
 
 
 
 
 
 
 
43
 
44
+ try:
45
+ # If choice is a number
46
+ idx = int(choice) - 1
47
+ if 0 <= idx < len(available_links):
48
+ next_article = available_links[idx]
49
+ self.console.print(f"[bold cyan]Moving to:[/bold cyan] {next_article}\n")
50
+ state, message = self.env.step(next_article)
51
+ if message:
52
+ self.console.print(f"[bold]{message}[/bold]")
53
+ else:
54
+ self.console.print("[bold red]Invalid choice. Trying again.[/bold red]\n")
55
+ except ValueError:
56
+ self.console.print("[bold red]Invalid choice format. Trying again.[/bold red]\n")
57
+
58
+ self.console.print(Panel(f"[bold green]Game completed in {state['steps_taken']} steps[/bold green]"))
59
+ self.console.print(f"[bold]Path:[/bold] {' β†’ '.join(state['path_taken'])}")
60
  return state
61
 
62
+ def _display_game_status(self, state):
63
+ """Display current game status with rich formatting"""
64
+ # Display current article
65
+ self.console.print(Panel(f"[bold cyan]{state['current_article']}[/bold cyan]",
66
+ expand=False,
67
+ border_style="cyan"))
68
+
69
+ # Display article links
70
+ self.console.print("[bold green]Available Links:[/bold green]")
71
+ self._display_links(state['available_links'])
72
+
73
+ # Display path so far
74
+ self.console.print(f"\n[bold yellow]Steps taken:[/bold yellow] {state['steps_taken']}")
75
+ if state['path_taken']:
76
+ self.console.print(f"[bold yellow]Path so far:[/bold yellow] {' β†’ '.join(state['path_taken'])}")
77
+
78
+ def _display_links(self, links):
79
+ """Display links in a nicely formatted table"""
80
+ table = Table(show_header=False, box=SIMPLE)
81
+ table.add_column("Number", style="dim")
82
+ table.add_column("Link", style="green")
83
+ table.add_column("Available", style="bold")
84
+
85
+ for i, link in enumerate(links):
86
+ # Check if link is available
87
+ is_available = link in self.env.wiki_data
88
+ status = "[green]βœ“[/green]" if is_available else "[red]βœ—[/red]"
89
+ color = "green" if is_available else "red"
90
+ table.add_row(
91
+ f"{i+1}",
92
+ f"[{color}]{link}[/{color}]",
93
+ status
94
+ )
95
+
96
+ self.console.print(table)
97
+
98
+ def _get_available_links(self, links):
99
+ """Filter links to only those available in the wiki data"""
100
+ return [link for link in links if link in self.env.wiki_data]
101
+
102
+ @traceable(name="LLM Decision")
103
+ def _get_llm_choice(self, state):
104
+ """Ask LLM for next move"""
105
  current = state['current_article']
106
  target = state['target_article']
107
+ all_links = state['available_links']
108
+ available_links = self._get_available_links(all_links)
109
+ path_so_far = state['path_taken']
110
 
111
+ # Create prompt with relevant context (not the full article)
112
+ prompt = f"""You are playing WikiRun, trying to navigate from one Wikipedia article to another using only links.
113
  Current article: {current}
114
  Target article: {target}
115
+ Available links (numbered):
116
+ {self._format_links(available_links)}
117
 
118
+ Your path so far: {' -> '.join(path_so_far)}
 
 
 
 
 
 
119
 
120
+ Think about which link is most likely to lead you toward the target article.
121
+ First, think step by step about your strategy.
122
+ Then output your choice as a number in this format: <choice>N</choice> where N is the link number.
123
+ """
124
 
125
+ # Call LLM via litellm with langsmith tracing
126
+ response = litellm.completion(
127
+ model=self.model,
128
+ messages=[{"role": "user", "content": prompt}],
129
+ # metadata={
130
+ # "current_article": current,
131
+ # "target_article": target,
132
+ # "available_links": available_links,
133
+ # "steps_taken": state['steps_taken'],
134
+ # "path_so_far": path_so_far
135
+ # }
136
+ )
137
+
138
+ # Extract the choice from response
139
+ content = response.choices[0].message.content
140
+ self.console.print(Panel(Markdown(content), title="[bold]Agent Thinking[/bold]", border_style="yellow"))
141
+
142
+ # Extract choice using format <choice>N</choice>
143
+ import re
144
+ choice_match = re.search(r'<choice>(\d+)</choice>', content)
145
+ if choice_match:
146
+ return choice_match.group(1)
147
+ else:
148
+ # Fallback: try to find any number in the response
149
+ numbers = re.findall(r'\d+', content)
150
+ if numbers:
151
+ for num in numbers:
152
+ if 1 <= int(num) <= len(available_links):
153
+ return num
154
+ # Default to first link if no valid choice found
155
+ return "1" if available_links else "0"
156
+
157
+ def _format_links(self, links):
158
+ """Format the list of links for the prompt"""
159
+ return "\n".join([f"{i+1}. {link}" for i, link in enumerate(links)])
160
+
161
+ def setup_langsmith():
162
+ """Print instructions for setting up LangSmith tracing"""
163
+ console = Console()
164
+ console.print(Panel("[bold yellow]LangSmith Setup Instructions[/bold yellow]"))
165
+ console.print("To enable LangSmith tracing, set the following environment variables:")
166
+ console.print("[bold]export LANGSMITH_API_KEY='your-api-key'[/bold]")
167
+ console.print("Get your API key from: https://smith.langchain.com/settings")
168
+ console.print("Once set, your WikiRun agent will log traces to your LangSmith dashboard")
169
 
170
  if __name__ == "__main__":
171
  import sys
172
 
173
  if len(sys.argv) < 2:
174
+ console = Console()
175
+ console.print("[bold red]Please provide the path to Wikipedia data[/bold red]")
176
  console.print("Usage: python agent.py <wiki_data_path>")
177
  sys.exit(1)
178
+
179
+ # Remind about LangSmith setup
180
+ if not os.environ.get("LANGSMITH_API_KEY"):
181
+ setup_langsmith()
182
 
183
  wiki_data_path = sys.argv[1]
184
+ agent = WikiRunAgent(wiki_data_path)
185
+ agent.run_game(start_article="Peanut", target_article="Silicon Valley")
186
+ # agent.run_game(start_article="Silicon Valley", target_article="Peanut")