Hi,
I’m new to here, with chatgpt, i’m trying to write an agent to help to analyze log files. When adding memory function, I got this error. Chatgpt cannot give me good answer, could somebody help? Thanks in advance.
My file is like:
import os
import traceback
import re
import pandas as pd
from langchain_ollama import OllamaLLM
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.schema.document import Document
from langchain.agents import Tool, AgentExecutor, create_react_agent
from langchain.chains import RetrievalQA
from langchain.memory import ConversationBufferMemory
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnablePassthrough
from langchain_core.messages import AIMessage, HumanMessage
# === CONFIGURATION ===
log_path = "/env_test/tftpboot/Book2.csv"
base_url = "http://10.59.19.3:11434"
model_name = "llama3"
# === 1. LOAD CSV LOG FILE ===
df = pd.read_csv(log_path, header=None).dropna(axis=1, how='all').fillna("").astype(str)
# === 2. Build FAISS Index ===
docs = [Document(page_content="\n".join(f"{k}={v}" for k, v in row.items() if v.strip()), metadata={"row_index": i}) for i, row in df.iterrows()]
embedding_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
db = FAISS.from_documents(docs, embedding_model)
# === 3. Setup LLM and Memory ===
llm = OllamaLLM(model=model_name, base_url=base_url)
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
input_key="input" #new required field in LangChain >0.1.0
)
# === 4. Shared cache to store last result row indexes ===
last_indexes = []
# === 5. Tool Helpers ===
def parse_keyword(q):
match = re.search(r"(?:how many|count)?\s*(\w+)(?:\s+logs?)?", q, re.IGNORECASE)
return match.group(1) if match else q.strip()
def get_row_indexes_by_keyword(keyword: str):
global last_indexes
matches = df[df.apply(lambda row: row.astype(str).str.contains(keyword, case=False).any(), axis=1)]
last_indexes = matches.index.tolist()
return_str = ", ".join(map(str, last_indexes)) if last_indexes else "No matching rows found"
print("return_str is "+return_str)
return return_str
def get_row_indexes_by_field(field: str, value: str):
global last_indexes
matches = df[df[field].astype(str).str.contains(value, case=False, na=False)]
last_indexes = matches.index.tolist()
return_str = ", ".join(map(str, last_indexes)) if last_indexes else "No matching rows found"
print("return_str is "+return_str)
return return_str
def print_rows_by_index(indexes: list[int], limit=5) -> str:
output = []
for idx in indexes[:limit]:
if 0 <= idx < len(df):
row = df.iloc[idx]
clean = row[row != ""]
output.append(f"\n--- Row {idx} ---\n" + clean.to_string())
return "\n".join(output) if output else "No rows to show."
# === 6. Tools ===
tools = [
Tool(
name="FindRowIndexesByKeyword",
func=lambda q: get_row_indexes_by_keyword(parse_keyword(q)),
description="Return a list of row indexes where any field contains the given keyword"
),
Tool(
name="FindRowIndexesByField",
func=lambda q: get_row_indexes_by_field(*re.search(r"(\w+)=['\"]?(.+?)['\"]?", q).groups()),
description="Return a list of row indexes where a specific field equals a value, e.g., subtype='ha'"
),
Tool(
name="PrintRowsByIndex",
func=lambda q: print_rows_by_index(last_indexes),
description="Print the rows found from the last search using saved row indexes"
)
]
#def format_log_to_messages(intermediate_steps):
# """Construct the scratchpad that lets the agent continue its thought process."""
# thoughts = []
# for action, observation in intermediate_steps:
# thoughts.append(AIMessage(content=action.log))
# human_message = HumanMessage(content=f"Observation: {observation}")
# thoughts.append(human_message)
# return thoughts
#
## Ensure agent_scratchpad is formatted correctly
#agent_scratchpad = format_log_to_messages([]) # Initialize with an empty list
agent_scratchpad = []
# === 7. Agent Setup ===
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful log analysis assistant.\n\n"
"You have access to the following tools:\n\n{tools}\n\n"
"Use them if they help answer the question.\n"
"Tools available: {tool_names}"),
("human", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
print("prompt is "+str(prompt))
agent = create_react_agent(llm=llm, tools=tools, prompt=prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
memory=memory,
verbose=True,
handle_parsing_errors=True,
return_intermediate_steps=True,
agent_scratchpad_key="agent_scratchpad", # ? match placeholder
input_key="input", # ? match prompt
)
# === 8. Main Loop ===
print("\n?? You can now ask questions about the logs (type 'exit' to quit).")
while True:
query = input("\n?? Ask: ").strip()
if query.lower() == "exit":
break
if isinstance(agent_scratchpad, list):
print("agent_scratchpad is a list")
#result = agent_executor.invoke({"input": query})
try:
result = agent_executor.invoke({"input": query})
except Exception as e:
print(f"? Exception: {e}")
traceback.print_exc()
result = None
print("\n? Answer:\n", result["answer"])
root@cenubu81:/env_test/my_codes/document_analyzer#
When I run it, i got:
(env) root@cenubu81:/env_test/my_codes/document_analyzer# python3 agent2.py
/env_test/my_codes/document_analyzer/agent2.py:26: LangChainDeprecationWarning: The class `HuggingFaceEmbeddings` was deprecated in LangChain 0.2.2 and will be removed in 1.0. An updated version of the class exists in the :class:`~langchain-huggingface package and should be used instead. To use it run `pip install -U :class:`~langchain-huggingface` and import as `from :class:`~langchain_huggingface import HuggingFaceEmbeddings``.
embedding_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
/env_test/my_codes/document_analyzer/agent2.py:31: LangChainDeprecationWarning: Please see the migration guide at: https://python.langchain.com/docs/versions/migrating_memory/
memory = ConversationBufferMemory(
prompt is input_variables=['agent_scratchpad', 'input', 'tool_names', 'tools'] input_types={'agent_scratchpad': list[typing.Annotated[typing.Union[typing.Annotated[langchain_core.messages.ai.AIMessage, Tag(tag='ai')], typing.Annotated[langchain_core.messages.human.HumanMessage, Tag(tag='human')], typing.Annotated[langchain_core.messages.chat.ChatMessage, Tag(tag='chat')], typing.Annotated[langchain_core.messages.system.SystemMessage, Tag(tag='system')], typing.Annotated[langchain_core.messages.function.FunctionMessage, Tag(tag='function')], typing.Annotated[langchain_core.messages.tool.ToolMessage, Tag(tag='tool')], typing.Annotated[langchain_core.messages.ai.AIMessageChunk, Tag(tag='AIMessageChunk')], typing.Annotated[langchain_core.messages.human.HumanMessageChunk, Tag(tag='HumanMessageChunk')], typing.Annotated[langchain_core.messages.chat.ChatMessageChunk, Tag(tag='ChatMessageChunk')], typing.Annotated[langchain_core.messages.system.SystemMessageChunk, Tag(tag='SystemMessageChunk')], typing.Annotated[langchain_core.messages.function.FunctionMessageChunk, Tag(tag='FunctionMessageChunk')], typing.Annotated[langchain_core.messages.tool.ToolMessageChunk, Tag(tag='ToolMessageChunk')]], FieldInfo(annotation=NoneType, required=True, discriminator=Discriminator(discriminator=<function _get_type at 0x79b96f3b6b60>, custom_error_type=None, custom_error_message=None, custom_error_context=None))]]} partial_variables={} messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=['tool_names', 'tools'], input_types={}, partial_variables={}, template='You are a helpful log analysis assistant.\n\nYou have access to the following tools:\n\n{tools}\n\nUse them if they help answer the question.\nTools available: {tool_names}'), additional_kwargs={}), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], input_types={}, partial_variables={}, template='{input}'), additional_kwargs={}), MessagesPlaceholder(variable_name='agent_scratchpad')]
?? You can now ask questions about the logs (type 'exit' to quit).
?? Ask: how many logs contain shutdown
agent_scratchpad is a list
> Entering new AgentExecutor chain...
? Exception: variable agent_scratchpad should be a list of base messages, got of type <class 'str'>
Traceback (most recent call last):
File "/env_test/my_codes/document_analyzer/agent2.py", line 134, in <module>
result = agent_executor.invoke({"input": query})
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/env/lib/python3.12/site-packages/langchain/chains/base.py", line 167, in invoke
raise e
File "/root/env/lib/python3.12/site-packages/langchain/chains/base.py", line 157, in invoke
self._call(inputs, run_manager=run_manager)
File "/root/env/lib/python3.12/site-packages/langchain/agents/agent.py", line 1620, in _call
next_step_output = self._take_next_step(
^^^^^^^^^^^^^^^^^^^^^
File "/root/env/lib/python3.12/site-packages/langchain/agents/agent.py", line 1326, in _take_next_step
[
File "/root/env/lib/python3.12/site-packages/langchain/agents/agent.py", line 1354, in _iter_next_step
output = self._action_agent.plan(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/env/lib/python3.12/site-packages/langchain/agents/agent.py", line 461, in plan
for chunk in self.runnable.stream(inputs, config={"callbacks": callbacks}):
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/base.py", line 3438, in stream
yield from self.transform(iter([input]), config, **kwargs)
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/base.py", line 3424, in transform
yield from self._transform_stream_with_config(
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/base.py", line 2215, in _transform_stream_with_config
chunk: Output = context.run(next, iterator)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/base.py", line 3386, in _transform
yield from final_pipeline
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/base.py", line 1429, in transform
for ichunk in input:
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/base.py", line 5647, in transform
yield from self.bound.transform(
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/base.py", line 1429, in transform
for ichunk in input:
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/base.py", line 1447, in transform
yield from self.stream(final, config, **kwargs)
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/base.py", line 1014, in stream
yield self.invoke(input, config, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/env/lib/python3.12/site-packages/langchain_core/prompts/base.py", line 216, in invoke
return self._call_with_config(
^^^^^^^^^^^^^^^^^^^^^^^
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/base.py", line 1940, in _call_with_config
context.run(
File "/root/env/lib/python3.12/site-packages/langchain_core/runnables/config.py", line 428, in call_func_with_variable_args
return func(input, **kwargs) # type: ignore[call-arg]
^^^^^^^^^^^^^^^^^^^^^
File "/root/env/lib/python3.12/site-packages/langchain_core/prompts/base.py", line 190, in _format_prompt_with_error_handling
return self.format_prompt(**_inner_input)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/env/lib/python3.12/site-packages/langchain_core/prompts/chat.py", line 726, in format_prompt
messages = self.format_messages(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/env/lib/python3.12/site-packages/langchain_core/prompts/chat.py", line 1187, in format_messages
message = message_template.format_messages(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/env/lib/python3.12/site-packages/langchain_core/prompts/chat.py", line 183, in format_messages
raise ValueError(msg) # noqa: TRY004
^^^^^^^^^^^^^^^^^^^^^
ValueError: variable agent_scratchpad should be a list of base messages, got of type <class 'str'>
Traceback (most recent call last):
File "/env_test/my_codes/document_analyzer/agent2.py", line 139, in <module>
print("\n? Answer:\n", result["answer"])
~~~~~~^^^^^^^^^^
TypeError: 'NoneType' object is not subscriptable
(env) root@cenubu81:/env_test/my_codes/document_analyzer#
Thank you very much!!!
Hans