add main.py
This commit is contained in:
@@ -1,94 +1,68 @@
|
|||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
from dotenv import load_dotenv
|
||||||
from langchain_openai import ChatOpenAI
|
from langchain_openai import ChatOpenAI
|
||||||
from langchain.tools import tool
|
from agent_core import DeepAgent
|
||||||
from duckduckgo_search import DDGS
|
from tools import web_search, create_virtual_file, list_virtual_files, export_files
|
||||||
|
|
||||||
# LLM configuration
|
# Load environment variables
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# LLM initialization
|
||||||
llm = ChatOpenAI(
|
llm = ChatOpenAI(
|
||||||
model="openai/gpt-oss-20b:free",
|
model="openai/gpt-oss-20b:free",
|
||||||
base_url="https://platform.brojs.ru/jrnl-bh/api/inference/v1",
|
base_url="https://platform.brojs.ru/jrnl-bh/api/inference/v1",
|
||||||
api_key=os.getenv("JOURNAL_MCP_PAT"),
|
api_key=os.getenv("JOURNAL_MCP_PAT"),
|
||||||
temperature=0.5,
|
temperature=0.3,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Simple virtual file system
|
# Helper to wrap the LLM callable expected by DeepAgent
|
||||||
class VirtualFileSystem:
|
class LLMWrapper:
|
||||||
def __init__(self):
|
def __init__(self, llm):
|
||||||
self.files = {}
|
|
||||||
|
|
||||||
def write(self, path: str, content: str):
|
|
||||||
self.files[path] = content
|
|
||||||
|
|
||||||
def list(self):
|
|
||||||
return list(self.files.keys())
|
|
||||||
|
|
||||||
def dump_to_real_fs(self, base_dir: str = "."):
|
|
||||||
for path, content in self.files.items():
|
|
||||||
full_path = os.path.join(base_dir, path)
|
|
||||||
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
|
||||||
with open(full_path, "w", encoding="utf-8") as f:
|
|
||||||
f.write(content)
|
|
||||||
|
|
||||||
# Tool for web search using duckduckgo
|
|
||||||
@tool
|
|
||||||
def web_search(query: str) -> str:
|
|
||||||
"""Search the web for a query and return top 3 results as a formatted string."""
|
|
||||||
try:
|
|
||||||
with DDGS() as ddgs:
|
|
||||||
results = list(ddgs.text(query, max_results=3))
|
|
||||||
if not results:
|
|
||||||
return "No results found."
|
|
||||||
formatted = []
|
|
||||||
for i, r in enumerate(results, 1):
|
|
||||||
formatted.append(f"{i}. {r['title']}\n{r['body']}\nURL: {r['href']}")
|
|
||||||
return "\n\n".join(formatted)
|
|
||||||
except Exception as e:
|
|
||||||
return f"Search error: {e}"
|
|
||||||
|
|
||||||
# Deep agent implementation
|
|
||||||
class DeepAgent:
|
|
||||||
def __init__(self, llm, tools):
|
|
||||||
self.llm = llm
|
self.llm = llm
|
||||||
self.tools = {t.__name__: t for t in tools}
|
def __call__(self, messages):
|
||||||
self.vfs = VirtualFileSystem()
|
# langchain returns a list of Message objects; convert to dict
|
||||||
|
# For simplicity, we use the first assistant message content
|
||||||
|
response = self.llm(messages)
|
||||||
|
# The wrapper expects a dict with 'content'
|
||||||
|
return {"content": response["content"]}
|
||||||
|
|
||||||
def run(self, prompt: str):
|
llm_wrapper = LLMWrapper(llm)
|
||||||
# Initial system message
|
|
||||||
system_msg = "You are a helpful assistant that can search the web and create virtual files."
|
# Instantiate agent with tools
|
||||||
# Build conversation
|
agent = DeepAgent(llm_wrapper, [web_search, create_virtual_file, list_virtual_files, export_files])
|
||||||
messages = [system_msg, prompt]
|
|
||||||
# Simple loop: ask for tool usage
|
# Example tasks
|
||||||
while True:
|
TASKS = [
|
||||||
# Ask LLM for next action
|
{
|
||||||
response = self.llm.invoke(messages)
|
"description": "Найди информацию о LangGraph и создай файл summary.md",
|
||||||
text = response.content.strip()
|
"query": "LangGraph python framework",
|
||||||
if text.lower().startswith("search:"):
|
"filename": "summary.md",
|
||||||
query = text[7:].strip()
|
},
|
||||||
result = web_search(query)
|
{
|
||||||
self.vfs.write(f"search_{query.replace(' ', '_')}.txt", result)
|
"description": "Найди топ-5 Python библиотек для работы с LLM и создай файл llm_libs.md",
|
||||||
messages.append(f"Search result for '{query}' written to virtual file.")
|
"query": "top python libraries for llm",
|
||||||
elif text.lower().startswith("create file:"):
|
"filename": "llm_libs.md",
|
||||||
parts = text[12:].strip().split("::", 1)
|
},
|
||||||
if len(parts) == 2:
|
{
|
||||||
path, content = parts
|
"description": "Найди что такое ReAct агент и создай файл react_agent.md",
|
||||||
self.vfs.write(path.strip(), content.strip())
|
"query": "ReAct agent definition",
|
||||||
messages.append(f"File '{path.strip()}' created.")
|
"filename": "react_agent.md",
|
||||||
else:
|
},
|
||||||
messages.append("Invalid create file syntax. Use 'create file: path::content'.")
|
]
|
||||||
elif text.lower() == "done":
|
|
||||||
break
|
for task in TASKS:
|
||||||
else:
|
print(f"\n=== {task['description']} ===")
|
||||||
messages.append(text)
|
# Step 1: search
|
||||||
# Dump virtual files to real filesystem
|
search_result = agent.run(task["query"])
|
||||||
self.vfs.dump_to_real_fs()
|
# Step 2: create file with search result
|
||||||
return "Agent finished. Files written to disk."
|
create_msg = agent.run(f"create_virtual_file {task['filename']} | {search_result}")
|
||||||
|
print(create_msg)
|
||||||
|
|
||||||
|
# Export all virtual files to disk
|
||||||
|
export_msg = agent.run("export_files output")
|
||||||
|
print(export_msg)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
agent = DeepAgent(llm, tools=[web_search])
|
# The script already executed tasks above; nothing else needed.
|
||||||
# Example usage: search for LangChain and create a file
|
pass
|
||||||
user_prompt = (
|
|
||||||
"Search for 'LangChain deep agent' and create a file named 'summary.txt' with the first search result."
|
|
||||||
)
|
|
||||||
result = agent.run(user_prompt)
|
|
||||||
print(result)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user