
Агенты ИИ для начинающих: построение вашего первого агента искусственного интеллекта
6 июня 2025 г.Агенты ИИ сейчас везде, и на то есть веская причина. Они преобразуют то, как мы взаимодействуем с программным обеспечением, выходя за рамки простых систем вопросов-ответов в инструменты, которые на самом деле могутделать что -тодля нас.
От ботов поддержки клиентов, которые могут обрабатывать возвраты средств до кодирующих помощников, которые могут исправлять ошибки в нескольких файлах, агенты становятся новым интерфейсом между людьми и сложными системами.
Но вот в чем дело: большинство "агентов" вы видитене совсемагенты вообще. Они просто чат -боты после сценария. Сегодня мы собираемся построить настоящего агента, который может думать, решать и действовать самостоятельно. И не волнуйтесь, мы будем держать это просто, чтобы даже новички могли легко следовать!
Давайте погрузимся! Но сначала,
Что делает настоящий агент ИИ?
Что мы имеем в виду под «настоящим агентом»?
Ключевое различие между истинным агентом и простой автоматизацией лежит вавтономия и динамическое принятие решенийПолем Давайте проиллюстрируем с аналогией:
- Рабочие процессыпохожи на GPS с фиксированным маршрутом - если есть контрольно -пропускной пункт, он не может адаптироваться
- Агентыэто как местный гид, который знает все ярлыки и может изменить планы на лету
Рабочие процессы отлично подходят для простых, четко определенных задач, но они часто не могут справиться с сложностью очень динамических запросов, в отличие от агентов.
Что мы построим
С помощью SDK Openai мы построим простого информационного агента, который сможет ответить на вопросы о акциях и компаниях. Он сможет:
- Получить цены на акции в реальном времениИспользование API Yahoo Finance
- Найти генеральных директоров компаниииз данных запаса
- Определите символы тикераИз названий компании
- Попросить разъясненияКогда запросы неоднозначны
Что делает этонастоящий агентэто то, что он автономно решает:
- Какой инструмент использовать для каждого запроса
- Когда собирать несколько инструментов вместе
- Когда спросить пользователя для получения дополнительной информации
- Как справиться с ошибками и повторно с разными подходами
Предварительные условия
Вот что вам нужно:
- Python 3.7 или выше
- Ключ OpenAI API (получите один вPlatform.openai.com)
- Основные знания питона
Создайте каталог проекта и установите необходимые пакеты:
mkdir stock-info-agent
cd stock-info-agent
pip install openai yfinance python-dotenv
Создать.env
Файл в вашем каталоге проекта:
OPENAI_API_KEY=your_api_key_here
{/ */}
Построение агента: пошаговое прохождение
Давайте построим этот агент с нуля, понимая каждый компонент по пути.
1. Настройка класса агента
Во -первых, мы создаем наш класс агентов с интеграцией OpenAI:
import json
from typing import Optional, Dict, Any, List
from openai import OpenAI
import yfinance as yf
from dotenv import load_dotenv
import os
load_dotenv()
class StockInfoAgent:
def __init__(self):
self.client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))
self.conversation_history = []
Аconversation_history
имеет решающее значение - это позволяет нашему агенту поддерживать контекст в разных взаимодействиях, понимая, например, что «их генеральный директор» относится к компании, обсуждаемой ранее.
2. Создание инструментов
Наше агент нужны инструменты для взаимодействия с реальным миром. Давайте создадим их:
Ценовой инструмент акций
def get_stock_price(self, ticker_symbol: str) -> Optional[str]:
"""Fetches the current stock price for the given ticker_symbol."""
try:
stock = yf.Ticker(ticker_symbol.upper())
info = stock.info
current_price = info.get('currentPrice') or info.get('regularMarketPrice')
if current_price:
return f"{current_price:.2f} USD"
return None
except Exception as e:
print(f"Error fetching stock price: {e}")
return None
Этот инструмент использует Yahoo Finance для получения цен на акции в реальном времени. Обратите внимание на обработку ошибок. Агенты, которые должны быть изящно обрабатывать сбои.
Генеральный директор Finder Tool
def get_company_ceo(self, ticker_symbol: str) -> Optional[str]:
"""Fetches the name of the CEO for the company associated with the ticker_symbol."""
try:
stock = yf.Ticker(ticker_symbol.upper())
info = stock.info
# Look for CEO in various possible fields
ceo = None
for field in ['companyOfficers', 'officers']:
if field in info:
officers = info[field]
if isinstance(officers, list):
for officer in officers:
if isinstance(officer, dict):
title = officer.get('title', '').lower()
if 'ceo' in title or 'chief executive' in title:
ceo = officer.get('name')
break
return ceo
except Exception as e:
print(f"Error fetching CEO info: {e}")
return None
Этот инструмент ищет различные структуры данных, чтобы найти генерального директора, поскольку Yahoo Finance не имеет стандартизированного формата.
Инструмент искателя символов тикера
Этот инструмент имеет решающее значение для обработки запросов естественного языка о компаниях:
def find_ticker_symbol(self, company_name: str) -> Optional[str]:
"""Tries to identify the stock ticker symbol for a given company_name."""
try:
# Use yfinance Lookup to search for the company
lookup = yf.Lookup(company_name)
stock_results = lookup.get_stock(count=5)
if not stock_results.empty:
return stock_results.index[0]
# If no stocks found, try all instruments
all_results = lookup.get_all(count=5)
if not all_results.empty:
return all_results.index[0]
except Exception as e:
print(f"Error searching for ticker: {e}")
return None
Этот инструмент позволяет пользователям обращаться к компаниям по имени («Apple», «Tesla», «Chat Ev Company») вместо того, чтобы знать символы тикеров.
Инструмент разъяснения
Это то, что делает нашего агента по -настоящему интерактивным, что позволяет ему просить у пользователя разъяснения, когда это необходимо.
def ask_user_for_clarification(self, question_to_user: str) -> str:
"""Poses the question_to_user to the actual user and returns their typed response."""
print(f"\nAgent needs clarification: {question_to_user}")
response = input("Your response: ")
return response
3. Определение инструментов для OpenAI
Агент должен знать, какие инструменты доступны и как их использовать. Мы определяем их в формате вызова Openai:
def create_tool_definitions(self) -> List[Dict[str, Any]]:
"""Creates OpenAI function calling definitions for the tools."""
return [
{
"type": "function",
"function": {
"name": "get_stock_price",
"description": "Fetches the current stock price for the given ticker symbol",
"parameters": {
"type": "object",
"properties": {
"ticker_symbol": {
"type": "string",
"description": "The stock ticker symbol (e.g., 'AAPL', 'MSFT')"
}
},
"required": ["ticker_symbol"]
}
}
},
# ... (other tool definitions)
]
Эти определения похожи на инструкции по руководству по ИИ - они говорят ему, что делает каждый инструмент и какие параметры ему нужны.
4. Мозг: обработка запросов пользователей
Вот где происходит магия-петля принятия решений агента:
def process_user_query(self, user_query: str) -> str:
"""Processes a user query using the OpenAI API with function calling."""
self.conversation_history.append({"role": "user", "content": user_query})
system_prompt = """You are a helpful stock information assistant. You have access to tools that can:
1. Get current stock prices
2. Find company CEOs
3. Find ticker symbols for company names
4. Ask users for clarification when needed
Use these tools to help answer user questions about stocks and companies.
If information is ambiguous, ask for clarification."""
while True:
messages = [
{"role": "system", "content": system_prompt},
*self.conversation_history
]
# Call OpenAI API with function calling
response = self.client.chat.completions.create(
model="gpt-4-turbo-preview",
messages=messages,
tools=self.create_tool_definitions(),
tool_choice="auto" # Let the model decide which tool to use
)
response_message = response.choices[0].message
# If no tool calls, we're done
if not response_message.tool_calls:
self.conversation_history.append({"role": "assistant", "content": response_message.content})
return response_message.content
# Execute the tool the agent chose
tool_call = response_message.tool_calls[0]
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f"\nExecuting tool: {function_name} with args: {function_args}")
# Execute the tool
result = self.execute_tool(function_name, function_args)
# Add everything to conversation history
self.conversation_history.append({
"role": "assistant",
"content": None,
"tool_calls": [{
"id": tool_call.id,
"type": "function",
"function": {
"name": function_name,
"arguments": json.dumps(function_args)
}
}]
})
self.conversation_history.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": str(result) if result is not None else "No result found"
})
Ключевое понимание здесь - этоwhile True
Loop - агент продолжает думать и действовать, пока не будет полного ответа. Он может использовать один инструмент, или пять, или попросить разъяснения несколько раз. Это настоящая автономия.
Смотрите нашего агента в действии
Вот настоящий разговор, который очень хорошо демонстрирует возможности нашего агента:
You: Who is the CEO of the EV company from China and what is its stock price?
Executing tool: ask_user_for_clarification with args: {'question_to_user': 'Are you referring to NIO, XPeng, or another Chinese EV company?'}
Agent needs clarification: Are you referring to NIO, XPeng, or another Chinese EV company?
Your response: BYD
Executing tool: find_ticker_symbol with args: {'company_name': 'BYD'}
Executing tool: get_company_ceo with args: {'ticker_symbol': 'BYDDF'}
Executing tool: get_stock_price with args: {'ticker_symbol': 'BYDDF'}
Agent: The CEO of BYD, the Chinese EV company, is Mr. Chuan-Fu Wang, and its current stock price is $59.50 USD.
Агент автономно:
- Признанная «компания EV из Китая» была неоднозначной
- На вопрос, какая конкретная компания
- Нашел символ тикера для BYD
- Получено информацию генерального директора
- Принесла текущую цену акций
- Составил полный ответ
Как использовать агента
Запуск агента прост, перейдите к каталогу проекта и запустите следующую команду:
python stock_agent.py
Попробуйте эти примеры запросов, чтобы увидеть разные поведения:
Простой запрос:
You: What's Apple's stock price?
Agent: Apple's current stock price is $182.63 USD.
Неоднозначный запрос, требующий разъяснения:
You: Who runs that big EV company?
Agent: Are you asking about the CEO of Tesla?
You: Yes
Agent: The CEO of Tesla is Mr. Elon R. Musk.
Сложный многопрофильный запрос:
You: Compare the stock prices of Microsoft and Apple
Agent: Microsoft (MSFT) is currently trading at $415.26 USD, while Apple (AAPL) is trading at $182.63 USD.
Расширение вашего агента
Модульный дизайн позволяет легко добавлять новые возможности:
Добавить анализ рынка
def get_price_change(self, ticker_symbol: str, period: str = "1d") -> Dict[str, Any]:
"""Get price change over a period"""
stock = yf.Ticker(ticker_symbol)
hist = stock.history(period=period)
if len(hist) >= 2:
start_price = hist['Close'].iloc[0]
end_price = hist['Close'].iloc[-1]
change = end_price - start_price
percent_change = (change / start_price) * 100
return {
"change": f"${change:.2f}",
"percent": f"{percent_change:.2f}%"
}
Добавить интеграцию новостей
def get_company_news(self, ticker_symbol: str) -> List[Dict[str, str]]:
"""Get recent news about the company"""
stock = yf.Ticker(ticker_symbol)
news = stock.news
return [{"title": item['title'], "link": item['link']} for item in news[:5]]
Лучшие практики для строительных агентов
- Четкие описания инструментов: Напишите описания, как будто объясняет коллеге
- Изящная обработка ошибок: Всегда обрабатывайте сбои API и отсутствующие данные
- Разговор контекст: Поддерживать историю для естественных взаимодействий
- Прозрачность пользователя: Показать, какие инструменты выполняются
- Начните просто: Добавьте сложность только при необходимости
Для более полезных советов, проверьтеГид АнтрикаПолем
Полный код
<petload> <summary> Нажмите, чтобы расширить полную реализацию </summary>
import json
from typing import Optional, Dict, Any, List
from openai import OpenAI
import yfinance as yf
from dotenv import load_dotenv
import os
# Load environment variables
load_dotenv()
class StockInfoAgent:
def __init__(self):
self.client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))
self.conversation_history = []
def get_stock_price(self, ticker_symbol: str) -> Optional[str]:
"""Fetches the current stock price for the given ticker_symbol."""
try:
stock = yf.Ticker(ticker_symbol.upper())
info = stock.info
current_price = info.get('currentPrice') or info.get('regularMarketPrice')
if current_price:
return f"{current_price:.2f} USD"
return None
except Exception as e:
print(f"Error fetching stock price: {e}")
return None
def get_company_ceo(self, ticker_symbol: str) -> Optional[str]:
"""Fetches the name of the CEO for the company associated with the ticker_symbol."""
try:
stock = yf.Ticker(ticker_symbol.upper())
info = stock.info
# Look for CEO in various possible fields
ceo = None
for field in ['companyOfficers', 'officers']:
if field in info:
officers = info[field]
if isinstance(officers, list):
for officer in officers:
if isinstance(officer, dict):
title = officer.get('title', '').lower()
if 'ceo' in title or 'chief executive' in title:
ceo = officer.get('name')
break
# Fallback to general company info
if not ceo and 'longBusinessSummary' in info:
ceo = None
return ceo
except Exception as e:
print(f"Error fetching CEO info: {e}")
return None
def find_ticker_symbol(self, company_name: str) -> Optional[str]:
"""Tries to identify the stock ticker symbol for a given company_name."""
try:
# Use yfinance Lookup to search for the company
lookup = yf.Lookup(company_name)
stock_results = lookup.get_stock(count=5)
if not stock_results.empty:
return stock_results.index[0]
# If no stocks found, try all instruments
all_results = lookup.get_all(count=5)
if not all_results.empty:
return all_results.index[0]
except Exception as e:
print(f"Error searching for ticker: {e}")
return None
def ask_user_for_clarification(self, question_to_user: str) -> str:
"""Poses the question_to_user to the actual user and returns their typed response."""
print(f"\nAgent needs clarification: {question_to_user}")
response = input("Your response: ")
return response
def create_tool_definitions(self) -> List[Dict[str, Any]]:
"""Creates OpenAI function calling definitions for the tools."""
return [
{
"type": "function",
"function": {
"name": "get_stock_price",
"description": "Fetches the current stock price for the given ticker symbol",
"parameters": {
"type": "object",
"properties": {
"ticker_symbol": {
"type": "string",
"description": "The stock ticker symbol (e.g., 'AAPL', 'MSFT')"
}
},
"required": ["ticker_symbol"]
}
}
},
{
"type": "function",
"function": {
"name": "get_company_ceo",
"description": "Fetches the name of the CEO for the company associated with the ticker symbol",
"parameters": {
"type": "object",
"properties": {
"ticker_symbol": {
"type": "string",
"description": "The stock ticker symbol"
}
},
"required": ["ticker_symbol"]
}
}
},
{
"type": "function",
"function": {
"name": "find_ticker_symbol",
"description": "Tries to identify the stock ticker symbol for a given company name",
"parameters": {
"type": "object",
"properties": {
"company_name": {
"type": "string",
"description": "The name of the company"
}
},
"required": ["company_name"]
}
}
},
{
"type": "function",
"function": {
"name": "ask_user_for_clarification",
"description": "Poses a question to the user and returns their response",
"parameters": {
"type": "object",
"properties": {
"question_to_user": {
"type": "string",
"description": "The question to ask the user"
}
},
"required": ["question_to_user"]
}
}
}
]
def execute_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Any:
"""Executes the specified tool with given arguments."""
if tool_name == "get_stock_price":
return self.get_stock_price(arguments["ticker_symbol"])
elif tool_name == "get_company_ceo":
return self.get_company_ceo(arguments["ticker_symbol"])
elif tool_name == "find_ticker_symbol":
return self.find_ticker_symbol(arguments["company_name"])
elif tool_name == "ask_user_for_clarification":
return self.ask_user_for_clarification(arguments["question_to_user"])
else:
return None
def process_user_query(self, user_query: str) -> str:
"""Processes a user query using the OpenAI API with function calling."""
# Add user message to conversation history
self.conversation_history.append({"role": "user", "content": user_query})
system_prompt = """You are a helpful stock information assistant. You have access to tools that can:
1. Get current stock prices
2. Find company CEOs
3. Find ticker symbols for company names
4. Ask users for clarification when needed
Use these tools to help answer user questions about stocks and companies. If information is ambiguous, ask for clarification."""
while True:
messages = [
{"role": "system", "content": system_prompt},
*self.conversation_history
]
# Call OpenAI API with function calling
response = self.client.chat.completions.create(
model="gpt-4-turbo-preview",
messages=messages,
tools=self.create_tool_definitions(),
tool_choice="auto"
)
response_message = response.choices[0].message
# If no tool calls, we're done
if not response_message.tool_calls:
self.conversation_history.append({"role": "assistant", "content": response_message.content})
return response_message.content
# Execute the first tool call
tool_call = response_message.tool_calls[0]
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f"\nExecuting tool: {function_name} with args: {function_args}")
# Execute the tool
result = self.execute_tool(function_name, function_args)
# Add the assistant's message with tool calls to history
self.conversation_history.append({
"role": "assistant",
"content": None,
"tool_calls": [{
"id": tool_call.id,
"type": "function",
"function": {
"name": function_name,
"arguments": json.dumps(function_args)
}
}]
})
# Add tool result to history
self.conversation_history.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": str(result) if result is not None else "No result found"
})
def chat(self):
"""Interactive chat loop."""
print("Stock Information Agent")
print("Ask me about stock prices, company CEOs, or any stock-related questions!")
print("Type 'quit' to exit.\n")
while True:
user_input = input("You: ")
if user_input.lower() in ['quit', 'exit', 'bye']:
print("Goodbye!")
break
try:
response = self.process_user_query(user_input)
print(f"\nAgent: {response}\n")
except Exception as e:
print(f"\nError: {e}\n")
if __name__ == "__main__":
agent = StockInfoAgent()
agent.chat()
</details>
Заключение
Поздравляю! Вы создали настоящего агента ИИ, который может думать, решать и действовать автономно. Это не просто чат -бот после сценария - это интеллектуальная система, которая может обрабатывать неоднозначные запросы, запрашивать разъяснения и объединить несколько инструментов вместе для решения сложных проблем.
Ключевые выводы:
- Настоящие агенты принимают свои собственные решения о том, как решить проблемы
- Простые, композиционные узоры бьют сложные рамки
- Начните с основных инструментов и добавляйте сложность только при необходимости
- Память разговора и обработка ошибок имеют решающее значение
С помощью этого фонда вы можете создавать агентов для любого домена, от финансового анализа до поддержки клиентов до личных помощников. Возможности бесконечны, когда вы даете ИИ возможность думать и действовать автономно.
Удачи, и мы не можем дождаться, чтобы увидеть, что вы строите!
Оригинал