Generative AI

How to build an agentic agentic age that learns continuously through episodic experiences and semantic patterns of long-term independence

In this tutorial, we look at how to build agentic systems that think beyond a single interaction by using memory as a core capability. We go through the way we design episodic memory to store experiences and semantic memory to capture long-term patterns, allowing the agent to change its behavior over many sessions. As we use planning, execution, review, and demonstration, we see how the agent gradually meets user preferences and becomes more autonomous. In the end, we understand how messy thinking helps us create agents that are more responsive, flexible, and intelligent with every interaction. Look Full codes here.

import numpy as np
from collections import defaultdict
import json
from datetime import datetime
import pickle


class EpisodicMemory:
   def __init__(self, capacity=100):
       self.capacity = capacity
       self.episodes = []
      
   def store(self, state, action, outcome, timestamp=None):
       if timestamp is None:
           timestamp = datetime.now().isoformat()
       episode = {
           'state': state,
           'action': action,
           'outcome': outcome,
           'timestamp': timestamp,
           'embedding': self._embed(state, action, outcome)
       }
       self.episodes.append(episode)
       if len(self.episodes) > self.capacity:
           self.episodes.pop(0)
  
   def _embed(self, state, action, outcome):
       text = f"{state} {action} {outcome}".lower()
       return hash(text) % 10000
  
   def retrieve_similar(self, query_state, k=3):
       if not self.episodes:
           return []
       query_emb = self._embed(query_state, "", "")
       scores = [(abs(ep['embedding'] - query_emb), ep) for ep in self.episodes]
       scores.sort(key=lambda x: x[0])
       return [ep for _, ep in scores[:k]]
  
   def get_recent(self, n=5):
       return self.episodes[-n:]


class SemanticMemory:
   def __init__(self):
       self.preferences = defaultdict(float)
       self.patterns = defaultdict(list)
       self.success_rates = defaultdict(lambda: {'success': 0, 'total': 0})
      
   def update_preference(self, key, value, weight=1.0):
       self.preferences[key] = 0.9 * self.preferences[key] + 0.1 * weight * value
  
   def record_pattern(self, context, action, success):
       pattern_key = f"{context}_{action}"
       self.patterns[context].append((action, success))
       self.success_rates[pattern_key]['total'] += 1
       if success:
           self.success_rates[pattern_key]['success'] += 1
  
   def get_best_action(self, context):
       if context not in self.patterns:
           return None
       action_scores = defaultdict(lambda: {'success': 0, 'total': 0})
       for action, success in self.patterns[context]:
           action_scores[action]['total'] += 1
           if success:
               action_scores[action]['success'] += 1
       best_action = max(action_scores.items(), key=lambda x: x[1]['success'] / max(x[1]['total'], 1))
       return best_action[0] if best_action[1]['total'] > 0 else None
  
   def get_preference(self, key):
       return self.preferences.get(key, 0.0)

We define the underlying memory structures that our agent relies on. We create episodic memory to capture specific experiences and semantic memory to create patterns over time. As we discover these basics, we prepare the agent to learn from interactions in the same way humans do. Look Full codes here.

class MemoryAgent:
   def __init__(self):
       self.episodic_memory = EpisodicMemory(capacity=50)
       self.semantic_memory = SemanticMemory()
       self.current_plan = []
       self.session_count = 0
      
   def perceive(self, user_input):
       user_input = user_input.lower()
       if any(word in user_input for word in ['recommend', 'suggest', 'what should']):
           intent="recommendation"
       elif any(word in user_input for word in ['remember', 'prefer', 'like', 'favorite']):
           intent="preference_update"
       elif any(word in user_input for word in ['do', 'complete', 'finish', 'task']):
           intent="task_execution"
       else:
           intent="conversation"
       return {'intent': intent, 'raw': user_input}
  
   def plan(self, state):
       intent = state['intent']
       user_input = state['raw']
       similar_episodes = self.episodic_memory.retrieve_similar(user_input, k=3)
       plan = []
       if intent == 'recommendation':
           genre_prefs = {k: v for k, v in self.semantic_memory.preferences.items() if 'genre_' in k}
           if genre_prefs:
               best_genre = max(genre_prefs.items(), key=lambda x: x[1])[0]
               plan.append(('recommend', best_genre.replace('genre_', '')))
           else:
               plan.append(('recommend', 'general'))
       elif intent == 'preference_update':
           genres = ['sci-fi', 'fantasy', 'mystery', 'romance', 'thriller']
           detected_genre = next((g for g in genres if g in user_input), None)
           if detected_genre:
               plan.append(('update_preference', detected_genre))
       elif intent == 'task_execution':
           best_action = self.semantic_memory.get_best_action('task')
           if best_action:
               plan.append(('execute', best_action))
           else:
               plan.append(('execute', 'default'))
       self.current_plan = plan
       return plan

We develop agent-based cognitive systems and systems. We process user input, see intent, and build plans by incorporating pre-built memories. We begin to build what the reasons for the egagali and how to determine its next action. Look Full codes here.

 def act(self, action):
       action_type, param = action
       if action_type == 'recommend':
           if param == 'general':
               return f"Let me learn your preferences first! What genres do you enjoy?"
           return f"Based on your preferences, I recommend exploring {param}!"
       elif action_type == 'update_preference':
           self.semantic_memory.update_preference(f'genre_{param}', 1.0, weight=1.0)
           return f"Got it! I'll remember you enjoy {param}."
       elif action_type == 'execute':
           return f"Executing task with strategy: {param}"
       return "Action completed"
  
   def revise_plan(self, feedback):
       if 'no' in feedback.lower() or 'wrong' in feedback.lower():
           if self.current_plan:
               action_type, param = self.current_plan[0]
               if action_type == 'recommend':
                   genre_prefs = sorted(
                       [(k, v) for k, v in self.semantic_memory.preferences.items() if 'genre_' in k],
                       key=lambda x: x[1],
                       reverse=True
                   )
                   if len(genre_prefs) > 1:
                       new_genre = genre_prefs[1][0].replace('genre_', '')
                       self.current_plan = [('recommend', new_genre)]
                       return True
       return False
  
   def reflect(self, state, action, outcome, success):
       self.episodic_memory.store(state['raw'], str(action), outcome)
       self.semantic_memory.record_pattern(state['intent'], str(action), success)

We describe how the agent performs an action, revises its decisions when the response contradicts expectations, and reflects by storing experience. We continuously improve the performance of the agent by allowing us to learn from every change. With this soop, we make the program flexible and self-sustaining. Look Full codes here.

 def run_session(self, user_inputs):
       self.session_count += 1
       print(f"n{'='*60}")
       print(f"SESSION {self.session_count}")
       print(f"{'='*60}n")
       results = []
       for i, user_input in enumerate(user_inputs, 1):
           print(f"Turn {i}")
           print(f"User: {user_input}")
           state = self.perceive(user_input)
           plan = self.plan(state)
           if not plan:
               print("Agent: I'm not sure what to do with that.n")
               continue
           response = self.act(plan[0])
           print(f"Agent: {response}n")
           success="recommend" in plan[0][0] or 'update' in plan[0][0]
           self.reflect(state, plan[0], response, success)
           results.append({
               'turn': i,
               'input': user_input,
               'intent': state['intent'],
               'action': plan[0],
               'response': response
           })
       return results

We simulate real interactions where an agent processes multiple user inputs within a single session. We watch the Check → Program → Law → Cycle that shows more often. As we run through the times, we see how the agent starts stealing custom and is smart. Look Full codes here.

def evaluate_memory_usage(agent):
   print("n" + "="*60)
   print("MEMORY ANALYSIS")
   print("="*60 + "n")
   print(f"Episodic Memory:")
   print(f"  Total episodes stored: {len(agent.episodic_memory.episodes)}")
   if agent.episodic_memory.episodes:
       print(f"  Oldest episode: {agent.episodic_memory.episodes[0]['timestamp']}")
       print(f"  Latest episode: {agent.episodic_memory.episodes[-1]['timestamp']}")
   print(f"nSemantic Memory:")
   print(f"  Learned preferences: {len(agent.semantic_memory.preferences)}")
   for pref, value in sorted(agent.semantic_memory.preferences.items(), key=lambda x: x[1], reverse=True)[:5]:
       print(f"    {pref}: {value:.3f}")
   print(f"n  Action patterns learned: {len(agent.semantic_memory.patterns)}")
   print(f"n  Success rates by context-action:")
   for key, stats in list(agent.semantic_memory.success_rates.items())[:5]:
       if stats['total'] > 0:
           rate = stats['success'] / stats['total']
           print(f"    {key}: {rate:.2%} ({stats['success']}/{stats['total']})")


def compare_sessions(results_history):
   print("n" + "="*60)
   print("CROSS-SESSION ANALYSIS")
   print("="*60 + "n")
   for i, results in enumerate(results_history, 1):
       recommendation_quality = sum(1 for r in results if 'preferences' in r['response'].lower())
       print(f"Session {i}:")
       print(f"  Turns: {len(results)}")
       print(f"  Personalized responses: {recommendation_quality}")

We analyze how the agent uses its memories. We examine saved episodes, learned preferences, and patterns of success to assess how the performer evolves. Look Full codes here.

def run_demo():
   agent = MemoryAgent()
   print("n📚 SCENARIO: Agent learns user preferences over multiple sessions")
   session1_inputs = [
       "Hi, I'm looking for something to read",
       "I really like sci-fi books",
       "Can you recommend something?",
   ]
   results1 = agent.run_session(session1_inputs)
   session2_inputs = [
       "I'm bored, what should I read?",
       "Actually, I also enjoy fantasy novels",
       "Give me a recommendation",
   ]
   results2 = agent.run_session(session2_inputs)
   session3_inputs = [
       "What do you suggest for tonight?",
       "I'm in the mood for mystery too",
       "Recommend something based on what you know about me",
   ]
   results3 = agent.run_session(session3_inputs)
   evaluate_memory_usage(agent)
   compare_sessions([results1, results2, results3])
   print("n" + "="*60)
   print("EPISODIC MEMORY RETRIEVAL TEST")
   print("="*60 + "n")
   query = "recommend sci-fi"
   similar = agent.episodic_memory.retrieve_similar(query, k=3)
   print(f"Query: '{query}'")
   print(f"Retrieved {len(similar)} similar episodes:n")
   for ep in similar:
       print(f"  State: {ep['state']}")
       print(f"  Action: {ep['action']}")
       print(f"  Outcome: {ep['outcome'][:50]}...")
       print()


if __name__ == "__main__":
   print("="*60)
   print("MEMORY & LONG-TERM AUTONOMY IN AGENTIC SYSTEMS")
   print("="*60)
   run_demo()
   print("n✅ Tutorial complete! Key takeaways:")
   print("  • Episodic memory stores specific experiences")
   print("  • Semantic memory generalizes patterns")
   print("  • Agents improve recommendations over sessions")
   print("  • Memory retrieval guides future decisions")

We bring it all together by using multiple sessions and memory testing. We see the agent develop interactions and analytical recommendations based on the information gathered. This perfect scenario shows how the future generation emerges from the memory systems we have given birth to.

In conclusion, we see that the combination of episodic and semantic memory enables us to create agents that learn continuously and make better decisions over time. We see recommendations for the agent's refinement, drug-free programs, and retrieving past experiences to improve their session time after session. Through these processes, we see how much independence comes from simple but effective memory structures.


Look Full codes here. Feel free to take a look at ours GitHub page for tutorials, code and notebooks. Also, feel free to follow us Kind of stubborn and don't forget to join ours 100K + ML Subreddit and sign up Our newsletter. Wait! Do you telegraph? Now you can join us by telegraph.


AsifAzzaq is the CEO of MarktechPost Media Inc.. as a visionary entrepreneur and developer, Asifi is committed to harnessing the power of social intelligence for good. His latest effort is the launch of a media intelligence platform, MarktechPpost, which stands out for its deep understanding of machine learning and deep learning stories that are technically sound and easily understood by a wide audience. The platform sticks to more than two million monthly views, which shows its popularity among the audience.

Follow Marktechpost: Add us as a favorite source on Google.

Source link

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button