start with adapting example, and seperating out tooling into file
This commit is contained in:
parent
4fb6ada4e2
commit
bbd62ce4fc
11
hw2/.requirements.txt
Normal file
11
hw2/.requirements.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
langchain-community
|
||||||
|
langchain
|
||||||
|
langchain_openai
|
||||||
|
python-dotenv
|
||||||
|
firecrawl-py
|
||||||
|
chromadb
|
||||||
|
langchainhub
|
||||||
|
dnspython
|
||||||
|
validators
|
||||||
|
google-search-results
|
||||||
|
langchain-experimental
|
24
hw2/README.md
Normal file
24
hw2/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
## HW2 for gensec
|
||||||
|
|
||||||
|
|
||||||
|
### Enviornment
|
||||||
|
Install python3, then run the following:
|
||||||
|
```
|
||||||
|
pip install -r requirements.txt
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
After, populate .env with your OPENAI_API_KEY and FIREWALL_API_KEY
|
||||||
|
|
||||||
|
|
||||||
|
### Running
|
||||||
|
```
|
||||||
|
python3 app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Queries
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Enjoy!
|
42
hw2/app.py
42
hw2/app.py
@ -0,0 +1,42 @@
|
|||||||
|
from langchain import hub
|
||||||
|
from langchain.agents import AgentExecutor, create_react_agent, load_tools
|
||||||
|
from langchain.tools import tool
|
||||||
|
from langchain_openai import ChatOpenAI
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from tools import lookup_ip, lookup_name
|
||||||
|
from langsmith import Client
|
||||||
|
|
||||||
|
"""
|
||||||
|
This is the main runner of the custom agent. Agent tools are defined seperatly and imported from tools.py
|
||||||
|
|
||||||
|
So far, wholly adapted from https://github.com/wu4f/cs410g-src/blob/main/04_Agents/07_tools_custom_agent.py
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
#os.environ["LANGCHAIN_TRACING_V2"] = "true"
|
||||||
|
#os.environ["LANGCHAIN_PROJECT"] = f"LangSmith Introduction"
|
||||||
|
#os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
|
||||||
|
#client = Client()
|
||||||
|
llm = ChatOpenAI(model_name="gpt-4-turbo", temperature=0)
|
||||||
|
|
||||||
|
tools = load_tools(["serpapi", "terminal"], allow_dangerous_tools=True)
|
||||||
|
tools.extend([lookup_name, lookup_ip])
|
||||||
|
|
||||||
|
base_prompt = hub.pull("langchain-ai/react-agent-template")
|
||||||
|
prompt = base_prompt.partial(instructions="Answer the user's request utilizing at most 8 tool calls")
|
||||||
|
agent = create_react_agent(llm,tools,prompt)
|
||||||
|
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
|
||||||
|
print("Welcome to my application. I am configured with these tools:")
|
||||||
|
for tool in agent_executor.tools:
|
||||||
|
print(f' Tool: {tool.name} = {tool.description}')
|
||||||
|
while True:
|
||||||
|
line = input("llm>> ")
|
||||||
|
try:
|
||||||
|
if line:
|
||||||
|
result = agent_executor.invoke({"input":line})
|
||||||
|
print(result)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
8
hw2/requirements.txt
Normal file
8
hw2/requirements.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
langchain
|
||||||
|
langchain_openai
|
||||||
|
langchain-experimental
|
||||||
|
langchainhub
|
||||||
|
python-dotenv
|
||||||
|
dnspython
|
||||||
|
validators
|
||||||
|
google-search-results
|
44
hw2/tools.py
Normal file
44
hw2/tools.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
from langchain_core.pydantic_v1 import BaseModel, Field, root_validator
|
||||||
|
from langchain.tools import tool
|
||||||
|
import dns.resolver, dns.reversename
|
||||||
|
import validators
|
||||||
|
import validators
|
||||||
|
|
||||||
|
"""
|
||||||
|
Tools to be run by my custom agent.
|
||||||
|
|
||||||
|
So far, these are the same tooling provided by the example in https://github.com/wu4f/cs410g-src/blob/main/04_Agents/07_tools_custom_agent.py,
|
||||||
|
But I will be updating this to build my own tooling
|
||||||
|
"""
|
||||||
|
|
||||||
|
class LookupNameInput(BaseModel):
|
||||||
|
hostname: str = Field(description="Should be a hostname such as www.google.com")
|
||||||
|
@root_validator
|
||||||
|
def is_dns_address(cls, values: dict[str,any]) -> str:
|
||||||
|
if validators.domain(values.get("hostname")):
|
||||||
|
return values
|
||||||
|
raise ValueError("Malformed hostname")
|
||||||
|
class LookupIPInput(BaseModel):
|
||||||
|
address: str = Field(description="Should be an IP address such as 208.91.197.27 or 143.95.239.83")
|
||||||
|
@root_validator
|
||||||
|
def is_ip_address(cls, values: dict[str,any]) -> str:
|
||||||
|
if validators.ip_address.ipv4(values.get("address")):
|
||||||
|
return values
|
||||||
|
raise ValueError("Malformed IP address")
|
||||||
|
|
||||||
|
|
||||||
|
@tool("lookup_name",args_schema=LookupNameInput, return_direct=False)
|
||||||
|
def lookup_name(hostname):
|
||||||
|
"""Given a DNS hostname, it will return its IPv4 addresses"""
|
||||||
|
result = dns.resolver.resolve(hostname, 'A')
|
||||||
|
res = [ r.to_text() for r in result ]
|
||||||
|
return res[0]
|
||||||
|
|
||||||
|
|
||||||
|
@tool("lookup_ip", args_schema=LookupIPInput, return_direct=False)
|
||||||
|
def lookup_ip(address):
|
||||||
|
"""Given an IP address, returns names associated with it"""
|
||||||
|
n = dns.reversename.from_address(address)
|
||||||
|
result = dns.resolver.resolve(n, 'PTR')
|
||||||
|
res = [ r.to_text() for r in result ]
|
||||||
|
return res[0]
|
Reference in New Issue
Block a user