harvesthealth's picture
Upload folder using huggingface_hub
f6686e1 verified
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>tinytroupe.extraction API documentation</title>
<meta name="description" content="Simulations produce a lot of data, and it is often useful to extract these data in a structured way. For instance, you might wish to:
- Extract the …" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>tinytroupe.extraction</code></h1>
</header>
<section id="section-intro">
<p>Simulations produce a lot of data, and it is often useful to extract these data in a structured way. For instance, you might wish to:
- Extract the main points from an agent's interactions history, so that you can consult them later in a concise form.
- Generate synthetic data from a simulation, so that you can use it for training machine learning models or testing software.
- Simply turn some of the data into a more machine-readable format, such as JSON or CSV, so that you can analyze it more easily.</p>
<p>This module provides various utilities to help you extract data from TinyTroupe elements, such as agents and worlds. It also provides a
mechanism to reduce the extracted data to a more concise form, and to export artifacts from TinyTroupe elements. Incidentaly, it showcases
one of the many ways in which agent simulations differ from AI assistants, as the latter are not designed to be introspected in this way.</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;
Simulations produce a lot of data, and it is often useful to extract these data in a structured way. For instance, you might wish to:
- Extract the main points from an agent&#39;s interactions history, so that you can consult them later in a concise form.
- Generate synthetic data from a simulation, so that you can use it for training machine learning models or testing software.
- Simply turn some of the data into a more machine-readable format, such as JSON or CSV, so that you can analyze it more easily.
This module provides various utilities to help you extract data from TinyTroupe elements, such as agents and worlds. It also provides a
mechanism to reduce the extracted data to a more concise form, and to export artifacts from TinyTroupe elements. Incidentaly, it showcases
one of the many ways in which agent simulations differ from AI assistants, as the latter are not designed to be introspected in this way.
&#34;&#34;&#34;
import logging
logger = logging.getLogger(&#34;tinytroupe&#34;)
###########################################################################
# Exposed API
###########################################################################
from tinytroupe.extraction.artifact_exporter import ArtifactExporter
from tinytroupe.extraction.normalizer import Normalizer
from tinytroupe.extraction.results_extractor import ResultsExtractor
from tinytroupe.extraction.results_reducer import ResultsReducer
from tinytroupe.extraction.results_reporter import ResultsReporter
__all__ = [&#34;ArtifactExporter&#34;, &#34;Normalizer&#34;, &#34;ResultsExtractor&#34;, &#34;ResultsReducer&#34;, &#34;ResultsReporter&#34;]</code></pre>
</details>
</section>
<section>
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dl>
<dt><code class="name"><a title="tinytroupe.extraction.artifact_exporter" href="artifact_exporter.html">tinytroupe.extraction.artifact_exporter</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="tinytroupe.extraction.normalizer" href="normalizer.html">tinytroupe.extraction.normalizer</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="tinytroupe.extraction.results_extractor" href="results_extractor.html">tinytroupe.extraction.results_extractor</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="tinytroupe.extraction.results_reducer" href="results_reducer.html">tinytroupe.extraction.results_reducer</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="tinytroupe.extraction.results_reporter" href="results_reporter.html">tinytroupe.extraction.results_reporter</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
</dl>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="tinytroupe.extraction.ArtifactExporter"><code class="flex name class">
<span>class <span class="ident">ArtifactExporter</span></span>
<span>(</span><span>base_output_folder: str)</span>
</code></dt>
<dd>
<div class="desc"><p>An artifact exporter is responsible for exporting artifacts from TinyTroupe elements, for example
in order to create synthetic data files from simulations.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class ArtifactExporter(JsonSerializableRegistry):
&#34;&#34;&#34;
An artifact exporter is responsible for exporting artifacts from TinyTroupe elements, for example
in order to create synthetic data files from simulations.
&#34;&#34;&#34;
def __init__(self, base_output_folder:str) -&gt; None:
self.base_output_folder = base_output_folder
def export(self, artifact_name:str, artifact_data:Union[dict, str], content_type:str, content_format:str=None, target_format:str=&#34;txt&#34;, verbose:bool=False):
&#34;&#34;&#34;
Exports the specified artifact data to a file.
Args:
artifact_name (str): The name of the artifact.
artifact_data (Union[dict, str]): The data to export. If a dict is given, it will be saved as JSON.
If a string is given, it will be saved as is.
content_type (str): The type of the content within the artifact.
content_format (str, optional): The format of the content within the artifact (e.g., md, csv, etc). Defaults to None.
target_format (str): The format to export the artifact to (e.g., json, txt, docx, etc).
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
# dedent inputs, just in case
if isinstance(artifact_data, str):
artifact_data = utils.dedent(artifact_data)
elif isinstance(artifact_data, dict):
artifact_data[&#39;content&#39;] = utils.dedent(artifact_data[&#39;content&#39;])
else:
raise ValueError(&#34;The artifact data must be either a string or a dictionary.&#34;)
# clean the artifact name of invalid characters
invalid_chars = [&#39;/&#39;, &#39;\\&#39;, &#39;:&#39;, &#39;*&#39;, &#39;?&#39;, &#39;&#34;&#39;, &#39;&lt;&#39;, &#39;&gt;&#39;, &#39;|&#39;, &#39;\n&#39;, &#39;\t&#39;, &#39;\r&#39;, &#39;;&#39;]
for char in invalid_chars:
# check if the character is in the artifact name
if char in artifact_name:
# replace the character with an underscore
artifact_name = artifact_name.replace(char, &#34;-&#34;)
logger.warning(f&#34;Replaced invalid character {char} with hyphen in artifact name &#39;{artifact_name}&#39;.&#34;)
artifact_file_path = self._compose_filepath(artifact_data, artifact_name, content_type, target_format, verbose)
if target_format == &#34;json&#34;:
self._export_as_json(artifact_file_path, artifact_data, content_type, verbose)
elif target_format == &#34;txt&#34; or target_format == &#34;text&#34; or target_format == &#34;md&#34; or target_format == &#34;markdown&#34;:
self._export_as_txt(artifact_file_path, artifact_data, content_type, verbose)
elif target_format == &#34;docx&#34;:
self._export_as_docx(artifact_file_path, artifact_data, content_format, verbose)
else:
raise ValueError(f&#34;Unsupported target format: {target_format}.&#34;)
def _export_as_txt(self, artifact_file_path:str, artifact_data:Union[dict, str], content_type:str, verbose:bool=False):
&#34;&#34;&#34;
Exports the specified artifact data to a text file.
&#34;&#34;&#34;
with open(artifact_file_path, &#39;w&#39;, encoding=&#34;utf-8&#34;) as f:
if isinstance(artifact_data, dict):
content = artifact_data[&#39;content&#39;]
else:
content = artifact_data
f.write(content)
def _export_as_json(self, artifact_file_path:str, artifact_data:Union[dict, str], content_type:str, verbose:bool=False):
&#34;&#34;&#34;
Exports the specified artifact data to a JSON file.
&#34;&#34;&#34;
with open(artifact_file_path, &#39;w&#39;, encoding=&#34;utf-8&#34;) as f:
if isinstance(artifact_data, dict):
json.dump(artifact_data, f, indent=4)
else:
raise ValueError(&#34;The artifact data must be a dictionary to export to JSON.&#34;)
def _export_as_docx(self, artifact_file_path:str, artifact_data:Union[dict, str], content_original_format:str, verbose:bool=False):
&#34;&#34;&#34;
Exports the specified artifact data to a DOCX file.
&#34;&#34;&#34;
# original format must be &#39;text&#39; or &#39;markdown&#39;
if content_original_format not in [&#39;text&#39;, &#39;txt&#39;, &#39;markdown&#39;, &#39;md&#39;]:
raise ValueError(f&#34;The original format cannot be {content_original_format} to export to DOCX.&#34;)
else:
# normalize content value
content_original_format = &#39;markdown&#39; if content_original_format == &#39;md&#39; else content_original_format
# first, get the content to export. If `artifact_date` is a dict, the contant should be under the key `content`.
# If it is a string, the content is the string itself.
# using pypandoc
if isinstance(artifact_data, dict):
content = artifact_data[&#39;content&#39;]
else:
content = artifact_data
# first, convert to HTML. This is necessary because pypandoc does not support a GOOD direct conversion from markdown to DOCX.
html_content = markdown.markdown(content)
## write this intermediary HTML to file
#html_file_path = artifact_file_path.replace(&#34;.docx&#34;, &#34;.html&#34;)
#with open(html_file_path, &#39;w&#39;, encoding=&#34;utf-8&#34;) as f:
# f.write(html_content)
# then, convert to DOCX
pypandoc.convert_text(html_content, &#39;docx&#39;, format=&#39;html&#39;, outputfile=artifact_file_path)
###########################################################
# IO
###########################################################
def _compose_filepath(self, artifact_data:Union[dict, str], artifact_name:str, content_type:str, target_format:str=None, verbose:bool=False):
&#34;&#34;&#34;
Composes the file path for the artifact to export.
Args:
artifact_data (Union[dict, str]): The data to export.
artifact_name (str): The name of the artifact.
content_type (str): The type of the content within the artifact.
content_format (str, optional): The format of the content within the artifact (e.g., md, csv, etc). Defaults to None.
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
# Extension definition:
#
# - If the content format is specified, we use it as the part of the extension.
# - If artificat_data is a dict, we add .json to the extension. Note that if content format was specified, we&#39;d get &lt;content_format&gt;.json.
# - If artifact_data is a string and no content format is specified, we add .txt to the extension.
extension = None
if target_format is not None:
extension = f&#34;{target_format}&#34;
elif isinstance(artifact_data, str) and target_format is None:
extension = &#34;txt&#34;
# content type definition
if content_type is None:
subfolder = &#34;&#34;
else:
subfolder = content_type
# save to the specified file name or path, considering the base output folder.
artifact_file_path = os.path.join(self.base_output_folder, subfolder, f&#34;{artifact_name}.{extension}&#34;)
# create intermediate directories if necessary
os.makedirs(os.path.dirname(artifact_file_path), exist_ok=True)
return artifact_file_path</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="tinytroupe.utils.json.JsonSerializableRegistry" href="../utils/json.html#tinytroupe.utils.json.JsonSerializableRegistry">JsonSerializableRegistry</a></li>
</ul>
<h3>Methods</h3>
<dl>
<dt id="tinytroupe.extraction.ArtifactExporter.export"><code class="name flex">
<span>def <span class="ident">export</span></span>(<span>self, artifact_name: str, artifact_data: Union[str, dict], content_type: str, content_format: str = None, target_format: str = 'txt', verbose: bool = False)</span>
</code></dt>
<dd>
<div class="desc"><p>Exports the specified artifact data to a file.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>artifact_name</code></strong> :&ensp;<code>str</code></dt>
<dd>The name of the artifact.</dd>
<dt><strong><code>artifact_data</code></strong> :&ensp;<code>Union[dict, str]</code></dt>
<dd>The data to export. If a dict is given, it will be saved as JSON.
If a string is given, it will be saved as is.</dd>
<dt><strong><code>content_type</code></strong> :&ensp;<code>str</code></dt>
<dd>The type of the content within the artifact.</dd>
<dt><strong><code>content_format</code></strong> :&ensp;<code>str</code>, optional</dt>
<dd>The format of the content within the artifact (e.g., md, csv, etc). Defaults to None.</dd>
<dt><strong><code>target_format</code></strong> :&ensp;<code>str</code></dt>
<dd>The format to export the artifact to (e.g., json, txt, docx, etc).</dd>
<dt><strong><code>verbose</code></strong> :&ensp;<code>bool</code>, optional</dt>
<dd>Whether to print debug messages. Defaults to False.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def export(self, artifact_name:str, artifact_data:Union[dict, str], content_type:str, content_format:str=None, target_format:str=&#34;txt&#34;, verbose:bool=False):
&#34;&#34;&#34;
Exports the specified artifact data to a file.
Args:
artifact_name (str): The name of the artifact.
artifact_data (Union[dict, str]): The data to export. If a dict is given, it will be saved as JSON.
If a string is given, it will be saved as is.
content_type (str): The type of the content within the artifact.
content_format (str, optional): The format of the content within the artifact (e.g., md, csv, etc). Defaults to None.
target_format (str): The format to export the artifact to (e.g., json, txt, docx, etc).
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
# dedent inputs, just in case
if isinstance(artifact_data, str):
artifact_data = utils.dedent(artifact_data)
elif isinstance(artifact_data, dict):
artifact_data[&#39;content&#39;] = utils.dedent(artifact_data[&#39;content&#39;])
else:
raise ValueError(&#34;The artifact data must be either a string or a dictionary.&#34;)
# clean the artifact name of invalid characters
invalid_chars = [&#39;/&#39;, &#39;\\&#39;, &#39;:&#39;, &#39;*&#39;, &#39;?&#39;, &#39;&#34;&#39;, &#39;&lt;&#39;, &#39;&gt;&#39;, &#39;|&#39;, &#39;\n&#39;, &#39;\t&#39;, &#39;\r&#39;, &#39;;&#39;]
for char in invalid_chars:
# check if the character is in the artifact name
if char in artifact_name:
# replace the character with an underscore
artifact_name = artifact_name.replace(char, &#34;-&#34;)
logger.warning(f&#34;Replaced invalid character {char} with hyphen in artifact name &#39;{artifact_name}&#39;.&#34;)
artifact_file_path = self._compose_filepath(artifact_data, artifact_name, content_type, target_format, verbose)
if target_format == &#34;json&#34;:
self._export_as_json(artifact_file_path, artifact_data, content_type, verbose)
elif target_format == &#34;txt&#34; or target_format == &#34;text&#34; or target_format == &#34;md&#34; or target_format == &#34;markdown&#34;:
self._export_as_txt(artifact_file_path, artifact_data, content_type, verbose)
elif target_format == &#34;docx&#34;:
self._export_as_docx(artifact_file_path, artifact_data, content_format, verbose)
else:
raise ValueError(f&#34;Unsupported target format: {target_format}.&#34;)</code></pre>
</details>
</dd>
</dl>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="tinytroupe.utils.json.JsonSerializableRegistry" href="../utils/json.html#tinytroupe.utils.json.JsonSerializableRegistry">JsonSerializableRegistry</a></b></code>:
<ul class="hlist">
<li><code><a title="tinytroupe.utils.json.JsonSerializableRegistry.from_json" href="../utils/json.html#tinytroupe.utils.json.JsonSerializableRegistry.from_json">from_json</a></code></li>
<li><code><a title="tinytroupe.utils.json.JsonSerializableRegistry.to_json" href="../utils/json.html#tinytroupe.utils.json.JsonSerializableRegistry.to_json">to_json</a></code></li>
</ul>
</li>
</ul>
</dd>
<dt id="tinytroupe.extraction.Normalizer"><code class="flex name class">
<span>class <span class="ident">Normalizer</span></span>
<span>(</span><span>elements: List[str], n: int, verbose: bool = False)</span>
</code></dt>
<dd>
<div class="desc"><p>A mechanism to normalize passages, concepts and other textual elements.</p>
<p>Normalizes the specified elements.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>elements</code></strong> :&ensp;<code>list</code></dt>
<dd>The elements to normalize.</dd>
<dt><strong><code>n</code></strong> :&ensp;<code>int</code></dt>
<dd>The number of normalized elements to output.</dd>
<dt><strong><code>verbose</code></strong> :&ensp;<code>bool</code>, optional</dt>
<dd>Whether to print debug messages. Defaults to False.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class Normalizer:
&#34;&#34;&#34;
A mechanism to normalize passages, concepts and other textual elements.
&#34;&#34;&#34;
def __init__(self, elements:List[str], n:int, verbose:bool=False):
&#34;&#34;&#34;
Normalizes the specified elements.
Args:
elements (list): The elements to normalize.
n (int): The number of normalized elements to output.
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
# ensure elements are unique
self.elements = list(set(elements))
self.n = n
self.verbose = verbose
# a JSON-based structure, where each output element is a key to a list of input elements that were merged into it
self.normalized_elements = None
# a dict that maps each input element to its normalized output. This will be used as cache later.
self.normalizing_map = {}
rendering_configs = {&#34;n&#34;: n,
&#34;elements&#34;: self.elements}
messages = utils.compose_initial_LLM_messages_with_templates(&#34;normalizer.system.mustache&#34;, &#34;normalizer.user.mustache&#34;,
base_module_folder=&#34;extraction&#34;,
rendering_configs=rendering_configs)
next_message = openai_utils.client().send_message(messages, temperature=0.1)
debug_msg = f&#34;Normalization result message: {next_message}&#34;
logger.debug(debug_msg)
if self.verbose:
print(debug_msg)
result = utils.extract_json(next_message[&#34;content&#34;])
logger.debug(result)
if self.verbose:
print(result)
self.normalized_elements = result
def normalize(self, element_or_elements:Union[str, List[str]]) -&gt; Union[str, List[str]]:
&#34;&#34;&#34;
Normalizes the specified element or elements.
This method uses a caching mechanism to improve performance. If an element has been normalized before,
its normalized form is stored in a cache (self.normalizing_map). When the same element needs to be
normalized again, the method will first check the cache and use the stored normalized form if available,
instead of normalizing the element again.
The order of elements in the output will be the same as in the input. This is ensured by processing
the elements in the order they appear in the input and appending the normalized elements to the output
list in the same order.
Args:
element_or_elements (Union[str, List[str]]): The element or elements to normalize.
Returns:
str: The normalized element if the input was a string.
list: The normalized elements if the input was a list, preserving the order of elements in the input.
&#34;&#34;&#34;
if isinstance(element_or_elements, str):
denormalized_elements = [element_or_elements]
elif isinstance(element_or_elements, list):
denormalized_elements = element_or_elements
else:
raise ValueError(&#34;The element_or_elements must be either a string or a list.&#34;)
normalized_elements = []
elements_to_normalize = []
for element in denormalized_elements:
if element not in self.normalizing_map:
elements_to_normalize.append(element)
if elements_to_normalize:
rendering_configs = {&#34;categories&#34;: self.normalized_elements,
&#34;elements&#34;: elements_to_normalize}
messages = utils.compose_initial_LLM_messages_with_templates(&#34;normalizer.applier.system.mustache&#34;, &#34;normalizer.applier.user.mustache&#34;,
base_module_folder=&#34;extraction&#34;,
rendering_configs=rendering_configs)
next_message = openai_utils.client().send_message(messages, temperature=0.1)
debug_msg = f&#34;Normalization result message: {next_message}&#34;
logger.debug(debug_msg)
if self.verbose:
print(debug_msg)
normalized_elements_from_llm = utils.extract_json(next_message[&#34;content&#34;])
assert isinstance(normalized_elements_from_llm, list), &#34;The normalized element must be a list.&#34;
assert len(normalized_elements_from_llm) == len(elements_to_normalize), &#34;The number of normalized elements must be equal to the number of elements to normalize.&#34;
for i, element in enumerate(elements_to_normalize):
normalized_element = normalized_elements_from_llm[i]
self.normalizing_map[element] = normalized_element
for element in denormalized_elements:
normalized_elements.append(self.normalizing_map[element])
return normalized_elements</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="tinytroupe.extraction.Normalizer.normalize"><code class="name flex">
<span>def <span class="ident">normalize</span></span>(<span>self, element_or_elements: Union[str, List[str]]) ‑> Union[str, List[str]]</span>
</code></dt>
<dd>
<div class="desc"><p>Normalizes the specified element or elements.</p>
<p>This method uses a caching mechanism to improve performance. If an element has been normalized before,
its normalized form is stored in a cache (self.normalizing_map). When the same element needs to be
normalized again, the method will first check the cache and use the stored normalized form if available,
instead of normalizing the element again.</p>
<p>The order of elements in the output will be the same as in the input. This is ensured by processing
the elements in the order they appear in the input and appending the normalized elements to the output
list in the same order.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>element_or_elements</code></strong> :&ensp;<code>Union[str, List[str]]</code></dt>
<dd>The element or elements to normalize.</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><code>str</code></dt>
<dd>The normalized element if the input was a string.</dd>
<dt><code>list</code></dt>
<dd>The normalized elements if the input was a list, preserving the order of elements in the input.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def normalize(self, element_or_elements:Union[str, List[str]]) -&gt; Union[str, List[str]]:
&#34;&#34;&#34;
Normalizes the specified element or elements.
This method uses a caching mechanism to improve performance. If an element has been normalized before,
its normalized form is stored in a cache (self.normalizing_map). When the same element needs to be
normalized again, the method will first check the cache and use the stored normalized form if available,
instead of normalizing the element again.
The order of elements in the output will be the same as in the input. This is ensured by processing
the elements in the order they appear in the input and appending the normalized elements to the output
list in the same order.
Args:
element_or_elements (Union[str, List[str]]): The element or elements to normalize.
Returns:
str: The normalized element if the input was a string.
list: The normalized elements if the input was a list, preserving the order of elements in the input.
&#34;&#34;&#34;
if isinstance(element_or_elements, str):
denormalized_elements = [element_or_elements]
elif isinstance(element_or_elements, list):
denormalized_elements = element_or_elements
else:
raise ValueError(&#34;The element_or_elements must be either a string or a list.&#34;)
normalized_elements = []
elements_to_normalize = []
for element in denormalized_elements:
if element not in self.normalizing_map:
elements_to_normalize.append(element)
if elements_to_normalize:
rendering_configs = {&#34;categories&#34;: self.normalized_elements,
&#34;elements&#34;: elements_to_normalize}
messages = utils.compose_initial_LLM_messages_with_templates(&#34;normalizer.applier.system.mustache&#34;, &#34;normalizer.applier.user.mustache&#34;,
base_module_folder=&#34;extraction&#34;,
rendering_configs=rendering_configs)
next_message = openai_utils.client().send_message(messages, temperature=0.1)
debug_msg = f&#34;Normalization result message: {next_message}&#34;
logger.debug(debug_msg)
if self.verbose:
print(debug_msg)
normalized_elements_from_llm = utils.extract_json(next_message[&#34;content&#34;])
assert isinstance(normalized_elements_from_llm, list), &#34;The normalized element must be a list.&#34;
assert len(normalized_elements_from_llm) == len(elements_to_normalize), &#34;The number of normalized elements must be equal to the number of elements to normalize.&#34;
for i, element in enumerate(elements_to_normalize):
normalized_element = normalized_elements_from_llm[i]
self.normalizing_map[element] = normalized_element
for element in denormalized_elements:
normalized_elements.append(self.normalizing_map[element])
return normalized_elements</code></pre>
</details>
</dd>
</dl>
</dd>
<dt id="tinytroupe.extraction.ResultsExtractor"><code class="flex name class">
<span>class <span class="ident">ResultsExtractor</span></span>
<span>(</span><span>extraction_prompt_template_path: str = 'C:\\Users\\pdasilva\\repos\\TinyTroupe\\tinytroupe\\extraction\\./prompts/interaction_results_extractor.mustache', extraction_objective: str = "The main points present in the agents' interactions history.", situation: str = '', fields: List[str] = None, fields_hints: dict = None, verbose: bool = False)</span>
</code></dt>
<dd>
<div class="desc"><p>Initializes the ResultsExtractor with default parameters.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>extraction_prompt_template_path</code></strong> :&ensp;<code>str</code></dt>
<dd>The path to the extraction prompt template.</dd>
<dt><strong><code>extraction_objective</code></strong> :&ensp;<code>str</code></dt>
<dd>The default extraction objective.</dd>
<dt><strong><code>situation</code></strong> :&ensp;<code>str</code></dt>
<dd>The default situation to consider.</dd>
<dt><strong><code>fields</code></strong> :&ensp;<code>List[str]</code>, optional</dt>
<dd>The default fields to extract. Defaults to None.</dd>
<dt><strong><code>fields_hints</code></strong> :&ensp;<code>dict</code>, optional</dt>
<dd>The default hints for the fields to extract. Defaults to None.</dd>
<dt><strong><code>verbose</code></strong> :&ensp;<code>bool</code>, optional</dt>
<dd>Whether to print debug messages by default. Defaults to False.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class ResultsExtractor:
def __init__(self,
extraction_prompt_template_path:str = os.path.join(os.path.dirname(__file__), &#39;./prompts/interaction_results_extractor.mustache&#39;),
extraction_objective:str = &#34;The main points present in the agents&#39; interactions history.&#34;,
situation:str = &#34;&#34;,
fields:List[str] = None,
fields_hints:dict = None,
verbose:bool = False):
&#34;&#34;&#34;
Initializes the ResultsExtractor with default parameters.
Args:
extraction_prompt_template_path (str): The path to the extraction prompt template.
extraction_objective (str): The default extraction objective.
situation (str): The default situation to consider.
fields (List[str], optional): The default fields to extract. Defaults to None.
fields_hints (dict, optional): The default hints for the fields to extract. Defaults to None.
verbose (bool, optional): Whether to print debug messages by default. Defaults to False.
&#34;&#34;&#34;
self._extraction_prompt_template_path = extraction_prompt_template_path
# Default parameters
self.default_extraction_objective = extraction_objective
self.default_situation = situation
self.default_fields = fields
self.default_fields_hints = fields_hints
self.default_verbose = verbose
# Cache for the last extraction results
self.agent_extraction = {}
self.world_extraction = {}
def extract_results_from_agents(self,
agents:List[TinyPerson],
extraction_objective:str=None,
situation:str =None,
fields:list=None,
fields_hints:dict=None,
verbose:bool=None):
&#34;&#34;&#34;
Extracts results from a list of TinyPerson instances.
Args:
agents (List[TinyPerson]): The list of TinyPerson instances to extract results from.
extraction_objective (str): The extraction objective.
situation (str): The situation to consider.
fields (list, optional): The fields to extract. If None, the extractor will decide what names to use.
Defaults to None.
fields_hints (dict, optional): Hints for the fields to extract. Maps field names to strings with the hints. Defaults to None.
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
results = []
for agent in agents:
result = self.extract_results_from_agent(agent, extraction_objective, situation, fields, fields_hints, verbose)
results.append(result)
return results
def extract_results_from_agent(self,
tinyperson:TinyPerson,
extraction_objective:str=&#34;The main points present in the agent&#39;s interactions history.&#34;,
situation:str = &#34;&#34;,
fields:list=None,
fields_hints:dict=None,
verbose:bool=None):
&#34;&#34;&#34;
Extracts results from a TinyPerson instance.
Args:
tinyperson (TinyPerson): The TinyPerson instance to extract results from.
extraction_objective (str): The extraction objective.
situation (str): The situation to consider.
fields (list, optional): The fields to extract. If None, the extractor will decide what names to use.
Defaults to None.
fields_hints (dict, optional): Hints for the fields to extract. Maps field names to strings with the hints. Defaults to None.
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
extraction_objective, situation, fields, fields_hints, verbose = self._get_default_values_if_necessary(
extraction_objective, situation, fields, fields_hints, verbose
)
messages = []
rendering_configs = {}
if fields is not None:
rendering_configs[&#34;fields&#34;] = &#34;, &#34;.join(fields)
if fields_hints is not None:
rendering_configs[&#34;fields_hints&#34;] = list(fields_hints.items())
messages.append({&#34;role&#34;: &#34;system&#34;,
&#34;content&#34;: chevron.render(
open(self._extraction_prompt_template_path).read(),
rendering_configs)})
interaction_history = tinyperson.pretty_current_interactions(max_content_length=None)
extraction_request_prompt = \
f&#34;&#34;&#34;
## Extraction objective
{extraction_objective}
## Situation
You are considering a single agent, named {tinyperson.name}. Your objective thus refers to this agent specifically.
{situation}
## Agent Interactions History
You will consider an agent&#39;s history of interactions, which include stimuli it received as well as actions it
performed.
{interaction_history}
&#34;&#34;&#34;
messages.append({&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: extraction_request_prompt})
next_message = openai_utils.client().send_message(messages, temperature=0.0, frequency_penalty=0.0, presence_penalty=0.0)
debug_msg = f&#34;Extraction raw result message: {next_message}&#34;
logger.debug(debug_msg)
if verbose:
print(debug_msg)
if next_message is not None:
result = utils.extract_json(next_message[&#34;content&#34;])
else:
result = None
# cache the result
self.agent_extraction[tinyperson.name] = result
return result
def extract_results_from_world(self,
tinyworld:TinyWorld,
extraction_objective:str=&#34;The main points that can be derived from the agents conversations and actions.&#34;,
situation:str=&#34;&#34;,
fields:list=None,
fields_hints:dict=None,
verbose:bool=None):
&#34;&#34;&#34;
Extracts results from a TinyWorld instance.
Args:
tinyworld (TinyWorld): The TinyWorld instance to extract results from.
extraction_objective (str): The extraction objective.
situation (str): The situation to consider.
fields (list, optional): The fields to extract. If None, the extractor will decide what names to use.
Defaults to None.
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
extraction_objective, situation, fields, fields_hints, verbose = self._get_default_values_if_necessary(
extraction_objective, situation, fields, fields_hints, verbose
)
messages = []
rendering_configs = {}
if fields is not None:
rendering_configs[&#34;fields&#34;] = &#34;, &#34;.join(fields)
if fields_hints is not None:
rendering_configs[&#34;fields_hints&#34;] = list(fields_hints.items())
messages.append({&#34;role&#34;: &#34;system&#34;,
&#34;content&#34;: chevron.render(
open(self._extraction_prompt_template_path).read(),
rendering_configs)})
# TODO: either summarize first or break up into multiple tasks
interaction_history = tinyworld.pretty_current_interactions(max_content_length=None)
extraction_request_prompt = \
f&#34;&#34;&#34;
## Extraction objective
{extraction_objective}
## Situation
You are considering various agents.
{situation}
## Agents Interactions History
You will consider the history of interactions from various agents that exist in an environment called {tinyworld.name}.
Each interaction history includes stimuli the corresponding agent received as well as actions it performed.
{interaction_history}
&#34;&#34;&#34;
messages.append({&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: extraction_request_prompt})
next_message = openai_utils.client().send_message(messages, temperature=0.0)
debug_msg = f&#34;Extraction raw result message: {next_message}&#34;
logger.debug(debug_msg)
if verbose:
print(debug_msg)
if next_message is not None:
result = utils.extract_json(next_message[&#34;content&#34;])
else:
result = None
# cache the result
self.world_extraction[tinyworld.name] = result
return result
def save_as_json(self, filename:str, verbose:bool=False):
&#34;&#34;&#34;
Saves the last extraction results as JSON.
Args:
filename (str): The filename to save the JSON to.
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
with open(filename, &#39;w&#39;) as f:
json.dump({&#34;agent_extractions&#34;: self.agent_extraction,
&#34;world_extraction&#34;: self.world_extraction}, f, indent=4)
if verbose:
print(f&#34;Saved extraction results to {filename}&#34;)
def _get_default_values_if_necessary(self,
extraction_objective:str,
situation:str,
fields:List[str],
fields_hints:dict,
verbose:bool):
if extraction_objective is None:
extraction_objective = self.default_extraction_objective
if situation is None:
situation = self.default_situation
if fields is None:
fields = self.default_fields
if fields_hints is None:
fields_hints = self.default_fields_hints
if verbose is None:
verbose = self.default_verbose
return extraction_objective, situation, fields, fields_hints, verbose</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="tinytroupe.extraction.ResultsExtractor.extract_results_from_agent"><code class="name flex">
<span>def <span class="ident">extract_results_from_agent</span></span>(<span>self, tinyperson: <a title="tinytroupe.agent.tiny_person.TinyPerson" href="../agent/tiny_person.html#tinytroupe.agent.tiny_person.TinyPerson">TinyPerson</a>, extraction_objective: str = "The main points present in the agent's interactions history.", situation: str = '', fields: list = None, fields_hints: dict = None, verbose: bool = None)</span>
</code></dt>
<dd>
<div class="desc"><p>Extracts results from a TinyPerson instance.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>tinyperson</code></strong> :&ensp;<code>TinyPerson</code></dt>
<dd>The TinyPerson instance to extract results from.</dd>
<dt><strong><code>extraction_objective</code></strong> :&ensp;<code>str</code></dt>
<dd>The extraction objective.</dd>
<dt><strong><code>situation</code></strong> :&ensp;<code>str</code></dt>
<dd>The situation to consider.</dd>
<dt><strong><code>fields</code></strong> :&ensp;<code>list</code>, optional</dt>
<dd>The fields to extract. If None, the extractor will decide what names to use.
Defaults to None.</dd>
<dt><strong><code>fields_hints</code></strong> :&ensp;<code>dict</code>, optional</dt>
<dd>Hints for the fields to extract. Maps field names to strings with the hints. Defaults to None.</dd>
<dt><strong><code>verbose</code></strong> :&ensp;<code>bool</code>, optional</dt>
<dd>Whether to print debug messages. Defaults to False.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python"> def extract_results_from_agent(self,
tinyperson:TinyPerson,
extraction_objective:str=&#34;The main points present in the agent&#39;s interactions history.&#34;,
situation:str = &#34;&#34;,
fields:list=None,
fields_hints:dict=None,
verbose:bool=None):
&#34;&#34;&#34;
Extracts results from a TinyPerson instance.
Args:
tinyperson (TinyPerson): The TinyPerson instance to extract results from.
extraction_objective (str): The extraction objective.
situation (str): The situation to consider.
fields (list, optional): The fields to extract. If None, the extractor will decide what names to use.
Defaults to None.
fields_hints (dict, optional): Hints for the fields to extract. Maps field names to strings with the hints. Defaults to None.
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
extraction_objective, situation, fields, fields_hints, verbose = self._get_default_values_if_necessary(
extraction_objective, situation, fields, fields_hints, verbose
)
messages = []
rendering_configs = {}
if fields is not None:
rendering_configs[&#34;fields&#34;] = &#34;, &#34;.join(fields)
if fields_hints is not None:
rendering_configs[&#34;fields_hints&#34;] = list(fields_hints.items())
messages.append({&#34;role&#34;: &#34;system&#34;,
&#34;content&#34;: chevron.render(
open(self._extraction_prompt_template_path).read(),
rendering_configs)})
interaction_history = tinyperson.pretty_current_interactions(max_content_length=None)
extraction_request_prompt = \
f&#34;&#34;&#34;
## Extraction objective
{extraction_objective}
## Situation
You are considering a single agent, named {tinyperson.name}. Your objective thus refers to this agent specifically.
{situation}
## Agent Interactions History
You will consider an agent&#39;s history of interactions, which include stimuli it received as well as actions it
performed.
{interaction_history}
&#34;&#34;&#34;
messages.append({&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: extraction_request_prompt})
next_message = openai_utils.client().send_message(messages, temperature=0.0, frequency_penalty=0.0, presence_penalty=0.0)
debug_msg = f&#34;Extraction raw result message: {next_message}&#34;
logger.debug(debug_msg)
if verbose:
print(debug_msg)
if next_message is not None:
result = utils.extract_json(next_message[&#34;content&#34;])
else:
result = None
# cache the result
self.agent_extraction[tinyperson.name] = result
return result</code></pre>
</details>
</dd>
<dt id="tinytroupe.extraction.ResultsExtractor.extract_results_from_agents"><code class="name flex">
<span>def <span class="ident">extract_results_from_agents</span></span>(<span>self, agents: List[<a title="tinytroupe.agent.tiny_person.TinyPerson" href="../agent/tiny_person.html#tinytroupe.agent.tiny_person.TinyPerson">TinyPerson</a>], extraction_objective: str = None, situation: str = None, fields: list = None, fields_hints: dict = None, verbose: bool = None)</span>
</code></dt>
<dd>
<div class="desc"><p>Extracts results from a list of TinyPerson instances.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>agents</code></strong> :&ensp;<code>List[TinyPerson]</code></dt>
<dd>The list of TinyPerson instances to extract results from.</dd>
<dt><strong><code>extraction_objective</code></strong> :&ensp;<code>str</code></dt>
<dd>The extraction objective.</dd>
<dt><strong><code>situation</code></strong> :&ensp;<code>str</code></dt>
<dd>The situation to consider.</dd>
<dt><strong><code>fields</code></strong> :&ensp;<code>list</code>, optional</dt>
<dd>The fields to extract. If None, the extractor will decide what names to use.
Defaults to None.</dd>
<dt><strong><code>fields_hints</code></strong> :&ensp;<code>dict</code>, optional</dt>
<dd>Hints for the fields to extract. Maps field names to strings with the hints. Defaults to None.</dd>
<dt><strong><code>verbose</code></strong> :&ensp;<code>bool</code>, optional</dt>
<dd>Whether to print debug messages. Defaults to False.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def extract_results_from_agents(self,
agents:List[TinyPerson],
extraction_objective:str=None,
situation:str =None,
fields:list=None,
fields_hints:dict=None,
verbose:bool=None):
&#34;&#34;&#34;
Extracts results from a list of TinyPerson instances.
Args:
agents (List[TinyPerson]): The list of TinyPerson instances to extract results from.
extraction_objective (str): The extraction objective.
situation (str): The situation to consider.
fields (list, optional): The fields to extract. If None, the extractor will decide what names to use.
Defaults to None.
fields_hints (dict, optional): Hints for the fields to extract. Maps field names to strings with the hints. Defaults to None.
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
results = []
for agent in agents:
result = self.extract_results_from_agent(agent, extraction_objective, situation, fields, fields_hints, verbose)
results.append(result)
return results</code></pre>
</details>
</dd>
<dt id="tinytroupe.extraction.ResultsExtractor.extract_results_from_world"><code class="name flex">
<span>def <span class="ident">extract_results_from_world</span></span>(<span>self, tinyworld: <a title="tinytroupe.environment.tiny_world.TinyWorld" href="../environment/tiny_world.html#tinytroupe.environment.tiny_world.TinyWorld">TinyWorld</a>, extraction_objective: str = 'The main points that can be derived from the agents conversations and actions.', situation: str = '', fields: list = None, fields_hints: dict = None, verbose: bool = None)</span>
</code></dt>
<dd>
<div class="desc"><p>Extracts results from a TinyWorld instance.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>tinyworld</code></strong> :&ensp;<code>TinyWorld</code></dt>
<dd>The TinyWorld instance to extract results from.</dd>
<dt><strong><code>extraction_objective</code></strong> :&ensp;<code>str</code></dt>
<dd>The extraction objective.</dd>
<dt><strong><code>situation</code></strong> :&ensp;<code>str</code></dt>
<dd>The situation to consider.</dd>
<dt><strong><code>fields</code></strong> :&ensp;<code>list</code>, optional</dt>
<dd>The fields to extract. If None, the extractor will decide what names to use.
Defaults to None.</dd>
<dt><strong><code>verbose</code></strong> :&ensp;<code>bool</code>, optional</dt>
<dd>Whether to print debug messages. Defaults to False.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python"> def extract_results_from_world(self,
tinyworld:TinyWorld,
extraction_objective:str=&#34;The main points that can be derived from the agents conversations and actions.&#34;,
situation:str=&#34;&#34;,
fields:list=None,
fields_hints:dict=None,
verbose:bool=None):
&#34;&#34;&#34;
Extracts results from a TinyWorld instance.
Args:
tinyworld (TinyWorld): The TinyWorld instance to extract results from.
extraction_objective (str): The extraction objective.
situation (str): The situation to consider.
fields (list, optional): The fields to extract. If None, the extractor will decide what names to use.
Defaults to None.
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
extraction_objective, situation, fields, fields_hints, verbose = self._get_default_values_if_necessary(
extraction_objective, situation, fields, fields_hints, verbose
)
messages = []
rendering_configs = {}
if fields is not None:
rendering_configs[&#34;fields&#34;] = &#34;, &#34;.join(fields)
if fields_hints is not None:
rendering_configs[&#34;fields_hints&#34;] = list(fields_hints.items())
messages.append({&#34;role&#34;: &#34;system&#34;,
&#34;content&#34;: chevron.render(
open(self._extraction_prompt_template_path).read(),
rendering_configs)})
# TODO: either summarize first or break up into multiple tasks
interaction_history = tinyworld.pretty_current_interactions(max_content_length=None)
extraction_request_prompt = \
f&#34;&#34;&#34;
## Extraction objective
{extraction_objective}
## Situation
You are considering various agents.
{situation}
## Agents Interactions History
You will consider the history of interactions from various agents that exist in an environment called {tinyworld.name}.
Each interaction history includes stimuli the corresponding agent received as well as actions it performed.
{interaction_history}
&#34;&#34;&#34;
messages.append({&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: extraction_request_prompt})
next_message = openai_utils.client().send_message(messages, temperature=0.0)
debug_msg = f&#34;Extraction raw result message: {next_message}&#34;
logger.debug(debug_msg)
if verbose:
print(debug_msg)
if next_message is not None:
result = utils.extract_json(next_message[&#34;content&#34;])
else:
result = None
# cache the result
self.world_extraction[tinyworld.name] = result
return result</code></pre>
</details>
</dd>
<dt id="tinytroupe.extraction.ResultsExtractor.save_as_json"><code class="name flex">
<span>def <span class="ident">save_as_json</span></span>(<span>self, filename: str, verbose: bool = False)</span>
</code></dt>
<dd>
<div class="desc"><p>Saves the last extraction results as JSON.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>filename</code></strong> :&ensp;<code>str</code></dt>
<dd>The filename to save the JSON to.</dd>
<dt><strong><code>verbose</code></strong> :&ensp;<code>bool</code>, optional</dt>
<dd>Whether to print debug messages. Defaults to False.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def save_as_json(self, filename:str, verbose:bool=False):
&#34;&#34;&#34;
Saves the last extraction results as JSON.
Args:
filename (str): The filename to save the JSON to.
verbose (bool, optional): Whether to print debug messages. Defaults to False.
&#34;&#34;&#34;
with open(filename, &#39;w&#39;) as f:
json.dump({&#34;agent_extractions&#34;: self.agent_extraction,
&#34;world_extraction&#34;: self.world_extraction}, f, indent=4)
if verbose:
print(f&#34;Saved extraction results to {filename}&#34;)</code></pre>
</details>
</dd>
</dl>
</dd>
<dt id="tinytroupe.extraction.ResultsReducer"><code class="flex name class">
<span>class <span class="ident">ResultsReducer</span></span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class ResultsReducer:
def __init__(self):
self.results = {}
self.rules = {}
def add_reduction_rule(self, trigger: str, func: callable):
if trigger in self.rules:
raise Exception(f&#34;Rule for {trigger} already exists.&#34;)
self.rules[trigger] = func
def reduce_agent(self, agent: TinyPerson) -&gt; list:
reduction = []
for message in agent.episodic_memory.retrieve_all():
if message[&#39;role&#39;] == &#39;system&#39;:
continue # doing nothing for `system` role yet at least
elif message[&#39;role&#39;] == &#39;user&#39;:
# User role is related to stimuli only
stimulus_type = message[&#39;content&#39;][&#39;stimuli&#39;][0].get(&#39;type&#39;, None)
stimulus_content = message[&#39;content&#39;][&#39;stimuli&#39;][0].get(&#39;content&#39;, None)
stimulus_source = message[&#39;content&#39;][&#39;stimuli&#39;][0].get(&#39;source&#39;, None)
stimulus_timestamp = message[&#39;simulation_timestamp&#39;]
if stimulus_type in self.rules:
extracted = self.rules[stimulus_type](focus_agent=agent, source_agent=TinyPerson.get_agent_by_name(stimulus_source), target_agent=agent, kind=&#39;stimulus&#39;, event=stimulus_type, content=stimulus_content, timestamp=stimulus_timestamp)
if extracted is not None:
reduction.append(extracted)
elif message[&#39;role&#39;] == &#39;assistant&#39;:
# Assistant role is related to actions only
if &#39;action&#39; in message[&#39;content&#39;]:
action_type = message[&#39;content&#39;][&#39;action&#39;].get(&#39;type&#39;, None)
action_content = message[&#39;content&#39;][&#39;action&#39;].get(&#39;content&#39;, None)
action_target = message[&#39;content&#39;][&#39;action&#39;].get(&#39;target&#39;, None)
action_timestamp = message[&#39;simulation_timestamp&#39;]
if action_type in self.rules:
extracted = self.rules[action_type](focus_agent=agent, source_agent=agent, target_agent=TinyPerson.get_agent_by_name(action_target), kind=&#39;action&#39;, event=action_type, content=action_content, timestamp=action_timestamp)
if extracted is not None:
reduction.append(extracted)
return reduction
def reduce_agent_to_dataframe(self, agent: TinyPerson, column_names: list=None) -&gt; pd.DataFrame:
reduction = self.reduce_agent(agent)
return pd.DataFrame(reduction, columns=column_names)</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="tinytroupe.extraction.ResultsReducer.add_reduction_rule"><code class="name flex">
<span>def <span class="ident">add_reduction_rule</span></span>(<span>self, trigger: str, func: <built-in function callable>)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def add_reduction_rule(self, trigger: str, func: callable):
if trigger in self.rules:
raise Exception(f&#34;Rule for {trigger} already exists.&#34;)
self.rules[trigger] = func</code></pre>
</details>
</dd>
<dt id="tinytroupe.extraction.ResultsReducer.reduce_agent"><code class="name flex">
<span>def <span class="ident">reduce_agent</span></span>(<span>self, agent: <a title="tinytroupe.agent.tiny_person.TinyPerson" href="../agent/tiny_person.html#tinytroupe.agent.tiny_person.TinyPerson">TinyPerson</a>) ‑> list</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def reduce_agent(self, agent: TinyPerson) -&gt; list:
reduction = []
for message in agent.episodic_memory.retrieve_all():
if message[&#39;role&#39;] == &#39;system&#39;:
continue # doing nothing for `system` role yet at least
elif message[&#39;role&#39;] == &#39;user&#39;:
# User role is related to stimuli only
stimulus_type = message[&#39;content&#39;][&#39;stimuli&#39;][0].get(&#39;type&#39;, None)
stimulus_content = message[&#39;content&#39;][&#39;stimuli&#39;][0].get(&#39;content&#39;, None)
stimulus_source = message[&#39;content&#39;][&#39;stimuli&#39;][0].get(&#39;source&#39;, None)
stimulus_timestamp = message[&#39;simulation_timestamp&#39;]
if stimulus_type in self.rules:
extracted = self.rules[stimulus_type](focus_agent=agent, source_agent=TinyPerson.get_agent_by_name(stimulus_source), target_agent=agent, kind=&#39;stimulus&#39;, event=stimulus_type, content=stimulus_content, timestamp=stimulus_timestamp)
if extracted is not None:
reduction.append(extracted)
elif message[&#39;role&#39;] == &#39;assistant&#39;:
# Assistant role is related to actions only
if &#39;action&#39; in message[&#39;content&#39;]:
action_type = message[&#39;content&#39;][&#39;action&#39;].get(&#39;type&#39;, None)
action_content = message[&#39;content&#39;][&#39;action&#39;].get(&#39;content&#39;, None)
action_target = message[&#39;content&#39;][&#39;action&#39;].get(&#39;target&#39;, None)
action_timestamp = message[&#39;simulation_timestamp&#39;]
if action_type in self.rules:
extracted = self.rules[action_type](focus_agent=agent, source_agent=agent, target_agent=TinyPerson.get_agent_by_name(action_target), kind=&#39;action&#39;, event=action_type, content=action_content, timestamp=action_timestamp)
if extracted is not None:
reduction.append(extracted)
return reduction</code></pre>
</details>
</dd>
<dt id="tinytroupe.extraction.ResultsReducer.reduce_agent_to_dataframe"><code class="name flex">
<span>def <span class="ident">reduce_agent_to_dataframe</span></span>(<span>self, agent: <a title="tinytroupe.agent.tiny_person.TinyPerson" href="../agent/tiny_person.html#tinytroupe.agent.tiny_person.TinyPerson">TinyPerson</a>, column_names: list = None) ‑> pandas.core.frame.DataFrame</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def reduce_agent_to_dataframe(self, agent: TinyPerson, column_names: list=None) -&gt; pd.DataFrame:
reduction = self.reduce_agent(agent)
return pd.DataFrame(reduction, columns=column_names)</code></pre>
</details>
</dd>
</dl>
</dd>
<dt id="tinytroupe.extraction.ResultsReporter"><code class="flex name class">
<span>class <span class="ident">ResultsReporter</span></span>
<span>(</span><span>default_reporting_task: str = 'Summarize the key findings, insights, and outcomes from the simulation data.', verbose: bool = False)</span>
</code></dt>
<dd>
<div class="desc"><p>Initializes the ResultsReporter.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>default_reporting_task</code></strong> :&ensp;<code>str</code></dt>
<dd>The default task to ask agents when generating reports.</dd>
<dt><strong><code>verbose</code></strong> :&ensp;<code>bool</code></dt>
<dd>Whether to print debug messages.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class ResultsReporter:
def __init__(self,
default_reporting_task: str = &#34;Summarize the key findings, insights, and outcomes from the simulation data.&#34;,
verbose: bool = False):
&#34;&#34;&#34;
Initializes the ResultsReporter.
Args:
default_reporting_task (str): The default task to ask agents when generating reports.
verbose (bool): Whether to print debug messages.
&#34;&#34;&#34;
self.default_reporting_task = default_reporting_task
self.verbose = verbose
self.console = Console()
# Cache for generated reports
self.last_report = None
def report_from_agents(self,
agents: Union[TinyPerson, TinyWorld, List[TinyPerson]],
reporting_task: str = None,
report_title: str = &#34;Simulation Report&#34;,
include_agent_summaries: bool = True,
consolidate_responses: bool = True,
requirements: str = &#34;Present the findings in a clear, structured manner.&#34;) -&gt; str:
&#34;&#34;&#34;
Option 1: Generate a report by asking agents about specific reporting tasks.
Args:
agents: Single agent, TinyWorld, or list of agents to interview.
reporting_task: The specific task to ask agents about.
report_title: Title for the generated report.
include_agent_summaries: Whether to include agent mini-bios in the report.
consolidate_responses: Whether to consolidate all responses into a single report.
requirements: Formatting or content requirements for the report.
Returns:
str: The generated Markdown report.
&#34;&#34;&#34;
if reporting_task is None:
reporting_task = self.default_reporting_task
# Extract agents from input
agent_list = self._extract_agents(agents)
if self.verbose:
logger.info(f&#34;Interviewing {len(agent_list)} agents for report generation.&#34;)
# Collect responses from agents
agent_responses = []
for agent in agent_list:
response = self._interview_agent(agent, reporting_task)
agent_responses.append({
&#34;agent&#34;: agent,
&#34;response&#34;: response
})
# Generate the report
report = self._format_agent_interview_report(
agent_responses,
report_title,
reporting_task,
include_agent_summaries,
consolidate_responses,
requirements
)
self.last_report = report
return report
def report_from_interactions(self,
agents: Union[TinyPerson, TinyWorld, List[TinyPerson]],
report_title: str = &#34;Interaction Analysis Report&#34;,
include_agent_summaries: bool = True,
first_n: int = None,
last_n: int = None,
max_content_length: int = None,
requirements: str = &#34;Present the findings in a clear, structured manner.&#34;) -&gt; str:
&#34;&#34;&#34;
Option 2: Generate a report by analyzing agents&#39; historical interactions.
Args:
agents: Single agent, TinyWorld, or list of agents to analyze.
report_title: Title for the generated report.
include_agent_summaries: Whether to include agent mini-bios.
first_n: Number of first interactions to include.
last_n: Number of last interactions to include.
max_content_length: Maximum content length for interactions.
requirements: Formatting or content requirements for the report.
Returns:
str: The generated Markdown report.
&#34;&#34;&#34;
# Extract agents from input
agent_list = self._extract_agents(agents)
if self.verbose:
logger.info(f&#34;Analyzing interactions from {len(agent_list)} agents.&#34;)
# Collect interaction data
interactions_data = []
for agent in agent_list:
interactions = agent.pretty_current_interactions(
simplified=True,
first_n=first_n,
last_n=last_n,
max_content_length=max_content_length
)
interactions_data.append({
&#34;agent&#34;: agent,
&#34;interactions&#34;: interactions
})
# Generate the report
report = self._format_interactions_report(
interactions_data,
report_title,
include_agent_summaries,
requirements
)
self.last_report = report
return report
def report_from_data(self,
data: Union[str, Dict[str, Any], List[Dict[str, Any]]],
report_title: str = &#34;Data Report&#34;,
requirements: str = &#34;Present the findings in a clear, structured manner.&#34;) -&gt; str:
&#34;&#34;&#34;
Option 3: Generate a report from raw text or structured data.
Args:
data: Raw text, dictionary, or list of dictionaries to format.
report_title: Title for the generated report.
requirements: Formatting or content requirements for the report. If None, uses simple formatting.
Returns:
str: The generated Markdown report.
&#34;&#34;&#34;
if self.verbose:
logger.info(&#34;Generating report from raw data.&#34;)
# Generate the report
report = self._format_data_report(data, report_title, requirements)
self.last_report = report
return report
def display_report(self, report: str = None):
&#34;&#34;&#34;
Display a report on the console with rich formatting.
Args:
report: The report to display. If None, uses the last generated report.
&#34;&#34;&#34;
if report is None:
report = self.last_report
if report is None:
self.console.print(&#34;[red]No report available to display.[/red]&#34;)
return
markdown = Markdown(report)
self.console.print(markdown)
def save_report(self,
filename: str,
report: str = None,
verbose: bool = None):
&#34;&#34;&#34;
Save a report to a file.
Args:
filename: The filename to save the report to.
report: The report to save. If None, uses the last generated report.
verbose: Whether to print confirmation message.
&#34;&#34;&#34;
if report is None:
report = self.last_report
if report is None:
raise ValueError(&#34;No report available to save.&#34;)
if verbose is None:
verbose = self.verbose
with open(filename, &#39;w&#39;, encoding=&#39;utf-8&#39;) as f:
f.write(report)
if verbose:
logger.info(f&#34;Report saved to {filename}&#34;)
def _extract_agents(self, agents) -&gt; List[TinyPerson]:
&#34;&#34;&#34;Extract a list of TinyPerson objects from various input types.&#34;&#34;&#34;
if isinstance(agents, TinyPerson):
return [agents]
elif isinstance(agents, TinyWorld):
return agents.agents
elif isinstance(agents, list):
return agents
else:
raise ValueError(&#34;Agents must be a TinyPerson, TinyWorld, or list of TinyPerson objects.&#34;)
def _interview_agent(self, agent: TinyPerson, reporting_task: str) -&gt; str:
&#34;&#34;&#34;Interview a single agent about the reporting task.&#34;&#34;&#34;
if self.verbose:
logger.debug(f&#34;Interviewing agent {agent.name} about: {reporting_task}&#34;)
# Following TinyTroupe patterns - directly interact with the agent
prompt = f&#34;&#34;&#34;
I need you to provide a comprehensive report based on your experiences and observations.
Reporting task: {reporting_task}
Please provide detailed insights, specific examples, and key findings from your perspective.
Focus on what you&#39;ve learned, observed, and experienced during the simulation.
&#34;&#34;&#34;
# Use listen_and_act pattern to get agent&#39;s response
agent.listen(prompt)
actions = agent.act(return_actions=True)
# Extract the response from the agent&#39;s actions
response = &#34;&#34;
for action in actions:
if action[&#34;action&#34;][&#34;type&#34;] == &#34;TALK&#34;:
response += action[&#34;action&#34;][&#34;content&#34;] + &#34;\n&#34;
if self.verbose:
logger.debug(f&#34;Agent {agent.name} response received.&#34;)
return response.strip()
def _format_agent_interview_report(self,
agent_responses: List[Dict],
title: str,
task: str,
include_summaries: bool,
consolidate: bool,
requirements: str) -&gt; str:
&#34;&#34;&#34;Format agent interview responses into a Markdown report.&#34;&#34;&#34;
# Prepare data for LLM formatting
agents_data = []
for resp in agent_responses:
agent_info = {
&#34;name&#34;: resp[&#34;agent&#34;].name,
&#34;response&#34;: resp[&#34;response&#34;]
}
if include_summaries:
agent_info[&#34;bio&#34;] = resp[&#34;agent&#34;].minibio(extended=False)
agents_data.append(agent_info)
# Generate report using LLM
return self._generate_report_with_llm(
title=title,
report_type=&#34;agent_interview&#34;,
data={
&#34;reporting_task&#34;: task,
&#34;agents_data&#34;: agents_data,
&#34;consolidate&#34;: consolidate
},
include_summaries=include_summaries,
requirements=requirements
)
def _format_interactions_report(self,
interactions_data: List[Dict],
title: str,
include_summaries: bool,
requirements: str) -&gt; str:
&#34;&#34;&#34;Format interaction data into a Markdown report.&#34;&#34;&#34;
# Prepare data for LLM formatting
agents_data = []
for data in interactions_data:
agent_info = {
&#34;name&#34;: data[&#34;agent&#34;].name,
&#34;interactions&#34;: data[&#34;interactions&#34;]
}
if include_summaries:
agent_info[&#34;bio&#34;] = data[&#34;agent&#34;].minibio(extended=False)
agents_data.append(agent_info)
# Generate report using LLM
return self._generate_report_with_llm(
title=title,
report_type=&#34;interactions&#34;,
data={&#34;agents_data&#34;: agents_data},
include_summaries=include_summaries,
requirements=requirements
)
def _format_data_report(self,
data: Any,
title: str,
requirements: str) -&gt; str:
&#34;&#34;&#34;Format raw data into a Markdown report.&#34;&#34;&#34;
return self._generate_report_with_llm(
title=title,
report_type=&#34;custom_data&#34;,
data=data,
requirements=requirements
)
def _generate_report_with_llm(self,
title: str,
report_type: str,
data: Any,
include_summaries: bool = False,
requirements: str = None) -&gt; str:
&#34;&#34;&#34;Generate a report using LLM based on the report type and data.&#34;&#34;&#34;
# Base system prompt
system_prompt = &#34;You are a professional report writer who creates clear, well-structured Markdown reports.&#34;
# Type-specific prompts and instructions
if report_type == &#34;agent_interview&#34;:
system_prompt += &#34; You specialize in synthesizing interview responses from multiple agents.&#34;
user_prompt = f&#34;&#34;&#34;
## Task
Create a comprehensive report based on agent interviews such that it fulfills the
specified requirements below.
## Report Title
{title}
## Report Details
- **Reporting Task:** {data[&#39;reporting_task&#39;]}
- **Number of Agents Interviewed:** {len(data[&#39;agents_data&#39;])}
- **Generated on:** {self._get_timestamp()}
## Agent Responses
{json.dumps(data[&#39;agents_data&#39;], indent=2)}
## Instructions
- Start with the title as a level-1 header
- Write a direct, clear report, but do not simplify or summarize the information
- Make sure all important details are included. This is not a summary, but a detailed report, so you never remove information, you just make it more readable
- Do not include the original data or agent responses, but only the resulting report information
- For each agent, include their bio if provided
- Use proper Markdown formatting throughout
- Follow the requirements given next, which can also override any of these rules
## Requirements
{requirements}
&#34;&#34;&#34;
elif report_type == &#34;interactions&#34;:
system_prompt += &#34; You specialize in analyzing and presenting agent interaction histories.&#34;
user_prompt = f&#34;&#34;&#34;
## Task
Create a report analyzing agent interactions from a simulation such that it fulfills the
specified requirements below.
## Report Title
{title}
## Report Details
- **Number of Agents Analyzed:** {len(data[&#39;agents_data&#39;])}
- **Generated on:** {self._get_timestamp()}
## Agent Interaction Data
{json.dumps(data[&#39;agents_data&#39;], indent=2)}
## Instructions
- Start with the title as a level-1 header
- Write a direct, clear report, but do not simplify or summarize the information
- Make sure all important details are included. This is not a summary, but a detailed report, so you never remove information, you just make it more readable
- Do not include agents&#39; interaction history, but only the resulting report information
- For each agent, include their bio if provided
- Use proper Markdown formatting throughout
- Follow the requirements given next, which can also override any of these rules
## Requirements
{requirements}
&#34;&#34;&#34;
elif report_type == &#34;custom_data&#34;:
# Handle arbitrary data without assuming any structure
if isinstance(data, str):
data_representation = data
else:
# For any other type, convert to JSON for a clean representation
data_representation = json.dumps(data, indent=2)
user_prompt = f&#34;&#34;&#34;
## Task
Create a well-structured Markdown report based on the provided data such that it fulfills the
specified requirements below.
## Report Title
{title}
## Generated on
{self._get_timestamp()}
## Data to Format
{data_representation}
## Instructions
- Start with the title as a level-1 header
- Write a direct, clear report, but do not simplify or summarize the information
- Make sure all important details are included. This is not a summary, but a detailed report, so you never remove information, you just make it more readable
- Use proper Markdown formatting throughout
- Follow the requirements given next, which can also override any of these rules
## Requirements
{requirements if requirements else &#34;Use your best judgment to create a clear, informative report that presents the data in an organized and readable manner.&#34;}
&#34;&#34;&#34;
else:
raise ValueError(f&#34;Unknown report type: {report_type}&#34;)
# Generate the report
report_chat = LLMChat(
system_prompt=system_prompt,
user_prompt=user_prompt,
output_type=str,
enable_json_output_format=False,
model=default[&#34;model&#34;],
temperature=0.3
)
return report_chat()
def _get_timestamp(self) -&gt; str:
&#34;&#34;&#34;Get current timestamp for report headers.&#34;&#34;&#34;
from datetime import datetime
return datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="tinytroupe.extraction.ResultsReporter.display_report"><code class="name flex">
<span>def <span class="ident">display_report</span></span>(<span>self, report: str = None)</span>
</code></dt>
<dd>
<div class="desc"><p>Display a report on the console with rich formatting.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>report</code></strong></dt>
<dd>The report to display. If None, uses the last generated report.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def display_report(self, report: str = None):
&#34;&#34;&#34;
Display a report on the console with rich formatting.
Args:
report: The report to display. If None, uses the last generated report.
&#34;&#34;&#34;
if report is None:
report = self.last_report
if report is None:
self.console.print(&#34;[red]No report available to display.[/red]&#34;)
return
markdown = Markdown(report)
self.console.print(markdown)</code></pre>
</details>
</dd>
<dt id="tinytroupe.extraction.ResultsReporter.report_from_agents"><code class="name flex">
<span>def <span class="ident">report_from_agents</span></span>(<span>self, agents: Union[<a title="tinytroupe.agent.tiny_person.TinyPerson" href="../agent/tiny_person.html#tinytroupe.agent.tiny_person.TinyPerson">TinyPerson</a><a title="tinytroupe.environment.tiny_world.TinyWorld" href="../environment/tiny_world.html#tinytroupe.environment.tiny_world.TinyWorld">TinyWorld</a>, List[<a title="tinytroupe.agent.tiny_person.TinyPerson" href="../agent/tiny_person.html#tinytroupe.agent.tiny_person.TinyPerson">TinyPerson</a>]], reporting_task: str = None, report_title: str = 'Simulation Report', include_agent_summaries: bool = True, consolidate_responses: bool = True, requirements: str = 'Present the findings in a clear, structured manner.') ‑> str</span>
</code></dt>
<dd>
<div class="desc"><p>Option 1: Generate a report by asking agents about specific reporting tasks.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>agents</code></strong></dt>
<dd>Single agent, TinyWorld, or list of agents to interview.</dd>
<dt><strong><code>reporting_task</code></strong></dt>
<dd>The specific task to ask agents about.</dd>
<dt><strong><code>report_title</code></strong></dt>
<dd>Title for the generated report.</dd>
<dt><strong><code>include_agent_summaries</code></strong></dt>
<dd>Whether to include agent mini-bios in the report.</dd>
<dt><strong><code>consolidate_responses</code></strong></dt>
<dd>Whether to consolidate all responses into a single report.</dd>
<dt><strong><code>requirements</code></strong></dt>
<dd>Formatting or content requirements for the report.</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><code>str</code></dt>
<dd>The generated Markdown report.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def report_from_agents(self,
agents: Union[TinyPerson, TinyWorld, List[TinyPerson]],
reporting_task: str = None,
report_title: str = &#34;Simulation Report&#34;,
include_agent_summaries: bool = True,
consolidate_responses: bool = True,
requirements: str = &#34;Present the findings in a clear, structured manner.&#34;) -&gt; str:
&#34;&#34;&#34;
Option 1: Generate a report by asking agents about specific reporting tasks.
Args:
agents: Single agent, TinyWorld, or list of agents to interview.
reporting_task: The specific task to ask agents about.
report_title: Title for the generated report.
include_agent_summaries: Whether to include agent mini-bios in the report.
consolidate_responses: Whether to consolidate all responses into a single report.
requirements: Formatting or content requirements for the report.
Returns:
str: The generated Markdown report.
&#34;&#34;&#34;
if reporting_task is None:
reporting_task = self.default_reporting_task
# Extract agents from input
agent_list = self._extract_agents(agents)
if self.verbose:
logger.info(f&#34;Interviewing {len(agent_list)} agents for report generation.&#34;)
# Collect responses from agents
agent_responses = []
for agent in agent_list:
response = self._interview_agent(agent, reporting_task)
agent_responses.append({
&#34;agent&#34;: agent,
&#34;response&#34;: response
})
# Generate the report
report = self._format_agent_interview_report(
agent_responses,
report_title,
reporting_task,
include_agent_summaries,
consolidate_responses,
requirements
)
self.last_report = report
return report</code></pre>
</details>
</dd>
<dt id="tinytroupe.extraction.ResultsReporter.report_from_data"><code class="name flex">
<span>def <span class="ident">report_from_data</span></span>(<span>self, data: Union[str, Dict[str, Any], List[Dict[str, Any]]], report_title: str = 'Data Report', requirements: str = 'Present the findings in a clear, structured manner.') ‑> str</span>
</code></dt>
<dd>
<div class="desc"><p>Option 3: Generate a report from raw text or structured data.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>data</code></strong></dt>
<dd>Raw text, dictionary, or list of dictionaries to format.</dd>
<dt><strong><code>report_title</code></strong></dt>
<dd>Title for the generated report.</dd>
<dt><strong><code>requirements</code></strong></dt>
<dd>Formatting or content requirements for the report. If None, uses simple formatting.</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><code>str</code></dt>
<dd>The generated Markdown report.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def report_from_data(self,
data: Union[str, Dict[str, Any], List[Dict[str, Any]]],
report_title: str = &#34;Data Report&#34;,
requirements: str = &#34;Present the findings in a clear, structured manner.&#34;) -&gt; str:
&#34;&#34;&#34;
Option 3: Generate a report from raw text or structured data.
Args:
data: Raw text, dictionary, or list of dictionaries to format.
report_title: Title for the generated report.
requirements: Formatting or content requirements for the report. If None, uses simple formatting.
Returns:
str: The generated Markdown report.
&#34;&#34;&#34;
if self.verbose:
logger.info(&#34;Generating report from raw data.&#34;)
# Generate the report
report = self._format_data_report(data, report_title, requirements)
self.last_report = report
return report</code></pre>
</details>
</dd>
<dt id="tinytroupe.extraction.ResultsReporter.report_from_interactions"><code class="name flex">
<span>def <span class="ident">report_from_interactions</span></span>(<span>self, agents: Union[<a title="tinytroupe.agent.tiny_person.TinyPerson" href="../agent/tiny_person.html#tinytroupe.agent.tiny_person.TinyPerson">TinyPerson</a><a title="tinytroupe.environment.tiny_world.TinyWorld" href="../environment/tiny_world.html#tinytroupe.environment.tiny_world.TinyWorld">TinyWorld</a>, List[<a title="tinytroupe.agent.tiny_person.TinyPerson" href="../agent/tiny_person.html#tinytroupe.agent.tiny_person.TinyPerson">TinyPerson</a>]], report_title: str = 'Interaction Analysis Report', include_agent_summaries: bool = True, first_n: int = None, last_n: int = None, max_content_length: int = None, requirements: str = 'Present the findings in a clear, structured manner.') ‑> str</span>
</code></dt>
<dd>
<div class="desc"><p>Option 2: Generate a report by analyzing agents' historical interactions.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>agents</code></strong></dt>
<dd>Single agent, TinyWorld, or list of agents to analyze.</dd>
<dt><strong><code>report_title</code></strong></dt>
<dd>Title for the generated report.</dd>
<dt><strong><code>include_agent_summaries</code></strong></dt>
<dd>Whether to include agent mini-bios.</dd>
<dt><strong><code>first_n</code></strong></dt>
<dd>Number of first interactions to include.</dd>
<dt><strong><code>last_n</code></strong></dt>
<dd>Number of last interactions to include.</dd>
<dt><strong><code>max_content_length</code></strong></dt>
<dd>Maximum content length for interactions.</dd>
<dt><strong><code>requirements</code></strong></dt>
<dd>Formatting or content requirements for the report.</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><code>str</code></dt>
<dd>The generated Markdown report.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def report_from_interactions(self,
agents: Union[TinyPerson, TinyWorld, List[TinyPerson]],
report_title: str = &#34;Interaction Analysis Report&#34;,
include_agent_summaries: bool = True,
first_n: int = None,
last_n: int = None,
max_content_length: int = None,
requirements: str = &#34;Present the findings in a clear, structured manner.&#34;) -&gt; str:
&#34;&#34;&#34;
Option 2: Generate a report by analyzing agents&#39; historical interactions.
Args:
agents: Single agent, TinyWorld, or list of agents to analyze.
report_title: Title for the generated report.
include_agent_summaries: Whether to include agent mini-bios.
first_n: Number of first interactions to include.
last_n: Number of last interactions to include.
max_content_length: Maximum content length for interactions.
requirements: Formatting or content requirements for the report.
Returns:
str: The generated Markdown report.
&#34;&#34;&#34;
# Extract agents from input
agent_list = self._extract_agents(agents)
if self.verbose:
logger.info(f&#34;Analyzing interactions from {len(agent_list)} agents.&#34;)
# Collect interaction data
interactions_data = []
for agent in agent_list:
interactions = agent.pretty_current_interactions(
simplified=True,
first_n=first_n,
last_n=last_n,
max_content_length=max_content_length
)
interactions_data.append({
&#34;agent&#34;: agent,
&#34;interactions&#34;: interactions
})
# Generate the report
report = self._format_interactions_report(
interactions_data,
report_title,
include_agent_summaries,
requirements
)
self.last_report = report
return report</code></pre>
</details>
</dd>
<dt id="tinytroupe.extraction.ResultsReporter.save_report"><code class="name flex">
<span>def <span class="ident">save_report</span></span>(<span>self, filename: str, report: str = None, verbose: bool = None)</span>
</code></dt>
<dd>
<div class="desc"><p>Save a report to a file.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>filename</code></strong></dt>
<dd>The filename to save the report to.</dd>
<dt><strong><code>report</code></strong></dt>
<dd>The report to save. If None, uses the last generated report.</dd>
<dt><strong><code>verbose</code></strong></dt>
<dd>Whether to print confirmation message.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def save_report(self,
filename: str,
report: str = None,
verbose: bool = None):
&#34;&#34;&#34;
Save a report to a file.
Args:
filename: The filename to save the report to.
report: The report to save. If None, uses the last generated report.
verbose: Whether to print confirmation message.
&#34;&#34;&#34;
if report is None:
report = self.last_report
if report is None:
raise ValueError(&#34;No report available to save.&#34;)
if verbose is None:
verbose = self.verbose
with open(filename, &#39;w&#39;, encoding=&#39;utf-8&#39;) as f:
f.write(report)
if verbose:
logger.info(f&#34;Report saved to {filename}&#34;)</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="tinytroupe" href="../index.html">tinytroupe</a></code></li>
</ul>
</li>
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
<ul>
<li><code><a title="tinytroupe.extraction.artifact_exporter" href="artifact_exporter.html">tinytroupe.extraction.artifact_exporter</a></code></li>
<li><code><a title="tinytroupe.extraction.normalizer" href="normalizer.html">tinytroupe.extraction.normalizer</a></code></li>
<li><code><a title="tinytroupe.extraction.results_extractor" href="results_extractor.html">tinytroupe.extraction.results_extractor</a></code></li>
<li><code><a title="tinytroupe.extraction.results_reducer" href="results_reducer.html">tinytroupe.extraction.results_reducer</a></code></li>
<li><code><a title="tinytroupe.extraction.results_reporter" href="results_reporter.html">tinytroupe.extraction.results_reporter</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="tinytroupe.extraction.ArtifactExporter" href="#tinytroupe.extraction.ArtifactExporter">ArtifactExporter</a></code></h4>
<ul class="">
<li><code><a title="tinytroupe.extraction.ArtifactExporter.export" href="#tinytroupe.extraction.ArtifactExporter.export">export</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="tinytroupe.extraction.Normalizer" href="#tinytroupe.extraction.Normalizer">Normalizer</a></code></h4>
<ul class="">
<li><code><a title="tinytroupe.extraction.Normalizer.normalize" href="#tinytroupe.extraction.Normalizer.normalize">normalize</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="tinytroupe.extraction.ResultsExtractor" href="#tinytroupe.extraction.ResultsExtractor">ResultsExtractor</a></code></h4>
<ul class="">
<li><code><a title="tinytroupe.extraction.ResultsExtractor.extract_results_from_agent" href="#tinytroupe.extraction.ResultsExtractor.extract_results_from_agent">extract_results_from_agent</a></code></li>
<li><code><a title="tinytroupe.extraction.ResultsExtractor.extract_results_from_agents" href="#tinytroupe.extraction.ResultsExtractor.extract_results_from_agents">extract_results_from_agents</a></code></li>
<li><code><a title="tinytroupe.extraction.ResultsExtractor.extract_results_from_world" href="#tinytroupe.extraction.ResultsExtractor.extract_results_from_world">extract_results_from_world</a></code></li>
<li><code><a title="tinytroupe.extraction.ResultsExtractor.save_as_json" href="#tinytroupe.extraction.ResultsExtractor.save_as_json">save_as_json</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="tinytroupe.extraction.ResultsReducer" href="#tinytroupe.extraction.ResultsReducer">ResultsReducer</a></code></h4>
<ul class="">
<li><code><a title="tinytroupe.extraction.ResultsReducer.add_reduction_rule" href="#tinytroupe.extraction.ResultsReducer.add_reduction_rule">add_reduction_rule</a></code></li>
<li><code><a title="tinytroupe.extraction.ResultsReducer.reduce_agent" href="#tinytroupe.extraction.ResultsReducer.reduce_agent">reduce_agent</a></code></li>
<li><code><a title="tinytroupe.extraction.ResultsReducer.reduce_agent_to_dataframe" href="#tinytroupe.extraction.ResultsReducer.reduce_agent_to_dataframe">reduce_agent_to_dataframe</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="tinytroupe.extraction.ResultsReporter" href="#tinytroupe.extraction.ResultsReporter">ResultsReporter</a></code></h4>
<ul class="">
<li><code><a title="tinytroupe.extraction.ResultsReporter.display_report" href="#tinytroupe.extraction.ResultsReporter.display_report">display_report</a></code></li>
<li><code><a title="tinytroupe.extraction.ResultsReporter.report_from_agents" href="#tinytroupe.extraction.ResultsReporter.report_from_agents">report_from_agents</a></code></li>
<li><code><a title="tinytroupe.extraction.ResultsReporter.report_from_data" href="#tinytroupe.extraction.ResultsReporter.report_from_data">report_from_data</a></code></li>
<li><code><a title="tinytroupe.extraction.ResultsReporter.report_from_interactions" href="#tinytroupe.extraction.ResultsReporter.report_from_interactions">report_from_interactions</a></code></li>
<li><code><a title="tinytroupe.extraction.ResultsReporter.save_report" href="#tinytroupe.extraction.ResultsReporter.save_report">save_report</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>