Refactor: reformat all code for lefthook using ruff and gofmt (#16585)

This commit is contained in:
Wang Qi
2026-07-03 12:53:39 +08:00
committed by GitHub
parent 19fcb4a981
commit 6a4b9be426
588 changed files with 11123 additions and 15412 deletions

View File

@@ -34,7 +34,6 @@ ATTEMPT_TIME = 2
@singleton
class ESConnection(ESConnectionBase):
@staticmethod
def convert_field_name(field_name: str, use_tokenized_content=False) -> str:
match field_name:
@@ -111,18 +110,19 @@ class ESConnection(ESConnectionBase):
"""
def search(
self, select_fields: list[str],
highlight_fields: list[str],
condition: dict,
match_expressions: list[MatchExpr],
order_by: OrderByExpr,
offset: int,
limit: int,
index_names: str | list[str],
memory_ids: list[str],
agg_fields: list[str] | None = None,
rank_feature: dict | None = None,
hide_forgotten: bool = True
self,
select_fields: list[str],
highlight_fields: list[str],
condition: dict,
match_expressions: list[MatchExpr],
order_by: OrderByExpr,
offset: int,
limit: int,
index_names: str | list[str],
memory_ids: list[str],
agg_fields: list[str] | None = None,
rank_feature: dict | None = None,
hide_forgotten: bool = True,
):
"""
Refers to https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
@@ -154,15 +154,17 @@ class ESConnection(ESConnectionBase):
elif isinstance(v, str) or isinstance(v, int):
bool_query.filter.append(Q("term", **{field_name: v}))
else:
raise Exception(
f"Condition `{str(k)}={str(v)}` value type is {str(type(v))}, expected to be int, str or list.")
raise Exception(f"Condition `{str(k)}={str(v)}` value type is {str(type(v))}, expected to be int, str or list.")
s = Search()
vector_similarity_weight = 0.5
for m in match_expressions:
if isinstance(m, FusionExpr) and m.method == "weighted_sum" and "weights" in m.fusion_params:
assert len(match_expressions) == 3 and isinstance(match_expressions[0], MatchTextExpr) and isinstance(match_expressions[1],
MatchDenseExpr) and isinstance(
match_expressions[2], FusionExpr)
assert (
len(match_expressions) == 3
and isinstance(match_expressions[0], MatchTextExpr)
and isinstance(match_expressions[1], MatchDenseExpr)
and isinstance(match_expressions[2], FusionExpr)
)
weights = m.fusion_params["weights"]
vector_similarity_weight = get_float(weights.split(",")[1])
for m in match_expressions:
@@ -170,24 +172,31 @@ class ESConnection(ESConnectionBase):
minimum_should_match = m.extra_options.get("minimum_should_match", 0.0)
if isinstance(minimum_should_match, float):
minimum_should_match = str(int(minimum_should_match * 100)) + "%"
bool_query.must.append(Q("query_string", fields=[self.convert_field_name(f, use_tokenized_content=True) for f in m.fields],
type="best_fields", query=m.matching_text,
minimum_should_match=minimum_should_match,
boost=1))
bool_query.must.append(
Q(
"query_string",
fields=[self.convert_field_name(f, use_tokenized_content=True) for f in m.fields],
type="best_fields",
query=m.matching_text,
minimum_should_match=minimum_should_match,
boost=1,
)
)
bool_query.boost = 1.0 - vector_similarity_weight
elif isinstance(m, MatchDenseExpr):
assert (bool_query is not None)
assert bool_query is not None
similarity = 0.0
if "similarity" in m.extra_options:
similarity = m.extra_options["similarity"]
s = s.knn(self.convert_field_name(m.vector_column_name),
m.topn,
m.topn * 2,
query_vector=list(m.embedding_data),
filter=bool_query.to_dict(),
similarity=similarity,
)
s = s.knn(
self.convert_field_name(m.vector_column_name),
m.topn,
m.topn * 2,
query_vector=list(m.embedding_data),
filter=bool_query.to_dict(),
similarity=similarity,
)
if bool_query and rank_feature:
for fld, sc in rank_feature.items():
@@ -207,7 +216,7 @@ class ESConnection(ESConnectionBase):
if field.endswith("_int") or field.endswith("_flt"):
order_info = {"order": order, "unmapped_type": "float"}
elif field == "id":
continue # id as "text", not a "keyword", order by it will cause error
continue # id as "text", not a "keyword", order by it will cause error
else:
order_info = {"order": order, "unmapped_type": "keyword"}
orders.append({field: order_info})
@@ -215,22 +224,24 @@ class ESConnection(ESConnectionBase):
if agg_fields:
for fld in agg_fields:
s.aggs.bucket(f'aggs_{fld}', 'terms', field=fld, size=1000000)
s.aggs.bucket(f"aggs_{fld}", "terms", field=fld, size=1000000)
if limit > 0:
s = s[offset:offset + limit]
s = s[offset : offset + limit]
q = s.to_dict()
self.logger.debug(f"ESConnection.search {str(index_names)} query: " + json.dumps(q))
for i in range(ATTEMPT_TIME):
try:
#print(json.dumps(q, ensure_ascii=False))
res = self.es.search(index=exist_index_list,
body=q,
timeout="600s",
# search_type="dfs_query_then_fetch",
track_total_hits=True,
_source=True)
# print(json.dumps(q, ensure_ascii=False))
res = self.es.search(
index=exist_index_list,
body=q,
timeout="600s",
# search_type="dfs_query_then_fetch",
track_total_hits=True,
_source=True,
)
if str(res.get("timed_out", "")).lower() == "true":
raise Exception("Es Timeout.")
self.logger.debug(f"ESConnection.search {str(index_names)} res: " + str(res))
@@ -249,7 +260,7 @@ class ESConnection(ESConnectionBase):
self.logger.error(f"ESConnection.search timeout for {ATTEMPT_TIME} times!")
raise Exception("ESConnection.search timeout.")
def get_forgotten_messages(self, select_fields: list[str], index_name: str, memory_id: str, limit: int=512):
def get_forgotten_messages(self, select_fields: list[str], index_name: str, memory_id: str, limit: int = 512):
bool_query = Q("bool", must=[])
bool_query.must.append(Q("exists", field="forget_at"))
bool_query.filter.append(Q("term", memory_id=memory_id))
@@ -292,7 +303,7 @@ class ESConnection(ESConnectionBase):
self.logger.error(f"ESConnection.search timeout for {ATTEMPT_TIME} times!")
raise Exception("ESConnection.search timeout.")
def get_missing_field_message(self, select_fields: list[str], index_name: str, memory_id: str, field_name: str, limit: int=512):
def get_missing_field_message(self, select_fields: list[str], index_name: str, memory_id: str, field_name: str, limit: int = 512):
if not self.index_exist(index_name):
return None
bool_query = Q("bool", must=[])
@@ -340,8 +351,11 @@ class ESConnection(ESConnectionBase):
def get(self, doc_id: str, index_name: str, memory_ids: list[str]) -> dict | None:
for i in range(ATTEMPT_TIME):
try:
res = self.es.get(index=index_name,
id=doc_id, source=True, )
res = self.es.get(
index=index_name,
id=doc_id,
source=True,
)
if str(res.get("timed_out", "")).lower() == "true":
raise Exception("Es Timeout.")
message = res["_source"]
@@ -365,15 +379,13 @@ class ESConnection(ESConnectionBase):
d_copy = self.map_message_to_es_fields(d_copy_raw)
d_copy["memory_id"] = memory_id
meta_id = d_copy.pop("id", "")
operations.append(
{"index": {"_index": index_name, "_id": meta_id}})
operations.append({"index": {"_index": index_name, "_id": meta_id}})
operations.append(d_copy)
res = []
for _ in range(ATTEMPT_TIME):
try:
res = []
r = self.es.bulk(index=index_name, operations=operations,
refresh=False, timeout="60s")
r = self.es.bulk(index=index_name, operations=operations, refresh=False, timeout="60s")
if re.search(r"False", str(r["errors"]), re.IGNORECASE):
return res
@@ -409,15 +421,14 @@ class ESConnection(ESConnectionBase):
if "feas" != k.split("_")[-1]:
continue
try:
self.es.update(index=index_name, id=message_id, script=f"ctx._source.remove(\"{k}\");")
self.es.update(index=index_name, id=message_id, script=f'ctx._source.remove("{k}");')
except Exception:
self.logger.exception(f"ESConnection.update(index={index_name}, id={message_id}, doc={json.dumps(condition, ensure_ascii=False)}) got exception")
try:
self.es.update(index=index_name, id=message_id, doc=update_dict)
return True
except Exception as e:
self.logger.exception(
f"ESConnection.update(index={index_name}, id={message_id}, doc={json.dumps(condition, ensure_ascii=False)}) got exception: " + str(e))
self.logger.exception(f"ESConnection.update(index={index_name}, id={message_id}, doc={json.dumps(condition, ensure_ascii=False)}) got exception: " + str(e))
break
return False
@@ -434,8 +445,7 @@ class ESConnection(ESConnectionBase):
elif isinstance(v, str) or isinstance(v, int):
bool_query.filter.append(Q("term", **{k: v}))
else:
raise Exception(
f"Condition `{str(k)}={str(v)}` value type is {str(type(v))}, expected to be int, str or list.")
raise Exception(f"Condition `{str(k)}={str(v)}` value type is {str(type(v))}, expected to be int, str or list.")
scripts = []
params = {}
for k, v in update_dict.items():
@@ -465,11 +475,8 @@ class ESConnection(ESConnectionBase):
scripts.append(f"ctx._source.{k}=params.pp_{k};")
params[f"pp_{k}"] = json.dumps(v, ensure_ascii=False)
else:
raise Exception(
f"newValue `{str(k)}={str(v)}` value type is {str(type(v))}, expected to be int, str.")
ubq = UpdateByQuery(
index=index_name).using(
self.es).query(bool_query)
raise Exception(f"newValue `{str(k)}={str(v)}` value type is {str(type(v))}, expected to be int, str.")
ubq = UpdateByQuery(index=index_name).using(self.es).query(bool_query)
ubq = ubq.script(source="".join(scripts), params=params)
ubq = ubq.params(refresh=True)
ubq = ubq.params(slices=5)
@@ -521,10 +528,7 @@ class ESConnection(ESConnectionBase):
self.logger.debug("ESConnection.delete query: " + json.dumps(qry.to_dict()))
for _ in range(ATTEMPT_TIME):
try:
res = self.es.delete_by_query(
index=index_name,
body=Search().query(qry).to_dict(),
refresh=True)
res = self.es.delete_by_query(index=index_name, body=Search().query(qry).to_dict(), refresh=True)
return res["deleted"]
except ConnectionTimeout:
self.logger.exception("ES request timeout")

View File

@@ -42,7 +42,7 @@ class InfinityConnection(InfinityConnectionBase):
return False
@staticmethod
def convert_message_field_to_infinity(field_name: str, table_fields: list[str]=None):
def convert_message_field_to_infinity(field_name: str, table_fields: list[str] = None):
match field_name:
case "message_type":
return "message_type_kwd"
@@ -68,7 +68,7 @@ class InfinityConnection(InfinityConnectionBase):
return "content_embed"
return field_name
def convert_select_fields(self, output_fields: list[str], table_fields: list[str]=None) -> list[str]:
def convert_select_fields(self, output_fields: list[str], table_fields: list[str] = None) -> list[str]:
return list({self.convert_message_field_to_infinity(f, table_fields) for f in output_fields})
@staticmethod
@@ -277,7 +277,7 @@ class InfinityConnection(InfinityConnectionBase):
self.logger.debug(f"INFINITY search final result: {str(res)}")
return res, total_hits_count
def get_forgotten_messages(self, select_fields: list[str], index_name: str, memory_id: str, limit: int=512):
def get_forgotten_messages(self, select_fields: list[str], index_name: str, memory_id: str, limit: int = 512):
condition = {"memory_id": memory_id, "exists": "forget_at_flt"}
order_by = OrderByExpr()
order_by.asc("forget_at_flt")
@@ -309,7 +309,7 @@ class InfinityConnection(InfinityConnectionBase):
self.connPool.release_conn(inf_conn)
return res
def get_missing_field_message(self, select_fields: list[str], index_name: str, memory_id: str, field_name: str, limit: int=512):
def get_missing_field_message(self, select_fields: list[str], index_name: str, memory_id: str, field_name: str, limit: int = 512):
condition = {"memory_id": memory_id, "must_not": {"exists": field_name}}
order_by = OrderByExpr()
order_by.asc("valid_at_flt")

View File

@@ -27,9 +27,9 @@ def get_json_result_from_llm_response(response_str: str) -> dict:
"""
try:
clean_str = response_str.strip()
if clean_str.startswith('```json'):
if clean_str.startswith("```json"):
clean_str = clean_str[7:] # Remove the starting ```json
if clean_str.endswith('```'):
if clean_str.endswith("```"):
clean_str = clean_str[:-3] # Remove the ending ```
return json.loads(clean_str.strip())

View File

@@ -75,7 +75,7 @@ class SearchResult(BaseModel):
@singleton
class OBConnection(OBConnectionBase):
def __init__(self):
super().__init__(logger_name='ragflow.memory_ob_conn')
super().__init__(logger_name="ragflow.memory_ob_conn")
self._fulltext_search_columns = FTS_COLUMNS
"""
@@ -101,10 +101,10 @@ class OBConnection(OBConnectionBase):
def _get_vector_column_name_from_table(self, table_name: str) -> Optional[str]:
"""Get the vector column name from the table (q_{size}_vec pattern)."""
sql = f"""
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = '{self.db_name}'
AND TABLE_NAME = '{table_name}'
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = '{self.db_name}'
AND TABLE_NAME = '{table_name}'
AND COLUMN_NAME REGEXP '^q_[0-9]+_vec$'
LIMIT 1
"""
@@ -204,7 +204,7 @@ class OBConnection(OBConnectionBase):
memory_ids: list[str],
agg_fields: list[str] | None = None,
rank_feature: dict | None = None,
hide_forgotten: bool = True
hide_forgotten: bool = True,
):
"""Search messages in memory storage."""
if isinstance(index_names, str):
@@ -273,9 +273,7 @@ class OBConnection(OBConnectionBase):
fulltext_query = escape_string(fulltext_query.strip())
fulltext_topn = m.topn
fulltext_search_expr, fulltext_search_weight = self._parse_fulltext_columns(
fulltext_query, self._fulltext_search_columns
)
fulltext_search_expr, fulltext_search_weight = self._parse_fulltext_columns(fulltext_query, self._fulltext_search_columns)
elif isinstance(m, MatchDenseExpr):
vector_column_name = m.vector_column_name
vector_data = m.embedding_data
@@ -339,39 +337,27 @@ class OBConnection(OBConnectionBase):
)
self.logger.debug("OBConnection.search with fusion sql: %s", fusion_sql)
rows, elapsed_time = self._execute_search_sql(fusion_sql)
self.logger.info(
f"OBConnection.search table {table_name}, search type: fusion, elapsed time: {elapsed_time:.3f}s, rows: {len(rows)}"
)
self.logger.info(f"OBConnection.search table {table_name}, search type: fusion, elapsed time: {elapsed_time:.3f}s, rows: {len(rows)}")
for row in rows:
result.messages.append(self._row_to_entity(row, db_output_fields + ["_score"]))
result.total += 1
elif search_type == "vector":
vector_sql = self._build_vector_search_sql(
table_name, fields_expr, vector_search_score_expr, filters_expr,
vector_search_filter, vector_search_expr, limit, vector_topn, offset
)
vector_sql = self._build_vector_search_sql(table_name, fields_expr, vector_search_score_expr, filters_expr, vector_search_filter, vector_search_expr, limit, vector_topn, offset)
self.logger.debug("OBConnection.search with vector sql: %s", vector_sql)
rows, elapsed_time = self._execute_search_sql(vector_sql)
self.logger.info(
f"OBConnection.search table {table_name}, search type: vector, elapsed time: {elapsed_time:.3f}s, rows: {len(rows)}"
)
self.logger.info(f"OBConnection.search table {table_name}, search type: vector, elapsed time: {elapsed_time:.3f}s, rows: {len(rows)}")
for row in rows:
result.messages.append(self._row_to_entity(row, db_output_fields + ["_score"]))
result.total += 1
elif search_type == "fulltext":
fulltext_sql = self._build_fulltext_search_sql(
table_name, fields_expr, fulltext_search_score_expr, filters_expr,
fulltext_search_filter, offset, limit, fulltext_topn
)
fulltext_sql = self._build_fulltext_search_sql(table_name, fields_expr, fulltext_search_score_expr, filters_expr, fulltext_search_filter, offset, limit, fulltext_topn)
self.logger.debug("OBConnection.search with fulltext sql: %s", fulltext_sql)
rows, elapsed_time = self._execute_search_sql(fulltext_sql)
self.logger.info(
f"OBConnection.search table {table_name}, search type: fulltext, elapsed time: {elapsed_time:.3f}s, rows: {len(rows)}"
)
self.logger.info(f"OBConnection.search table {table_name}, search type: fulltext, elapsed time: {elapsed_time:.3f}s, rows: {len(rows)}")
for row in rows:
result.messages.append(self._row_to_entity(row, db_output_fields + ["_score"]))
@@ -387,14 +373,10 @@ class OBConnection(OBConnectionBase):
order_by_expr = ("ORDER BY " + ", ".join(orders)) if orders else ""
limit_expr = f"LIMIT {offset}, {limit}" if limit != 0 else ""
filter_sql = self._build_filter_search_sql(
table_name, fields_expr, filters_expr, order_by_expr, limit_expr
)
filter_sql = self._build_filter_search_sql(table_name, fields_expr, filters_expr, order_by_expr, limit_expr)
self.logger.debug("OBConnection.search with filter sql: %s", filter_sql)
rows, elapsed_time = self._execute_search_sql(filter_sql)
self.logger.info(
f"OBConnection.search table {table_name}, search type: filter, elapsed time: {elapsed_time:.3f}s, rows: {len(rows)}"
)
self.logger.info(f"OBConnection.search table {table_name}, search type: filter, elapsed time: {elapsed_time:.3f}s, rows: {len(rows)}")
for row in rows:
result.messages.append(self._row_to_entity(row, db_output_fields))
@@ -413,13 +395,7 @@ class OBConnection(OBConnectionBase):
db_output_fields = [self.convert_field_name(f) for f in select_fields]
fields_expr = ", ".join(db_output_fields)
sql = (
f"SELECT {fields_expr}"
f" FROM {index_name}"
f" WHERE memory_id = {get_value_str(memory_id)} AND forget_at IS NOT NULL"
f" ORDER BY forget_at ASC"
f" LIMIT {limit}"
)
sql = f"SELECT {fields_expr} FROM {index_name} WHERE memory_id = {get_value_str(memory_id)} AND forget_at IS NOT NULL ORDER BY forget_at ASC LIMIT {limit}"
self.logger.debug("OBConnection.get_forgotten_messages sql: %s", sql)
res = self.client.perform_raw_text_sql(sql)
@@ -431,8 +407,7 @@ class OBConnection(OBConnectionBase):
return result
def get_missing_field_message(self, select_fields: list[str], index_name: str, memory_id: str, field_name: str,
limit: int = 512):
def get_missing_field_message(self, select_fields: list[str], index_name: str, memory_id: str, field_name: str, limit: int = 512):
"""Get messages missing a specific field."""
if not self._check_table_exists_cached(index_name):
return None
@@ -441,13 +416,7 @@ class OBConnection(OBConnectionBase):
db_output_fields = [self.convert_field_name(f) for f in select_fields]
fields_expr = ", ".join(db_output_fields)
sql = (
f"SELECT {fields_expr}"
f" FROM {index_name}"
f" WHERE memory_id = {get_value_str(memory_id)} AND {db_field_name} IS NULL"
f" ORDER BY valid_at ASC"
f" LIMIT {limit}"
)
sql = f"SELECT {fields_expr} FROM {index_name} WHERE memory_id = {get_value_str(memory_id)} AND {db_field_name} IS NULL ORDER BY valid_at ASC LIMIT {limit}"
self.logger.debug("OBConnection.get_missing_field_message sql: %s", sql)
res = self.client.perform_raw_text_sql(sql)
@@ -531,11 +500,7 @@ class OBConnection(OBConnectionBase):
if not set_values:
return True
update_sql = (
f"UPDATE {index_name}"
f" SET {', '.join(set_values)}"
f" WHERE {' AND '.join(filters)}"
)
update_sql = f"UPDATE {index_name} SET {', '.join(set_values)} WHERE {' AND '.join(filters)}"
self.logger.debug("OBConnection.update sql: %s", update_sql)
try:
@@ -557,14 +522,14 @@ class OBConnection(OBConnectionBase):
def get_total(self, res) -> int:
if isinstance(res, tuple):
return res[1]
if hasattr(res, 'total'):
if hasattr(res, "total"):
return res.total
return 0
def get_doc_ids(self, res) -> list[str]:
if isinstance(res, tuple):
res = res[0]
if hasattr(res, 'messages'):
if hasattr(res, "messages"):
return [row.get("id") for row in res.messages if row.get("id")]
return []
@@ -577,7 +542,7 @@ class OBConnection(OBConnectionBase):
if not fields:
return {}
messages = res.messages if hasattr(res, 'messages') else []
messages = res.messages if hasattr(res, "messages") else []
for doc in messages:
message = self.get_message_from_ob_doc(doc)
@@ -588,10 +553,7 @@ class OBConnection(OBConnectionBase):
if isinstance(v, list):
m[n] = v
continue
if n in ["message_id", "source_id", "valid_at", "invalid_at", "forget_at", "status"] and isinstance(v,
(int,
float,
bool)):
if n in ["message_id", "source_id", "valid_at", "invalid_at", "forget_at", "status"] and isinstance(v, (int, float, bool)):
m[n] = v
continue
if not isinstance(v, str):
@@ -610,9 +572,7 @@ class OBConnection(OBConnectionBase):
if isinstance(res, tuple):
res = res[0]
messages = getattr(res, "messages", None)
return get_highlight_from_messages(
messages, keywords, field_name, is_english_fn=lambda s: is_english([s])
)
return get_highlight_from_messages(messages, keywords, field_name, is_english_fn=lambda s: is_english([s]))
def get_aggregation(self, res, field_name: str):
"""Get aggregation for search results."""

View File

@@ -18,8 +18,8 @@ from typing import Optional, List
from common.constants import MemoryType
from common.time_utils import current_timestamp
class PromptAssembler:
class PromptAssembler:
SYSTEM_BASE_TEMPLATE = """**Memory Extraction Specialist**
You are an expert at analyzing conversations to extract structured memory.
@@ -47,7 +47,6 @@ You are an expert at analyzing conversations to extract structured memory.
- invalid_at: When it becomes false (e.g., repeal, disproven) or empty if still true
- Default: valid_at = conversation time, invalid_at = "" for timeless facts
""",
MemoryType.EPISODIC.name.lower(): """
**EXTRACT EPISODIC KNOWLEDGE:**
- Specific experiences, events, personal stories
@@ -59,7 +58,6 @@ You are an expert at analyzing conversations to extract structured memory.
- invalid_at: Event end time or empty if instantaneous
- Extract explicit times: "at 3 PM", "last Monday", "from X to Y"
""",
MemoryType.PROCEDURAL.name.lower(): """
**EXTRACT PROCEDURAL KNOWLEDGE:**
- Processes, methods, step-by-step instructions
@@ -71,7 +69,7 @@ You are an expert at analyzing conversations to extract structured memory.
- invalid_at: When it expires/becomes obsolete or empty if current
- For version-specific: use release dates
- For best practices: invalid_at = ""
"""
""",
}
OUTPUT_TEMPLATES = {
@@ -84,7 +82,6 @@ You are an expert at analyzing conversations to extract structured memory.
}
]
""",
MemoryType.EPISODIC.name.lower(): """
"episodic": [
{
@@ -94,7 +91,6 @@ You are an expert at analyzing conversations to extract structured memory.
}
]
""",
MemoryType.PROCEDURAL.name.lower(): """
"procedural": [
{
@@ -103,7 +99,7 @@ You are an expert at analyzing conversations to extract structured memory.
"invalid_at": "procedure expiration timestamp or empty"
}
]
"""
""",
}
BASE_USER_PROMPT = """
@@ -111,7 +107,7 @@ You are an expert at analyzing conversations to extract structured memory.
{conversation}
**CONVERSATION TIME:** {conversation_time}
**CURRENT TIME:** {current_time}
**CURRENT TIME:** {current_time}
"""
@classmethod
@@ -123,9 +119,7 @@ You are an expert at analyzing conversations to extract structured memory.
output_format = cls._generate_output_format(types_to_extract)
full_prompt = cls.SYSTEM_BASE_TEMPLATE.format(
type_specific_instructions=type_instructions,
timestamp_format=config.get("timestamp_format", "ISO 8601"),
max_items=config.get("max_items_per_type", 5)
type_specific_instructions=type_instructions, timestamp_format=config.get("timestamp_format", "ISO 8601"), max_items=config.get("max_items_per_type", 5)
)
full_prompt += f"\n**REQUIRED OUTPUT FORMAT (JSON):**\n```json\n{{\n{output_format}\n}}\n```\n"
@@ -140,7 +134,7 @@ You are an expert at analyzing conversations to extract structured memory.
def _get_types_to_extract(requested_types: List[str]) -> List[str]:
types = set()
for rt in requested_types:
if rt in [e.name.lower() for e in MemoryType] and rt != MemoryType.RAW.name.lower():
if rt in [e.name.lower() for e in MemoryType] and rt != MemoryType.RAW.name.lower():
types.add(rt)
return list(types)
@@ -184,12 +178,7 @@ You are an expert at analyzing conversations to extract structured memory.
return "\n".join(examples)
@classmethod
def assemble_user_prompt(
cls,
conversation: str,
conversation_time: Optional[str] = None,
current_time: Optional[str] = None
) -> str:
def assemble_user_prompt(cls, conversation: str, conversation_time: Optional[str] = None, current_time: Optional[str] = None) -> str:
return cls.BASE_USER_PROMPT.format(
conversation=conversation,
conversation_time=conversation_time or "Not specified",