Skip to content

Commit b5dc60a

Browse files
authored
Merge pull request #6 from Cotatus/feat/1-module
Feat : 감성 모니터링 에이전트 서비스 및 파이프라인 구조 추가
2 parents 08b8b08 + 658ca7b commit b5dc60a

File tree

18 files changed

+638
-1
lines changed

18 files changed

+638
-1
lines changed

.github/workflows/deploy.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Build & Push cotatus-agent to ECR
2+
3+
on:
4+
push:
5+
branches:
6+
- develop
7+
8+
jobs:
9+
build-and-push:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Checkout source
14+
uses: actions/checkout@v4
15+
16+
- name: Set short SHA
17+
id: vars
18+
run: |
19+
echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
20+
21+
- name: Configure AWS credentials
22+
uses: aws-actions/configure-aws-credentials@v4
23+
with:
24+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
25+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
26+
aws-region: ${{ secrets.AWS_REGION }}
27+
28+
- name: Login to Amazon ECR
29+
id: login-ecr
30+
uses: aws-actions/amazon-ecr-login@v2
31+
32+
- name: Build Docker image
33+
run: |
34+
docker build -t cotatus-agent:${{ steps.vars.outputs.SHORT_SHA }} .
35+
36+
- name: Tag Docker images
37+
run: |
38+
docker tag cotatus-agent:${{ steps.vars.outputs.SHORT_SHA }} \
39+
${{ steps.login-ecr.outputs.registry }}/${{ secrets.ECR_REPOSITORY }}:${{ steps.vars.outputs.SHORT_SHA }}
40+
41+
docker tag cotatus-agent:${{ steps.vars.outputs.SHORT_SHA }} \
42+
${{ steps.login-ecr.outputs.registry }}/${{ secrets.ECR_REPOSITORY }}:latest
43+
44+
- name: Push Docker images
45+
run: |
46+
docker push ${{ steps.login-ecr.outputs.registry }}/${{ secrets.ECR_REPOSITORY }}:${{ steps.vars.outputs.SHORT_SHA }}
47+
docker push ${{ steps.login-ecr.outputs.registry }}/${{ secrets.ECR_REPOSITORY }}:latest

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ application-prod.yml
4747

4848
.claude/
4949
.codetracker/
50-
50+
.env

Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM python:3.12-slim
2+
3+
WORKDIR /app
4+
5+
COPY . /app
6+
7+
RUN pip install -r requirements.txt
8+
9+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

requirements.txt

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
aiodns==3.5.0
2+
aiohappyeyeballs==2.6.1
3+
aiohttp==3.13.2
4+
aiosignal==1.4.0
5+
annotated-doc==0.0.4
6+
annotated-types==0.7.0
7+
anthropic==0.75.0
8+
anyio==4.12.0
9+
attrs==25.4.0
10+
Authlib==1.6.6
11+
base58==2.1.1
12+
beartype==0.22.9
13+
beautifulsoup4==4.14.3
14+
bitarray==2.9.2
15+
blinker==1.9.0
16+
boto3==1.35.99
17+
botocore==1.35.99
18+
cachetools==6.2.4
19+
certifi==2025.11.12
20+
cffi==2.0.0
21+
charset-normalizer==3.4.4
22+
ckzg==2.1.5
23+
click==8.3.1
24+
cloudpickle==3.1.2
25+
cryptography==46.0.3
26+
cyclopts==4.4.0
27+
cytoolz==1.1.0
28+
diskcache==5.6.3
29+
distro==1.9.0
30+
dnspython==2.8.0
31+
docstring_parser==0.17.0
32+
docutils==0.22.4
33+
email-validator==2.3.0
34+
eth-account==0.13.7
35+
eth-hash==0.7.1
36+
eth-keyfile==0.8.1
37+
eth-keys==0.7.0
38+
eth-rlp==2.2.0
39+
eth-typing==5.2.1
40+
eth-utils==5.3.1
41+
eth_abi==5.2.0
42+
Events==0.5
43+
exceptiongroup==1.3.1
44+
fakeredis==2.33.0
45+
fastapi==0.125.0
46+
fastapi-cli==0.0.16
47+
fastapi-cloud-cli==0.7.0
48+
fastar==0.8.0
49+
fastmcp==2.14.1
50+
Flask==3.1.2
51+
frozenlist==1.8.0
52+
google==3.0.0
53+
google-api-core==2.28.1
54+
google-auth==2.45.0
55+
google-genai==1.56.0
56+
googleapis-common-protos==1.72.0
57+
greenlet==3.3.0
58+
grpcio==1.76.0
59+
h11==0.16.0
60+
hexbytes==1.3.1
61+
httpcore==1.0.9
62+
httptools==0.7.1
63+
httpx==0.28.1
64+
httpx-sse==0.4.3
65+
idna==3.11
66+
importlib_metadata==8.7.0
67+
itsdangerous==2.2.0
68+
jaraco.classes==3.4.0
69+
jaraco.context==6.0.1
70+
jaraco.functools==4.3.0
71+
Jinja2==3.1.6
72+
jiter==0.12.0
73+
jmespath==1.0.1
74+
jsonpointer==3.0.0
75+
jsonschema==4.25.1
76+
jsonschema-path==0.3.4
77+
jsonschema-specifications==2025.9.1
78+
keyring==25.7.0
79+
lupa==2.6
80+
lz4==4.4.4
81+
markdown-it-py==4.0.0
82+
MarkupSafe==3.0.3
83+
mcp==1.25.0
84+
mdurl==0.1.2
85+
more-itertools==10.8.0
86+
multidict==6.7.0
87+
neo-mamba==3.1.0
88+
neo3crypto==0.4.4
89+
nest-asyncio==1.6.0
90+
netaddr==1.3.0
91+
openai==2.14.0
92+
openapi-pydantic==0.5.1
93+
opentelemetry-api==1.39.1
94+
opentelemetry-exporter-prometheus==0.60b1
95+
opentelemetry-instrumentation==0.60b1
96+
opentelemetry-sdk==1.39.1
97+
opentelemetry-semantic-conventions==0.60b1
98+
orjson==3.11.5
99+
packaging==24.2
100+
parsimonious==0.10.0
101+
pathable==0.4.4
102+
pathvalidate==3.3.1
103+
pinecone==8.0.0
104+
pinecone-plugin-assistant==3.0.1
105+
pinecone-plugin-interface==0.0.7
106+
platformdirs==4.5.1
107+
prometheus_client==0.23.1
108+
propcache==0.4.1
109+
proto-plus==1.27.0
110+
protobuf==6.33.2
111+
py-key-value-aio==0.3.0
112+
py-key-value-shared==0.3.0
113+
pyasn1==0.6.1
114+
pyasn1_modules==0.4.2
115+
pybiginteger==1.3.4
116+
pybiginteger-stubs==1.3.4
117+
pycares==4.11.0
118+
pycparser==2.23
119+
pycryptodome==3.23.0
120+
pydantic==2.12.5
121+
pydantic-settings==2.12.0
122+
pydantic_core==2.41.5
123+
pydocket==0.16.1
124+
Pygments==2.19.2
125+
PyJWT==2.10.1
126+
pyperclip==1.11.0
127+
python-dateutil==2.9.0.post0
128+
python-dotenv==1.2.1
129+
python-json-logger==4.0.0
130+
python-multipart==0.0.21
131+
pyunormalize==17.0.0
132+
PyYAML==6.0.3
133+
redis==7.1.0
134+
referencing==0.36.2
135+
regex==2025.11.3
136+
requests==2.32.5
137+
requests-toolbelt==1.0.0
138+
rich==14.2.0
139+
rich-rst==1.3.2
140+
rich-toolkit==0.17.1
141+
rignore==0.7.6
142+
rlp==4.1.0
143+
rpds-py==0.30.0
144+
rsa==4.9.1
145+
s3transfer==0.10.4
146+
sentry-sdk==2.48.0
147+
shellingham==1.5.4
148+
six==1.17.0
149+
sniffio==1.3.1
150+
sortedcontainers==2.4.0
151+
soupsieve==2.8.1
152+
spoon-ai-sdk==0.3.6
153+
SQLAlchemy==2.0.45
154+
sse-starlette==3.0.4
155+
starlette==0.50.0
156+
tenacity==9.1.2
157+
termcolor==3.2.0
158+
tiktoken==0.12.0
159+
toolz==1.1.0
160+
tqdm==4.67.1
161+
typer==0.20.1
162+
types-requests==2.32.4.20250913
163+
typing-inspection==0.4.2
164+
typing_extensions==4.15.0
165+
urllib3==2.6.2
166+
uvicorn==0.38.0
167+
uvloop==0.22.1
168+
watchfiles==1.1.1
169+
web3==7.11.0
170+
websockets==15.0.1
171+
Werkzeug==3.1.4
172+
wrapt==1.17.3
173+
x402==1.0.0
174+
yarl==1.22.0
175+
zipp==3.23.0
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from pipelines.sentiment_pipeline import run_sentiment_pipeline
2+
3+
4+
class SentimentAgent:
5+
"""
6+
Sentiment Monitoring Agent
7+
외부 시스템(Spring에서 호출해야됨)에서 호출되며
8+
내부 파이프라인을 실행하는 진입점 역할만 수행한다.
9+
"""
10+
11+
async def handle_news_sentiment(self, news_text: str) -> dict:
12+
13+
if not news_text or not news_text.strip():
14+
raise ValueError("news_text must not be empty")
15+
16+
result = await run_sentiment_pipeline(news_text)
17+
18+
return {
19+
"sentiment_score": result["sentiment_score"],
20+
"is_anomaly": result["is_anomaly"]
21+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from pydantic import BaseSettings
2+
3+
class Settings(BaseSettings):
4+
anomaly_threshold: float = 0.4
5+
min_history_size: int = 5
6+
7+
settings = Settings()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class SentimentError(Exception):
2+
pass
3+
4+
class InvalidNewsText(SentimentError):
5+
pass
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from pydantic import BaseModel
2+
3+
class SentimentResult(BaseModel):
4+
sentiment_score: float
5+
is_anomaly: bool

0 commit comments

Comments
 (0)