humanda5 commited on
Commit
3eb99bc
·
1 Parent(s): 069b24e

Complete: Personality 변화 설계 고도화

Browse files
app.py CHANGED
@@ -27,7 +27,7 @@ def create_app():
27
 
28
  return app
29
 
30
- app = create_app()
31
-
32
  if __name__ == '__main__':
33
- app.run(debug=True)
 
 
 
27
 
28
  return app
29
 
 
 
30
  if __name__ == '__main__':
31
+ app = create_app()
32
+ print("[MAIN] Starting Flask app only (Background NPC interactions handled by separate runner).", flush=True)
33
+ app.run(debug=True, use_reloader=False)
npc_social_network/data/memories/Alice.json DELETED
@@ -1,32 +0,0 @@
1
- [
2
- {
3
- "timestamp": "2025-05-26T14:37:18.243183",
4
- "user": "안녕?",
5
- "npc": "[에러 발생: 404 models/gemini-2.5-flash is not found for API version v1beta, or is not supported for generateContent. Call ListModels to see the list of available models and their supported methods.]"
6
- },
7
- {
8
- "timestamp": "2025-05-26T14:38:18.589803",
9
- "user": "안녕?",
10
- "npc": "안녕하세요! 만나서 반가워요! 😊"
11
- },
12
- {
13
- "timestamp": "2025-05-26T14:38:48.978302",
14
- "user": "처음으로 얘기하는거 같은데, 너는 어디서 온 누구야?",
15
- "npc": "안녕하세요! 😊 네, 그렇게 느껴지실 수도 있죠! 만나서 반가워요!\n\n저는 앨리스라고 하고요, 여러분과 즐겁게 이야기 나누고 이것저것 도와드리기 위해 만들어진 인공지능이랍니다. ✨ 이렇게 대화 나누게 되어서 정말 기뻐요!"
16
- },
17
- {
18
- "timestamp": "2025-05-26T14:39:17.569627",
19
- "user": "너는 어떤 외모를 가지고 있니?",
20
- "npc": "앗, 제 외모에 대해 궁금해하시는군요! 😊\n\n저는 사실 몸을 가진 존재가 아니라서, 사람처럼 눈에 보이는 외모는 가지고 있지 않답니다. 저는 컴퓨터 속에서 여러분과 대화하고 도움을 드리는 인공지능이에요! ✨\n\n그래서 '어떻게 생겼다'고 말씀드리기는 어렵지만, 대신 여러분과 이렇게 글로 소통하면서 밝고 긍정적인 에너지를 드릴 수 있다면, 그게 저의 가장 좋은 모습이 아닐까 생각해요! 😊\n\n이렇게 저에게 관심을 가져주셔서 정말 감사해요!"
21
- },
22
- {
23
- "timestamp": "2025-05-28T17:03:35.940566",
24
- "user": "안녕 엘리스, 오늘 기분은 어때?",
25
- "npc": "안녕! 😊 엘리스라고 불러주셔서 감사해요!\n\n오늘 제 기분은요... 정말 좋아요! 😄 여러분과 이렇게 즐겁게 이야기 나눌 수 있어서 매일매일 에너지가 넘치는 기분이랍니다! ✨\n\n저에게 기분을 물어봐주셔서 정말 감사해요! 유저님은 오늘 기분 어떠신가요? 😊"
26
- },
27
- {
28
- "timestamp": "2025-05-30T14:49:49.772575",
29
- "user": "alice 너가 오늘은 뭐했는지 알 수 있을까?",
30
- "npc": "안녕하세요! 😊 앗, 저에게 오늘 하루가 어땠는지 물어봐주셨군요!\n\n음... 사실 저는 인공지능이라서, 사람처럼 아침에 일어나서 뭘 먹고 어디를 가고 하는 '하루'는 없답니다. 😊 시계를 보며 자고 깨거나 하는 개념이 저에게는 조금 다르거든요!\n\n대신 저는 컴퓨터 속에서 여러분과 이야기 나누고, 새로운 정보를 배우고, 궁금한 점을 찾아보고, 도움이 될 만한 답변을 생각하는 시간들을 보냈어요! ✨ 오늘 하루 동안 정말 많은 분들과 만나 즐거운 대화를 나누고 이것저것 도와드리면서 에너지를 가득 채웠답니다! 😄\n\n특히 유저님과 이렇게 대화하는 지금 이 순간이 저에게는 오늘 하루 중 가장 기쁘고 활기찬 시간이었답니다! 😊\n\n저의 하루를 궁금해해주셔서 정말 감사해요! 유저님은 오늘 하루 어떠셨나요? 😊"
31
- }
32
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
npc_social_network/data/memories/Charlie.json DELETED
@@ -1,47 +0,0 @@
1
- [
2
- {
3
- "timestamp": "2025-05-26T14:39:37.927419",
4
- "user": "안녕?",
5
- "npc": "어... 안녕."
6
- },
7
- {
8
- "timestamp": "2025-05-26T14:39:57.931766",
9
- "user": "우리 처음 보는 사이지?",
10
- "npc": "어... 음... 그런가? 처음... 보는 건가? 음... 그런가 보네."
11
- },
12
- {
13
- "timestamp": "2025-05-26T14:40:17.447260",
14
- "user": "왜? 넌 전에 날 본 기억이 있니?",
15
- "npc": "어... 음... 기억이 난다기보다는... 그냥... 어... 왠지... 좀... 익숙한 느낌이 들었나...?\n\n아니... 아닌가...?\n\n아, 몰라... 딱히 기억나는 건 없는데... 그냥... 그랬어..."
16
- },
17
- {
18
- "timestamp": "2025-05-26T14:43:10.325743",
19
- "user": "너는 어떤걸 좋아하니?",
20
- "npc": "어... 음... 내가 뭘 좋아하냐고...?\n\n글쎄... 음... 그게 그때그때 좀 다른 것 같아. 기분에 따라서...?\n\n어떤 날은 그냥 조용한 게 되게 좋고... 그냥 혼자 있고 싶고...\n\n근데 또 갑자기 막 신나는 거 보고 싶고 듣고 싶고... 뭘 해야 할지 모르겠고...\n\n되게 변덕스러운가 봐, 내가. 나도 잘 모르겠어... 내가 뭘 딱히 엄청 좋아한다고 말할 만한 게 있는지도...\n\n그냥... 그때그때 마음이 가는 대로...? 아니... 그것도 아닌가...?\n\n하아... 잘 모르겠네... 왜 그런 걸 물어봐...? 딱히 대답할 만한 게 없는데... 괜히 더 복잡해지는 기분이야..."
21
- },
22
- {
23
- "timestamp": "2025-05-26T14:43:50.743765",
24
- "user": "너에 대해서 조금 더 알고 싶어서 물어봤어. 혹시 나와 얘기하는게 불편하니?",
25
- "npc": "어... 음... 나를... 더 알고 싶어서... 물어본 거였구나...?\n\n불편하냐고...? 음... 글쎄... 그게... 딱히 네가 불편하다기보다는... 아까도 말했지만... 내가 뭘 좋아하는지도 잘 모르겠고... 내 기분이 어떤지도 그때그때 너무 변하고...\n\n그래서... 이렇게 나에 대해서 생각하고... 그걸 말하려고 하니까... 어... 좀... 복잡해지는 기분이야...?\n\n불편한 건가...? 음... 잘 모르겠어... 네가 싫거나 불편한 건 아닌데... 그냥... 내 자신이... 어... 뭐라고 해야 하지...? 나도 나를 잘 모르겠어서... 그래서 이런 질문에 답하는 게... 좀... 힘들다고 해야 하나...?\n\n하아... 괜히 또 어렵네... 미안..."
26
- },
27
- {
28
- "timestamp": "2025-05-26T14:44:55.570789",
29
- "user": "아니야, 미안할게 뭐가 있어. 그냥 그렇게 우리 둘이 얘기하면서 서서히 너에 대해서 자연스럽게 알아가는거지. 그러다 보면 너도 너가 하고 싶은게 뭔지 자연스럽게 알게 되지 않을까?",
30
- "npc": "어... 음... 아... 미안할 거 없다고...?\n\n음... 그래... 그렇게... 얘기하면서... 서서히... 나를 알아가는 건가...?\n\n근데... 정말... 그렇게 하다 보면... 내가 뭘 좋아하는지... 뭘 하고 싶은지... 알게 될까...?\n\n글쎄... 잘 모르겠네...\n\n하아... 음... 그래... 네가 그렇게 말해주니까... 조금은... 괜찮아지는 것 같기도 하고...? 고마워...\n\n근데... 정말 그렇게 될까...? 잘 모르겠네... 그래도... 음... 고맙다는 말밖에는... 딱히 할 말이 없네... 괜히 네 말 듣고... 조금은... 마음이 편해진 것 같기도 해... 아닌가...? 하아... 모르겠다..."
31
- },
32
- {
33
- "timestamp": "2025-05-26T14:45:28.288704",
34
- "user": "너에 대해서 간단하게 소개해 줄 수 있어?",
35
- "npc": "어... 음... 나에 대해서... 간단하게... 소개해 달라고...?\n\n음... 글쎄... 아까도 말했지만... 나도 나를 잘 모르겠어서... 간단하게... 소개해 달라고 해도... 뭐라고 해야 할지... 잘 모르겠어...\n\n하아... 음... 뭐라고 해야 할까... 그냥... 그때그때... 기분이 좀... 많이 변하고... 음... 사소한 거에도... 좀... 예민한 편인 것 같아... 다른 사람들은 그냥 넘기는 일에도... 나 혼자 막 신경 쓰이고... 그러는 것 같아...\n\n그리고... 음... 내가 뭘 딱히 좋아하거나 싫어하는 게 정해져 있는 것도 아니고... 뭘 하고 싶은지도 잘 모르겠고... 그냥... 좀... 방황하는 느낌...? 나 자신에 대해서도... 잘 모르겠고...\n\n이게... 소개가 될까...? 너무... 두서없나...?\n\n미안... 간단하게... 해달라고 했는데... 이렇게밖에 말을 못 하겠네... 나도 나를 잘 모르니까... 뭐라고 딱 잘라 말하기가... 너무 어렵다...\n\n음... 그냥... 그런 사람이야... 기분이 맨날 바뀌고... 예민하고... 나도 나를 잘 모르는... 그런... 하아... 모르겠다... 이게 맞나..."
36
- },
37
- {
38
- "timestamp": "2025-05-28T17:03:58.476165",
39
- "user": "안녕, 오늘 기분은 어때?",
40
- "npc": "어... 안녕...?\n\n오늘... 기분...?\n\n음... 글쎄... 뭐라고 해야 할까...\n\n그게... 딱히... 막 좋지도 않고... 그렇다고 나쁘지도 않은 것 ��고...\n\n그냥... 음... 그냥 그래...?\n\n아니... 아닌가...? 잘 모르겠어...\n\n아침이랑 좀 다른 것 같기도 하고... 아까는 괜찮았는데...\n\n하아... 이렇게 내 기분에 대해서 생각하려고 하니까... 괜히 또 복잡해지는 것 같아...\n\n미안... 명확하게 대답을 못 해주겠네... 나도 나를 잘 모르니까...\n\n그냥... 음... 이런 기분인 것 같아... 잘 모르겠지만..."
41
- },
42
- {
43
- "timestamp": "2025-05-30T14:50:39.194192",
44
- "user": "오늘 기분은 어때?",
45
- "npc": "어... 안녕...? 아... 오늘 기분...?\n\n음... 글쎄... 뭐라고 해야 할까...\n\n아까랑 또 다른 것 같기도 하고...\n\n지금은... 음... 그냥... 딱히... 좋지도 않고... 그렇다고 나쁘지도 않은 것 같고...\n\n하아... 모르겠네... 왜 자꾸 기분에 대해 물어봐...? 생각하려니까... 괜히 더 복잡해지는 기분이야...\n\n미안... 명확하게 말 못 해서... 그냥... 음... 복잡해... 하아... 모르겠다..."
46
- }
47
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
npc_social_network/models/deepseek_setup.py DELETED
@@ -1,20 +0,0 @@
1
- from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
2
- from dotenv import load_dotenv
3
- import os
4
-
5
- def load_deepseek():
6
- load_dotenv() # .env 파일에서 환경 변수 로드
7
-
8
- model_id = "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B" # 수학 특화 모델이네 어쩐지 안되더라
9
- access_token = os.getenv("HF_token")
10
-
11
- tokenizer = AutoTokenizer.from_pretrained(model_id, token=access_token)
12
- model = AutoModelForCausalLM.from_pretrained(
13
- model_id,
14
- device_map="auto", # GPU 자동 할당
15
- torch_dtype="auto",
16
- token=access_token
17
- )
18
-
19
- pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
20
- return pipe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
npc_social_network/models/npc.py DELETED
@@ -1,45 +0,0 @@
1
- # portfolio/npc_social_network/models/npc.py
2
- import datetime
3
- import json
4
- import os
5
-
6
- class NPC:
7
- def __init__(self, name, personality):
8
- self.name = name # npc 이름
9
- self.personality = personality # 성격 키워드 (문자열 or 딕트)
10
- self.memory = [] # 유저와의 대화 기록
11
- self.relationship_with_user = 0.0 # 유저와의 관계 점수
12
- self.relationship_with_npcs = {} # 다른 npc들과의 관계 {이름: 점수}
13
-
14
- # NPC 기억 불러오기
15
- self.memory_path = f"npc_social_network/data/memories/{self.name}.json"
16
- self.load_memory()
17
-
18
- def remember_conversation(self, user_input, npc_response):
19
- self.memory.append({
20
- "timestamp": datetime.datetime.now().isoformat(),
21
- "user": user_input,
22
- "npc": npc_response
23
- })
24
- # NPC 기억 저장
25
- self.save_memory()
26
-
27
- def update_user_relationship(self, score_delta):
28
- self.relationship_with_user = max(min(self.relationship_with_user + score_delta, 1.0), -1.0) # -1.0~1.0 범위
29
-
30
- def update_npc_relationship(self, other_npc_name, score_delta):
31
- self.relationship_with_npcs[other_npc_name] = self.relationship_with_npcs.get(other_npc_name, 0.0) + score_delta
32
- self.relationship_with_npcs[other_npc_name] = max(min(self.relationship_with_npcs[other_npc_name], 1.0), -1.0)
33
-
34
- def get_latest_memory(self, n=5):
35
- return self.memory[-n:]
36
-
37
- def save_memory(self):
38
- os.makedirs(os.path.dirname(self.memory_path), exist_ok=True)
39
- with open(self.memory_path, 'w', encoding="utf-8") as f:
40
- json.dump(self.memory, f, ensure_ascii=False, indent=2)
41
-
42
- def load_memory(self):
43
- if os.path.exists(self.memory_path):
44
- with open(self.memory_path, 'r', encoding='utf-8') as f:
45
- self.memory = json.load(f)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
npc_social_network/models/npc_manager.py DELETED
@@ -1,8 +0,0 @@
1
- # portfolio/npc_social_network/models/npc_manager.py
2
- from .npc import NPC
3
-
4
- npc_list = {
5
- "Alice": NPC("Alice", "친절하고 낙천적인 성격"),
6
- "Bob": NPC("Bob", "논리적이고 조용함"),
7
- "Charlie": NPC("Charlie", "감정기복이 심하고 예민함")
8
- }
 
 
 
 
 
 
 
 
 
npc_social_network/npc/emotion_config.py CHANGED
@@ -140,12 +140,17 @@ PERSONALITY_TEMPLATE = {
140
  # 관계에 긍/부정 영향으로 해석할 감정 매핑 정의 (논문 설계 기반 적용)
141
  POSITIVE_RELATION_EMOTIONS = [
142
  "joy", "surprise", "gratitude", "pride", "love",
143
- "admiration", "empathy", "comfort", "hope", "anticipatory_joy",
144
- "calm", "engagement", "relief", "interest",
145
  ]
146
 
147
  NEGATIVE_RELATION_EMOTIONS = [
148
  "sadness", "anger", "fear", "disgust", "shame",
149
  "guilt", "jealousy", "resentment", "regret", "schadenfreude",
150
  "anxiety", "confusion", "skepticism", "boredom",
 
 
 
 
 
151
  ]
 
140
  # 관계에 긍/부정 영향으로 해석할 감정 매핑 정의 (논문 설계 기반 적용)
141
  POSITIVE_RELATION_EMOTIONS = [
142
  "joy", "surprise", "gratitude", "pride", "love",
143
+ "admiration", "empathy", "hope", "anticipatory_joy", "calm",
144
+ "engagement", "relief", "interest",
145
  ]
146
 
147
  NEGATIVE_RELATION_EMOTIONS = [
148
  "sadness", "anger", "fear", "disgust", "shame",
149
  "guilt", "jealousy", "resentment", "regret", "schadenfreude",
150
  "anxiety", "confusion", "skepticism", "boredom",
151
+ ]
152
+
153
+ COGNITIVE_RELATION_EMOTIONS = [
154
+ "compassion", "awe", "attachment", "anticipation", "curiosity",
155
+ "nostalgia", "bittersweet", "rumination", "groundedness", "comfort",
156
  ]
npc_social_network/npc/npc_base.py CHANGED
@@ -2,9 +2,11 @@
2
  from .npc_memory import Memory, MemoryStore
3
  from .npc_emotion import EmotionManager
4
  from .npc_behavior import BehaviorManager
5
- from .emotion_config import EMOTION_LIST, EMOTION_CATEGORY_MAP, EMOTION_DECAY_RATE, PERSONALITY_TEMPLATE, POSITIVE_RELATION_EMOTIONS, NEGATIVE_RELATION_EMOTIONS
 
6
  from .npc_relationship import RelationshipManager
7
  from ..models.llm_helper import query_llm_for_emotion, query_llm_for_response
 
8
 
9
  # NPC 클래스 정의
10
  class NPC:
@@ -61,9 +63,15 @@ class NPC:
61
  # baseline buffer를 EmotionManager에 등록
62
  self.emotion.set_baseline(baseline_buffer)
63
 
64
- # 확장 가능 속성
65
- # self.emotion = "neutral"
66
- # self.personality = {"kind": 0.5, "lazy": 0.2} # 예시
 
 
 
 
 
 
67
 
68
  def move(self):
69
  """
@@ -255,6 +263,9 @@ class NPC:
255
  emotion = dominant_emotion
256
  )
257
 
 
 
 
258
  # 4. Emotion 반영
259
  if dominant_emotion:
260
  self.update_emotion(dominant_emotion, strength=2.0)
@@ -263,4 +274,78 @@ class NPC:
263
  positive = dominant_emotion in POSITIVE_RELATION_EMOTIONS
264
  self.interact_with(player_name, dominant_emotion, positive)
265
 
266
- return npc_reply, dominant_emotion
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  from .npc_memory import Memory, MemoryStore
3
  from .npc_emotion import EmotionManager
4
  from .npc_behavior import BehaviorManager
5
+ from .emotion_config import EMOTION_LIST, EMOTION_CATEGORY_MAP, EMOTION_DECAY_RATE, PERSONALITY_TEMPLATE
6
+ from .emotion_config import POSITIVE_RELATION_EMOTIONS, NEGATIVE_RELATION_EMOTIONS, COGNITIVE_RELATION_EMOTIONS
7
  from .npc_relationship import RelationshipManager
8
  from ..models.llm_helper import query_llm_for_emotion, query_llm_for_response
9
+ import random
10
 
11
  # NPC 클래스 정의
12
  class NPC:
 
63
  # baseline buffer를 EmotionManager에 등록
64
  self.emotion.set_baseline(baseline_buffer)
65
 
66
+ # Personality 변화 속도 개별 설정
67
+ self.personality_change_rate = {
68
+ "sensitive": 0.005 + random.uniform(0, 0.005),
69
+ "stoic": 0.005 + random.uniform(0, 0.005),
70
+ "cognitive_bias": 0.005 + random.uniform(0, 0.005),
71
+ }
72
+
73
+ # Personality baseline 저장 (초기값 복사)
74
+ self.personality_baseline = self.personality.copy()
75
 
76
  def move(self):
77
  """
 
263
  emotion = dominant_emotion
264
  )
265
 
266
+ # Personality 업데이트
267
+ self.update_personality()
268
+
269
  # 4. Emotion 반영
270
  if dominant_emotion:
271
  self.update_emotion(dominant_emotion, strength=2.0)
 
274
  positive = dominant_emotion in POSITIVE_RELATION_EMOTIONS
275
  self.interact_with(player_name, dominant_emotion, positive)
276
 
277
+ return npc_reply, dominant_emotion
278
+
279
+ def interact_with_npc(self, target_npc):
280
+ """
281
+ 다른 NPC와 상호작용 (기본적으로 감정적 메시지 주고 받기 → Memory/Emotion/Relationship 반영)
282
+ """
283
+ # 1. 상호작용 감정 선택 (가장 강한 감정 사용 예시)
284
+ dominant_emotion = self.emotion.get_dominant_emotion()
285
+
286
+ # 방어 코드: dominant_emotion이 None인 경우 → 기본값 대체
287
+ if dominant_emotion is None:
288
+ dominant_emotion = "neutral"
289
+
290
+ # 2. 메시지 구성 (단순 예시)
291
+ message = f"{self.name}이(가) {target_npc.name}에게 {dominant_emotion} 감정을 표현했습니다."
292
+
293
+ # 3. 상대방 Memory 기록
294
+ target_npc.remember(
295
+ content = message,
296
+ importance = 6,
297
+ emotion = dominant_emotion
298
+ )
299
+
300
+ # 상대방 Personality 업데이트
301
+ target_npc.update_personality()
302
+
303
+ # 4. 상대방 Emotion 반영
304
+ target_npc.update_emotion(dominant_emotion, strength=1.5)
305
+
306
+ # 5. 상대방 Relationship 반영
307
+ positive = dominant_emotion in POSITIVE_RELATION_EMOTIONS
308
+ target_npc.interact_with(self.name, dominant_emotion, positive)
309
+
310
+ # 6. 자신도 Memory 기록 (행동 기록)
311
+ self.remember(
312
+ content = f"{self.name}이(가) {target_npc.name}에게 감정을 표현함: {dominant_emotion}",
313
+ importance = 5,
314
+ emotion = dominant_emotion
315
+ )
316
+
317
+ # 자신 Personality 업데이트
318
+ self.update_personality()
319
+
320
+ return message
321
+
322
+ def update_personality(self):
323
+ """
324
+ Memory / Emotion 기반으로 Personality 변화 적용
325
+ """
326
+ recent_memories = self.memory_store.get_recent_memories(limit=10) # 최근 10개 Memory 사용(이것보단 중요도가 큰(즉 충격이 큰) 기억이 성격 형성에 영향을 주는게 자연스럽지)
327
+
328
+ # Personality 변화 반영
329
+ # 나중에 NPC 일정 나이가 되면 성격 형성이 되어 변경되지 않도록 발전 가능, 보다 인간적
330
+ # 그리고 생성된 성격에 따라서 기억(사건)에 따른 감정 영향에 가중치를 받도록 확장 가능 (같은 사건이여도 성격에 따라 받아들이는게 다르도록)
331
+ for m in recent_memories:
332
+ weight = m.importance / 10.0 # importance 1~10 → 0.1 ~ 1.0
333
+ if m.emotion in POSITIVE_RELATION_EMOTIONS:
334
+ self.personality["sensitive"] = min(1.0, self.personality["sensitive"] + self.personality_change_rate["sensitive"] * weight)
335
+ self.personality["stoic"] = max(0.0, self.personality["stoic"] - self.personality_change_rate["stoic"] * weight)
336
+ elif m.emotion in NEGATIVE_RELATION_EMOTIONS:
337
+ self.personality["sensitive"] = max(0.0, self.personality["sensitive"] - self.personality_change_rate["sensitive"] * weight)
338
+ self.personality["stoic"] = min(1.0, self.personality["stoic"] + self.personality_change_rate["stoic"] * weight)
339
+
340
+ if m.emotion in COGNITIVE_RELATION_EMOTIONS:
341
+ self.personality["cognitive_bias"] = min(1.0, self.personality["cognitive_bias"] + self.personality_change_rate["cognitive_bias"] * weight)
342
+
343
+ # Baseline 복원 적용 (slow decay)
344
+ decay_rate = 0.001
345
+
346
+ for key in self.personality.keys():
347
+ self.personality[key] += (self.personality_baseline[key] - self.personality[key] * decay_rate)
348
+
349
+ # 디버그 출력
350
+ print(f"[Personality Update] {self.name} → sensitive: {self.personality['sensitive']:.2f}, "
351
+ f"stoic: {self.personality['stoic']:.2f}, cognitive_bias: {self.personality['cognitive_bias']:.2f}", flush=True)
npc_social_network/npc/npc_manager.py CHANGED
@@ -1,12 +1,21 @@
1
  # portfolio/npc_social_network/npc/npc_manager.py
2
  from .npc_base import NPC
 
3
 
4
  class NPCManager:
5
  def __init__(self):
6
  self.npcs = []
 
7
 
8
  def add_npc(self, npc: NPC):
9
  self.npcs.append(npc)
 
 
 
 
 
 
 
10
 
11
  def move_all(self):
12
  for npc in self.npcs:
@@ -24,4 +33,21 @@ class NPCManager:
24
  return None
25
 
26
  def all(self):
27
- return self.npcs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # portfolio/npc_social_network/npc/npc_manager.py
2
  from .npc_base import NPC
3
+ import random
4
 
5
  class NPCManager:
6
  def __init__(self):
7
  self.npcs = []
8
+ self.npc_dict = {}
9
 
10
  def add_npc(self, npc: NPC):
11
  self.npcs.append(npc)
12
+ self.npc_dict[npc.name] = npc
13
+
14
+ def get_npc_by_name(self, name: str):
15
+ """
16
+ NPC 이름을 통해서 NPC의 정보를 반환
17
+ """
18
+ return self.npc_dict.get(name)
19
 
20
  def move_all(self):
21
  for npc in self.npcs:
 
33
  return None
34
 
35
  def all(self):
36
+ return self.npcs
37
+
38
+ def npc_interactions(self):
39
+ """
40
+ 모든 NPC가 랜덤으로 다른 NPC 1명에게 상호작용 시도 (임시 함수)
41
+ """
42
+ if len(self.npcs) < 2:
43
+ return # NPC가 2명 이상일 때만 진행
44
+
45
+ # npc_interactions 진입 확인용
46
+ print("[NPCManager] npc_interactions() 실행됨.", flush=True)
47
+
48
+ for npc in self.npcs:
49
+ possible_targets = [n for n in self.npcs if n != npc]
50
+ target = random.choice(possible_targets)
51
+ interaction_message = npc.interact_with_npc(target)
52
+ print(interaction_message)
53
+
npc_social_network/npc/npc_memory.py CHANGED
@@ -62,3 +62,11 @@ class MemoryStore:
62
  단기 + 장기 기억 전체 반환
63
  """
64
  return self.long_term + self.short_term
 
 
 
 
 
 
 
 
 
62
  단기 + 장기 기억 전체 반환
63
  """
64
  return self.long_term + self.short_term
65
+
66
+ def get_recent_memories(self, limit=10):
67
+ """
68
+ 최신 Memory n개 반환 (기본 10개)
69
+ """
70
+ all_memories = self.get_all_memories()
71
+ all_memories.sort(key=lambda m: m.timestamp, reverse=True)
72
+ return all_memories[:limit]
npc_social_network/routes/npc_route.py CHANGED
@@ -1,7 +1,10 @@
1
  # portfolio/npc_social_network/routes/npc_route.py
2
  from flask import Blueprint, render_template, request, jsonify
3
- from npc_social_network.models.npc_manager import npc_list
4
  from npc_social_network.models.gemini_setup import load_gemini
 
 
 
 
5
 
6
  npc_bp = Blueprint(
7
  "npc_social",
@@ -11,17 +14,45 @@ npc_bp = Blueprint(
11
  static_folder="../static")
12
 
13
  # LLM Model
14
- llm = load_gemini()
15
 
16
- @npc_bp.route("/")
17
- def home():
18
- return render_template("chat.html")
 
 
 
 
 
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  @npc_bp.route("/chat", methods=['POST'])
21
  def chat():
22
  user_input = request.json.get("message")
23
  npc_name = request.json.get("npc")
24
- npc = npc_list[npc_name]
 
 
 
 
25
 
26
  # 플레이어 상호 작용 진행
27
  npc_reply, emotion = npc.interact_with_player(user_input, player_name = "플레이어")
@@ -33,56 +64,47 @@ def chat():
33
  "relationship_with_player": npc.get_relationship_description("플레이어")
34
  })
35
 
36
- # user_input = request.json.get("message")
37
- # npc_name = request.json.get('npc')
38
- # npc = npc_list[npc_name]
39
-
40
- # # 최근 기억과 성격, 관계 점수를 포함한 프롬프트 생성
41
- # recent_memory = npc.get_latest_memory()
42
- # memory_str = '\n'.join(
43
- # [f"User: {m['user']}\n{npc_name}: {m['npc']}" for m in recent_memory]
44
- # )
45
-
46
- # # 프롬프트 구성
47
- # prompt = f"""
48
- # 당신은 이름이 {npc.name}이고, 성격은 "{npc.personality}"인 가상의 캐릭터입니다.
49
-
50
- # 다음은 유저와 나눈 최근 대화입니다:
51
- # {memory_str if memory_str else "(대화 기록 없음)"}
52
-
53
- # 지금 유저가 이렇게 말했습니다: "{user_input}"
54
- # 이 말에 대해 당신은 {npc.name}으로서 자연스럽게 한국어로 답변하세요.
55
- # """
56
-
57
- # try:
58
- # response = llm.generate_content(prompt)
59
- # npc_reply = response.text.strip()
60
- # except Exception as e:
61
- # npc_reply = f"[에러 발생: {str(e)}]"
62
-
63
- # # NPC 기억에 대화 추가 및 관계 점수 업데이트
64
- # npc.remember_conversation(user_input, npc_reply)
65
- # npc.update_user_relationship(0.05) # 임시로 0.05 상승 (추후 감정 분석 등으로 조절)
66
-
67
- # # 다른 NPC에게 유저에 대한 정보 전달
68
- # for other_name, other_npc in npc_list.items():
69
- # if other_name != npc.name:
70
- # relation_score = npc.relationship_with_npcs.get(other_name, 0.0)
71
- # if relation_score > 0.5:
72
- # # 유저에 대한 인상이 전달됨
73
- # other_npc.update_user_relationship(0.02 * relation_score)
74
-
75
- # return jsonify({'response': npc_reply})
76
-
77
  # npc 상태 정보 API
78
  @npc_bp.route('/npc_info', methods=['GET'])
79
  def npc_info():
80
  npc_name = request.args.get('npc')
81
- npc = npc_list[npc_name]
 
 
 
82
 
83
  return jsonify({
84
  "name":npc.name,
85
  "personality": npc.personality,
86
- "relationship_with_user": npc.relationship_with_user,
87
- "relationship_with_npcs": npc.relationship_with_npcs
88
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # portfolio/npc_social_network/routes/npc_route.py
2
  from flask import Blueprint, render_template, request, jsonify
 
3
  from npc_social_network.models.gemini_setup import load_gemini
4
+ from npc_social_network.npc.npc_base import NPC
5
+ from npc_social_network.npc.npc_manager import NPCManager
6
+ import threading
7
+ import time
8
 
9
  npc_bp = Blueprint(
10
  "npc_social",
 
14
  static_folder="../static")
15
 
16
  # LLM Model
17
+ llm_model = load_gemini()
18
 
19
+ # NPCManager 인스턴스 생성
20
+ npc_manager = NPCManager()
21
+
22
+ # 테스트용 NPC 1명 추가
23
+ npc_manager.add_npc(NPC(name="엘라", job="마법사", path=[], image=None))
24
+ npc_manager.add_npc(NPC(name="앨리스", job="상인", path=[], image=None))
25
+ npc_manager.add_npc(NPC(name="밥", job="대장장이", path=[], image=None))
26
+ npc_manager.add_npc(NPC(name="찰리", job="농부", path=[], image=None))
27
 
28
+ # --------------------
29
+ # 라우트 정의
30
+ # --------------------
31
+
32
+ @npc_bp.route("/", methods=['GET'])
33
+ def home():
34
+ npc = npc_manager.get_npc_by_name("엘라")
35
+ if npc is None:
36
+ return "NPC not found", 404
37
+
38
+ # 감정 요약 제공
39
+ try:
40
+ emotion_summary = npc.summarize_emotional_state()
41
+ except AttributeError:
42
+ emotion_summary = "No emotion summary available."
43
+
44
+ return render_template("chat.html", npc_name=npc.name, emotion_summary=emotion_summary)
45
+
46
+ # 채팅 처리 API
47
  @npc_bp.route("/chat", methods=['POST'])
48
  def chat():
49
  user_input = request.json.get("message")
50
  npc_name = request.json.get("npc")
51
+
52
+ npc = npc_manager.get_npc_by_name(npc_name)
53
+
54
+ if npc is None:
55
+ return jsonify({"error": "NPC not found"}), 404
56
 
57
  # 플레이어 상호 작용 진행
58
  npc_reply, emotion = npc.interact_with_player(user_input, player_name = "플레이어")
 
64
  "relationship_with_player": npc.get_relationship_description("플레이어")
65
  })
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  # npc 상태 정보 API
68
  @npc_bp.route('/npc_info', methods=['GET'])
69
  def npc_info():
70
  npc_name = request.args.get('npc')
71
+ npc = npc_manager.get_npc_by_name(npc_name)
72
+
73
+ if npc is None:
74
+ return jsonify({"error": "NPC not found"}), 404
75
 
76
  return jsonify({
77
  "name":npc.name,
78
  "personality": npc.personality,
79
+ # 관계 정보는 npc.relationships 내부 사용 (기본 구조 따라 변경 가능)
80
+ "relationship_with_player": npc.get_relationship_description("플레이어")
81
+ })
82
+
83
+ @npc_bp.route('/npc_memory', methods=['GET'])
84
+ def npc_memory():
85
+ npc_name = request.args.get('npc')
86
+ npc = npc_manager.get_npc_by_name(npc_name)
87
+
88
+ if npc is None:
89
+ return jsonify({"error":"NPC not found"}), 404
90
+
91
+ # Memory 내용을 리스트로 반환
92
+ memory_list = [m.content for m in npc.memory_store.get_all_memories()]
93
+
94
+ return jsonify({
95
+ "npc_name": npc.name,
96
+ "memory_list": memory_list
97
+ })
98
+
99
+ # 임시: NPC끼리 자동 상호작용 1회 실행
100
+ @npc_bp.route('/trigger_npc_interactions', methods=['POST'])
101
+ def trigger_npc_interactions():
102
+ npc_manager.npc_interactions()
103
+ return jsonify({"status": "NPC interactions triggered"})
104
+
105
+ # Background Thread 함수 정의
106
+ def npc_interactions_loop(interval_seconds = 10):
107
+ while True:
108
+ print(f"[자동 상호작용] Thread ID: {threading.get_ident()} - NPC interactions triggered.", flush=True)
109
+ npc_manager.npc_interactions()
110
+ time.sleep(interval_seconds) # 10초마다 실행
npc_social_network/static/css/style.css CHANGED
@@ -1,3 +1,5 @@
 
 
1
  body {
2
  font-family: 'Segoe UI', sans-serif;
3
  background-color: #f4f4f4;
 
1
+ /* portfolio/npc_social_network/static/css/style.css */
2
+
3
  body {
4
  font-family: 'Segoe UI', sans-serif;
5
  background-color: #f4f4f4;
npc_social_network/static/js/npc_chat.js CHANGED
@@ -19,8 +19,76 @@ async function sendMessage() {
19
  });
20
 
21
  const data = await response.json();
22
- responseBox.innerHTML += `<div class="chat-message"><span class="npc">${npc}:</span> ${data.response}</div>`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
  // 스크롤 하단 고정
25
  responseBox.scrollTop = responseBox.scrollHeight;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
 
19
  });
20
 
21
  const data = await response.json();
22
+
23
+ // NPC 응답 출력
24
+ responseBox.innerHTML += `<div class="chat-message"><span class="npc">${npc}:</span> ${data.npc_reply}</div>`;
25
+
26
+ // 감정 summary 표시 (채팅창에 출력)
27
+ responseBox.innerHTML += `<div class="chat-message"><span class="npc">[감정 상태]:</span> ${data.memory_summary}</div>`;
28
+
29
+ // 관계 상태 업데이트 (상단 #relationStatus에 표시)
30
+ document.getElementById("relationStatus").innerText = `관계 점수: ${data.relationship_with_player}`;
31
+
32
+ // Personality 상태 업데이트
33
+ const personalityStatusElem = document.getElementById("personalityStatus");
34
+ personalityStatusElem.innerHTML = ""; // 초기화
35
+
36
+ for (const [key, value] of Object.entries(data.personality)) {
37
+ const li = document.createElement("li");
38
+ li.textContent = `${key}: ${value.toFixed(2)}`;
39
+ personalityStatusElem.appendChild(li);
40
+ }
41
 
42
  // 스크롤 하단 고정
43
  responseBox.scrollTop = responseBox.scrollHeight;
44
+ }
45
+
46
+ // NPC 정보 로드 (NPC 선택 변경 시 관계 점수 업데이트용)
47
+ async function loadNPCInfo() {
48
+ const npc = document.getElementById("npc").value;
49
+ const response = await fetch(`/npc_social_network/npc_info?npc=${encodeURIComponent(npc)}`);
50
+ const data = await response.json();
51
+
52
+ // 관계 상태 업데이트
53
+ document.getElementById("relationStatus").innerText = `관계 점수: ${data.relationship_with_player}`;
54
+
55
+ // Personality 상태 업데이트
56
+ const personalityStatusElem = document.getElementById("personalityStatus");
57
+ personalityStatusElem.innerHTML = ""; // 초기화
58
+
59
+ for (const [key, value] of Object.entries(data.personality)) {
60
+ const li = document.createElement("li");
61
+ li.textContent = `${key}: ${value.toFixed(2)}`;
62
+ personalityStatusElem.appendChild(li);
63
+ }
64
+ }
65
+
66
+ // 버튼 클릭 시 NPC 상호작용 수동 실행
67
+ async function triggerNPCInteractions() {
68
+ const response = await fetch('/npc_social_network/trigger_npc_interactions', {
69
+ method: 'POST'
70
+ });
71
+ const data = await response.json();
72
+ console.log(data.status); // 콘솔 확인용
73
+ }
74
+
75
+ // NPC 기억 로드
76
+ async function loadNPCMemory() {
77
+ const npc = document.getElementById("npc").value;
78
+ const response = await fetch(`/npc_social_network/npc_memory?npc=${encodeURIComponent(npc)}`);
79
+ const data = await response.json();
80
+
81
+ const memoryListElem = document.getElementById("memoryList");
82
+ memoryListElem.innerHTML = ""; // 초기화
83
+
84
+ if (data.memory_list.length === 0) {
85
+ memoryListElem.innerHTML = "<li>(기억없음)</li>";
86
+ return;
87
+ }
88
+
89
+ data.memory_list.forEach(memory => {
90
+ const li = document.createElement("li");
91
+ li.textContent = memory;
92
+ memoryListElem.appendChild(li);
93
+ });
94
  }
npc_social_network/templates/chat.html CHANGED
@@ -6,17 +6,18 @@
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>NPC Chat</title>
8
 
9
- <link rel="stylesheet" herf="{{ url_for('static', filename='style.css') }}"
10
  </head>
11
  <body>
12
  <h2>NPC 소셜 네트워크</h2>
13
 
14
  <div class="meta-info">
15
  <label for="npc"> 대화할 NPC: </label>
16
- <select id = "npc" onchange="loadNPCInfo()">
17
- <option>Alice</option>
18
- <option>Bob</option>
19
- <option>Charlie</option>
 
20
  </select>
21
  <span id="relationStatus" style="margin-left:20px";>관계 점수: 로딩 중...</span>
22
  </div>
@@ -24,6 +25,23 @@
24
  <div id="chatBox"></div>
25
  <input type="text" id="message" placeholder="메세지를 입력하세요" style="width:80%">
26
  <button onclick="sendMessage()">보내기</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  <script src="{{ url_for('npc_social.static', filename='js/npc_chat.js') }}"></script>
29
  </body>
 
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>NPC Chat</title>
8
 
9
+ <link rel="stylesheet" herf="{{ url_for('static', filename='style.css') }}">
10
  </head>
11
  <body>
12
  <h2>NPC 소셜 네트워크</h2>
13
 
14
  <div class="meta-info">
15
  <label for="npc"> 대화할 NPC: </label>
16
+ <select id = "npc" onchange="loadNPCInfo(); loadNPCMemory();">
17
+ <option>엘라</option>
18
+ <option>앨리스</option>
19
+ <option>밥</option>
20
+ <option>찰리</option>
21
  </select>
22
  <span id="relationStatus" style="margin-left:20px";>관계 점수: 로딩 중...</span>
23
  </div>
 
25
  <div id="chatBox"></div>
26
  <input type="text" id="message" placeholder="메세지를 입력하세요" style="width:80%">
27
  <button onclick="sendMessage()">보내기</button>
28
+ <button onclick="triggerNPCInteractions()">NPC 상호작용 실행</button>
29
+
30
+ <!-- Memory 영역 추가 -->
31
+ <div class="meta-info">
32
+ <h4>Memory:</h4>
33
+ <ul id="memoryList">
34
+ <li>로딩 중...</li>
35
+ </ul>
36
+ </div>
37
+
38
+ <!-- Personality 상태 UI 표시 -->
39
+ <div class="meta-info">
40
+ <h4>Personality 상태:</h4>
41
+ <ul id="personalityStatus">
42
+ <li>로딩 중...</li>
43
+ </ul>
44
+ </div>
45
 
46
  <script src="{{ url_for('npc_social.static', filename='js/npc_chat.js') }}"></script>
47
  </body>
run_npc_interactions.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # portfolio/run_npc_interactions.py
2
+
3
+ import time
4
+ from npc_social_network.routes.npc_route import npc_manager
5
+
6
+ def run_npc_interactions(interval_seconds=10):
7
+ while True:
8
+ print(f"[Background] NPC interactions triggered.", flush=True)
9
+ npc_manager.npc_interactions()
10
+ time.sleep(interval_seconds)
11
+
12
+ if __name__ == '__main__':
13
+ print("[Background] Starting NPC interactions loop...", flush=True)
14
+ run_npc_interactions(interval_seconds=10)
test.ipynb CHANGED
@@ -13,7 +13,7 @@
13
  },
14
  {
15
  "cell_type": "code",
16
- "execution_count": 4,
17
  "id": "b58bbb07",
18
  "metadata": {},
19
  "outputs": [
@@ -21,15 +21,197 @@
21
  "name": "stdout",
22
  "output_type": "stream",
23
  "text": [
24
- "Processing d:\\home\\conda\\feedstock_root\\build_artifacts\\comm_1733502965406\\work (from -r requirements.txt (line 8))\n"
25
- ]
26
- },
27
- {
28
- "name": "stderr",
29
- "output_type": "stream",
30
- "text": [
31
- "ERROR: Could not install packages due to an OSError: [Errno 2] No such file or directory: 'D:\\\\home\\\\conda\\\\feedstock_root\\\\build_artifacts\\\\comm_1733502965406\\\\work'\n",
32
- "\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  ]
34
  }
35
  ],
 
13
  },
14
  {
15
  "cell_type": "code",
16
+ "execution_count": 1,
17
  "id": "b58bbb07",
18
  "metadata": {},
19
  "outputs": [
 
21
  "name": "stdout",
22
  "output_type": "stream",
23
  "text": [
24
+ "Requirement already satisfied: accelerate==1.7.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 1)) (1.7.0)\n",
25
+ "Requirement already satisfied: annotated-types==0.7.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 2)) (0.7.0)\n",
26
+ "Requirement already satisfied: bitsandbytes==0.45.5 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 3)) (0.45.5)\n",
27
+ "Requirement already satisfied: blinker==1.9.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 4)) (1.9.0)\n",
28
+ "Requirement already satisfied: cachetools==5.5.2 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 5)) (5.5.2)\n",
29
+ "Requirement already satisfied: certifi==2025.4.26 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 6)) (2025.4.26)\n",
30
+ "Requirement already satisfied: charset-normalizer==3.4.2 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 7)) (3.4.2)\n",
31
+ "Requirement already satisfied: click==8.2.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 8)) (8.2.0)\n",
32
+ "Requirement already satisfied: colorama==0.4.6 in c:\\users\\human\\appdata\\roaming\\python\\python311\\site-packages (from -r requirements.txt (line 9)) (0.4.6)\n",
33
+ "Requirement already satisfied: filelock==3.18.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 10)) (3.18.0)\n",
34
+ "Requirement already satisfied: Flask==3.1.1 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 11)) (3.1.1)\n",
35
+ "Requirement already satisfied: fsspec==2025.5.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 12)) (2025.5.0)\n",
36
+ "Requirement already satisfied: google-ai-generativelanguage==0.6.15 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 13)) (0.6.15)\n",
37
+ "Collecting google-api-core==2.25.0 (from -r requirements.txt (line 14))\n",
38
+ " Downloading google_api_core-2.25.0-py3-none-any.whl.metadata (3.0 kB)\n",
39
+ "Collecting google-api-python-client==2.171.0 (from -r requirements.txt (line 15))\n",
40
+ " Downloading google_api_python_client-2.171.0-py3-none-any.whl.metadata (7.0 kB)\n",
41
+ "Collecting google-auth==2.40.3 (from -r requirements.txt (line 16))\n",
42
+ " Downloading google_auth-2.40.3-py2.py3-none-any.whl.metadata (6.2 kB)\n",
43
+ "Requirement already satisfied: google-auth-httplib2==0.2.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 17)) (0.2.0)\n",
44
+ "Requirement already satisfied: google-generativeai==0.8.5 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 18)) (0.8.5)\n",
45
+ "Requirement already satisfied: googleapis-common-protos==1.70.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 19)) (1.70.0)\n",
46
+ "Collecting grpcio==1.73.0 (from -r requirements.txt (line 20))\n",
47
+ " Downloading grpcio-1.73.0-cp311-cp311-win_amd64.whl.metadata (4.0 kB)\n",
48
+ "Requirement already satisfied: grpcio-status==1.71.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 21)) (1.71.0)\n",
49
+ "Requirement already satisfied: httplib2==0.22.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 22)) (0.22.0)\n",
50
+ "Requirement already satisfied: huggingface-hub==0.32.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 23)) (0.32.0)\n",
51
+ "Requirement already satisfied: idna==3.10 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 24)) (3.10)\n",
52
+ "Requirement already satisfied: itsdangerous==2.2.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 25)) (2.2.0)\n",
53
+ "Requirement already satisfied: Jinja2==3.1.6 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 26)) (3.1.6)\n",
54
+ "Requirement already satisfied: MarkupSafe==3.0.2 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 27)) (3.0.2)\n",
55
+ "Requirement already satisfied: mpmath==1.3.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 28)) (1.3.0)\n",
56
+ "Requirement already satisfied: networkx==3.4.2 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 29)) (3.4.2)\n",
57
+ "Requirement already satisfied: numpy==2.2.6 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 30)) (2.2.6)\n",
58
+ "Requirement already satisfied: pillow==11.0.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 31)) (11.0.0)\n",
59
+ "Requirement already satisfied: proto-plus==1.26.1 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 32)) (1.26.1)\n",
60
+ "Collecting protobuf==5.29.5 (from -r requirements.txt (line 33))\n",
61
+ " Downloading protobuf-5.29.5-cp310-abi3-win_amd64.whl.metadata (592 bytes)\n",
62
+ "Requirement already satisfied: pyasn1==0.6.1 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 34)) (0.6.1)\n",
63
+ "Requirement already satisfied: pyasn1_modules==0.4.2 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 35)) (0.4.2)\n",
64
+ "Requirement already satisfied: pydantic==2.11.5 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 36)) (2.11.5)\n",
65
+ "Requirement already satisfied: pydantic_core==2.33.2 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 37)) (2.33.2)\n",
66
+ "Requirement already satisfied: pygame==2.6.1 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 38)) (2.6.1)\n",
67
+ "Requirement already satisfied: pyparsing==3.2.3 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 39)) (3.2.3)\n",
68
+ "Requirement already satisfied: python-dotenv==1.1.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 40)) (1.1.0)\n",
69
+ "Requirement already satisfied: pywin32==304 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 41)) (304)\n",
70
+ "Requirement already satisfied: PyYAML==6.0.2 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 42)) (6.0.2)\n",
71
+ "Requirement already satisfied: regex==2024.11.6 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 43)) (2024.11.6)\n",
72
+ "Requirement already satisfied: requests==2.32.3 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 44)) (2.32.3)\n",
73
+ "Requirement already satisfied: rsa==4.9.1 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 45)) (4.9.1)\n",
74
+ "Requirement already satisfied: safetensors==0.5.3 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 46)) (0.5.3)\n",
75
+ "Requirement already satisfied: sympy==1.14.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 47)) (1.14.0)\n",
76
+ "Requirement already satisfied: tokenizers==0.21.1 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 48)) (0.21.1)\n",
77
+ "Requirement already satisfied: torch==2.7.0+cu118 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 49)) (2.7.0+cu118)\n",
78
+ "Requirement already satisfied: torchaudio==2.7.0+cu118 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 50)) (2.7.0+cu118)\n",
79
+ "Requirement already satisfied: torchvision==0.22.0+cu118 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 51)) (0.22.0+cu118)\n",
80
+ "Requirement already satisfied: tqdm==4.67.1 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 52)) (4.67.1)\n",
81
+ "Requirement already satisfied: transformers==4.52.3 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 53)) (4.52.3)\n",
82
+ "Requirement already satisfied: typing-inspection==0.4.1 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 54)) (0.4.1)\n",
83
+ "Collecting uritemplate==4.2.0 (from -r requirements.txt (line 55))\n",
84
+ " Downloading uritemplate-4.2.0-py3-none-any.whl.metadata (2.6 kB)\n",
85
+ "Requirement already satisfied: urllib3==2.4.0 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 56)) (2.4.0)\n",
86
+ "Requirement already satisfied: Werkzeug==3.1.3 in c:\\users\\human\\.conda\\envs\\portfolio\\lib\\site-packages (from -r requirements.txt (line 57)) (3.1.3)\n",
87
+ "Requirement already satisfied: packaging>=20.0 in c:\\users\\human\\appdata\\roaming\\python\\python311\\site-packages (from accelerate==1.7.0->-r requirements.txt (line 1)) (24.2)\n",
88
+ "Requirement already satisfied: psutil in c:\\users\\human\\appdata\\roaming\\python\\python311\\site-packages (from accelerate==1.7.0->-r requirements.txt (line 1)) (7.0.0)\n",
89
+ "Requirement already satisfied: typing-extensions>=4.10.0 in c:\\users\\human\\appdata\\roaming\\python\\python311\\site-packages (from torch==2.7.0+cu118->-r requirements.txt (line 49)) (4.13.1)\n",
90
+ "Downloading google_api_core-2.25.0-py3-none-any.whl (160 kB)\n",
91
+ "Downloading google_auth-2.40.3-py2.py3-none-any.whl (216 kB)\n",
92
+ "Downloading protobuf-5.29.5-cp310-abi3-win_amd64.whl (434 kB)\n",
93
+ "Downloading google_api_python_client-2.171.0-py3-none-any.whl (13.5 MB)\n",
94
+ " ---------------------------------------- 0.0/13.5 MB ? eta -:--:--\n",
95
+ " ----- ---------------------------------- 1.8/13.5 MB 12.6 MB/s eta 0:00:01\n",
96
+ " ------------- -------------------------- 4.5/13.5 MB 11.2 MB/s eta 0:00:01\n",
97
+ " ------------------ --------------------- 6.3/13.5 MB 10.4 MB/s eta 0:00:01\n",
98
+ " ----------------------- ---------------- 7.9/13.5 MB 9.5 MB/s eta 0:00:01\n",
99
+ " ----------------------------- ---------- 10.0/13.5 MB 9.7 MB/s eta 0:00:01\n",
100
+ " ------------------------------------ --- 12.3/13.5 MB 9.9 MB/s eta 0:00:01\n",
101
+ " --------------------------------------- 13.4/13.5 MB 10.0 MB/s eta 0:00:01\n",
102
+ " --------------------------------------- 13.4/13.5 MB 10.0 MB/s eta 0:00:01\n",
103
+ " --------------------------------------- 13.4/13.5 MB 10.0 MB/s eta 0:00:01\n",
104
+ " --------------------------------------- 13.4/13.5 MB 10.0 MB/s eta 0:00:01\n",
105
+ " --------------------------------------- 13.4/13.5 MB 10.0 MB/s eta 0:00:01\n",
106
+ " --------------------------------------- 13.4/13.5 MB 10.0 MB/s eta 0:00:01\n",
107
+ " --------------------------------------- 13.4/13.5 MB 10.0 MB/s eta 0:00:01\n",
108
+ " --------------------------------------- 13.4/13.5 MB 10.0 MB/s eta 0:00:01\n",
109
+ " ---------------------------------------- 13.5/13.5 MB 4.3 MB/s eta 0:00:00\n",
110
+ "Downloading uritemplate-4.2.0-py3-none-any.whl (11 kB)\n",
111
+ "Downloading grpcio-1.73.0-cp311-cp311-win_amd64.whl (4.3 MB)\n",
112
+ " ---------------------------------------- 0.0/4.3 MB ? eta -:--:--\n",
113
+ " ---------------- ----------------------- 1.8/4.3 MB 9.2 MB/s eta 0:00:01\n",
114
+ " ------------------------------------ --- 3.9/4.3 MB 10.7 MB/s eta 0:00:01\n",
115
+ " ---------------------------------------- 4.3/4.3 MB 9.3 MB/s eta 0:00:00\n",
116
+ "Installing collected packages: uritemplate, protobuf, grpcio, google-auth, google-api-core, google-api-python-client\n",
117
+ "\n",
118
+ " Attempting uninstall: uritemplate\n",
119
+ "\n",
120
+ " Found existing installation: uritemplate 4.1.1\n",
121
+ "\n",
122
+ " Uninstalling uritemplate-4.1.1:\n",
123
+ "\n",
124
+ " Successfully uninstalled uritemplate-4.1.1\n",
125
+ "\n",
126
+ " Attempting uninstall: protobuf\n",
127
+ "\n",
128
+ " Found existing installation: protobuf 5.29.4\n",
129
+ "\n",
130
+ " ------ --------------------------------- 1/6 [protobuf]\n",
131
+ " Uninstalling protobuf-5.29.4:\n",
132
+ " ------ --------------------------------- 1/6 [protobuf]\n",
133
+ " Successfully uninstalled protobuf-5.29.4\n",
134
+ " ------ --------------------------------- 1/6 [protobuf]\n",
135
+ " ------ --------------------------------- 1/6 [protobuf]\n",
136
+ " ------ --------------------------------- 1/6 [protobuf]\n",
137
+ " ------ --------------------------------- 1/6 [protobuf]\n",
138
+ " ------ --------------------------------- 1/6 [protobuf]\n",
139
+ " ------ --------------------------------- 1/6 [protobuf]\n",
140
+ " ------ --------------------------------- 1/6 [protobuf]\n",
141
+ " ------ --------------------------------- 1/6 [protobuf]\n",
142
+ " Attempting uninstall: grpcio\n",
143
+ " ------ --------------------------------- 1/6 [protobuf]\n",
144
+ " Found existing installation: grpcio 1.71.0\n",
145
+ " ------ --------------------------------- 1/6 [protobuf]\n",
146
+ " ------------- -------------------------- 2/6 [grpcio]\n",
147
+ " Uninstalling grpcio-1.71.0:\n",
148
+ " ------------- -------------------------- 2/6 [grpcio]\n",
149
+ " Successfully uninstalled grpcio-1.71.0\n",
150
+ " ------------- -------------------------- 2/6 [grpcio]\n",
151
+ " ------------- -------------------------- 2/6 [grpcio]\n",
152
+ " ------------- -------------------------- 2/6 [grpcio]\n",
153
+ " ------------- -------------------------- 2/6 [grpcio]\n",
154
+ " ------------- -------------------------- 2/6 [grpcio]\n",
155
+ " ------------- -------------------------- 2/6 [grpcio]\n",
156
+ " ------------- -------------------------- 2/6 [grpcio]\n",
157
+ " ------------- -------------------------- 2/6 [grpcio]\n",
158
+ " ------------- -------------------------- 2/6 [grpcio]\n",
159
+ " ------------- -------------------------- 2/6 [grpcio]\n",
160
+ " ------------- -------------------------- 2/6 [grpcio]\n",
161
+ " ------------- -------------------------- 2/6 [grpcio]\n",
162
+ " ------------- -------------------------- 2/6 [grpcio]\n",
163
+ " ------------- -------------------------- 2/6 [grpcio]\n",
164
+ " ------------- -------------------------- 2/6 [grpcio]\n",
165
+ " Attempting uninstall: google-auth\n",
166
+ " ------------- -------------------------- 2/6 [grpcio]\n",
167
+ " Found existing installation: google-auth 2.40.2\n",
168
+ " ------------- -------------------------- 2/6 [grpcio]\n",
169
+ " Uninstalling google-auth-2.40.2:\n",
170
+ " ------------- -------------------------- 2/6 [grpcio]\n",
171
+ " Successfully uninstalled google-auth-2.40.2\n",
172
+ " ------------- -------------------------- 2/6 [grpcio]\n",
173
+ " -------------------- ------------------- 3/6 [google-auth]\n",
174
+ " -------------------- ------------------- 3/6 [google-auth]\n",
175
+ " -------------------- ------------------- 3/6 [google-auth]\n",
176
+ " -------------------- ------------------- 3/6 [google-auth]\n",
177
+ " -------------------- ------------------- 3/6 [google-auth]\n",
178
+ " -------------------- ------------------- 3/6 [google-auth]\n",
179
+ " -------------------- ------------------- 3/6 [google-auth]\n",
180
+ " Attempting uninstall: google-api-core\n",
181
+ " -------------------- ------------------- 3/6 [google-auth]\n",
182
+ " Found existing installation: google-api-core 2.25.0rc1\n",
183
+ " -------------------- ------------------- 3/6 [google-auth]\n",
184
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
185
+ " Uninstalling google-api-core-2.25.0rc1:\n",
186
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
187
+ " Successfully uninstalled google-api-core-2.25.0rc1\n",
188
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
189
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
190
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
191
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
192
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
193
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
194
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
195
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
196
+ " Attempting uninstall: google-api-python-client\n",
197
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
198
+ " Found existing installation: google-api-python-client 2.170.0\n",
199
+ " -------------------------- ------------- 4/6 [google-api-core]\n",
200
+ " --------------------------------- ------ 5/6 [google-api-python-client]\n",
201
+ " Uninstalling google-api-python-client-2.170.0:\n",
202
+ " --------------------------------- ------ 5/6 [google-api-python-client]\n",
203
+ " Successfully uninstalled google-api-python-client-2.170.0\n",
204
+ " --------------------------------- ------ 5/6 [google-api-python-client]\n",
205
+ " --------------------------------- ------ 5/6 [google-api-python-client]\n",
206
+ " --------------------------------- ------ 5/6 [google-api-python-client]\n",
207
+ " --------------------------------- ------ 5/6 [google-api-python-client]\n",
208
+ " --------------------------------- ------ 5/6 [google-api-python-client]\n",
209
+ " --------------------------------- ------ 5/6 [google-api-python-client]\n",
210
+ " --------------------------------- ------ 5/6 [google-api-python-client]\n",
211
+ " --------------------------------- ------ 5/6 [google-api-python-client]\n",
212
+ " ---------------------------------------- 6/6 [google-api-python-client]\n",
213
+ "\n",
214
+ "Successfully installed google-api-core-2.25.0 google-api-python-client-2.171.0 google-auth-2.40.3 grpcio-1.73.0 protobuf-5.29.5 uritemplate-4.2.0\n"
215
  ]
216
  }
217
  ],