forked from UT-InfraAI/ventis
-
Notifications
You must be signed in to change notification settings - Fork 0
Telemetry signals #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
53911f2
Switched ventis build from building sequentially to in parallel with …
Saaketh0 ae6d61d
WIP: telemetry-signals changes before merging ventis-build-speedup
Saaketh0 115d672
Merge ventis-build-speedup into telemetry-signals
Saaketh0 8dc0403
small changes made to portfolio
Saaketh0 9ee6b35
added uv for pip install + caching
Saaketh0 c7bf902
Telemetry MVP
Saaketh0 ceedc5b
Removed useless glob controller function
Saaketh0 7d5c456
Decoupled some glob/loc logic
Saaketh0 8f8a8e0
Some more small changes
Saaketh0 ce398a1
organized examples folder
Saaketh0 9b2305d
moved templates folder and renamed it to helloworld
Saaketh0 c71e956
Initial telemetry code as of Aug 3 morning
Saaketh0 ed1d902
added a failure field to the future that fails if it happens (#28)
Saaketh0 95d0551
added more explicit failures
Saaketh0 9309939
added more explicit failures
Saaketh0 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,3 +19,4 @@ AWSCLIV2.pkg | |
| docker_container | ||
| grpc_stubs | ||
| stubs | ||
| tests | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,3 +40,4 @@ docker_container/ | |
| !.env.example | ||
| AWSCLIV2.pkg | ||
| .python-version | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| # Intent Agent | ||
| # | ||
| # Stage 0. Turns a free-text portfolio request into the structured input the | ||
| # rest of the pipeline needs: | ||
| # | ||
| # "Analyze 40% Apple, 35% Microsoft and 25% Nvidia over the last 6 months" | ||
| # -> {"holdings": {"AAPL": 0.4, "MSFT": 0.35, "NVDA": 0.25}, | ||
| # "lookback_days": 180} | ||
| # | ||
| # Calls AWS Bedrock (Converse API) via ventis.llm.bedrock -- same pattern as | ||
| # AdvisorAgent -- so token/cost telemetry gets recorded onto this execution's | ||
| # future:<future_id>:metrics hash. Configure with env vars: | ||
| # BEDROCK_MODEL_ID (default: meta.llama3-8b-instruct-v1:0) | ||
| # AWS_REGION (default: us-east-1) | ||
| # | ||
| # If the LLM is unavailable or returns unparseable output, parse() raises: | ||
| # there is no fallback, the request fails loudly rather than guessing at the | ||
| # holdings. Weights are renormalized to 1.0. | ||
| # | ||
| # Resource profile: cheap CPU, single call per request, on the critical path | ||
| # before the fan-out. | ||
|
|
||
| import os | ||
| import re | ||
| import json | ||
|
|
||
| try: | ||
| from ventis.llm.bedrock import call_bedrock | ||
| except ImportError: | ||
| from bedrock import call_bedrock | ||
|
|
||
| DEFAULT_LOOKBACK_DAYS = 365 | ||
|
|
||
|
|
||
| class IntentAgent(object): | ||
| def __init__(self): | ||
| self.tools = [self.parse] | ||
| self.model_id = os.environ.get( | ||
| "BEDROCK_MODEL_ID", "meta.llama3-8b-instruct-v1:0" | ||
| ) | ||
| self.region = os.environ.get("AWS_REGION", "us-east-1") | ||
|
|
||
| def parse(self, query: str) -> dict: | ||
| """Parse a natural-language portfolio request into holdings + lookback.""" | ||
| response = call_bedrock( | ||
| model_id=self.model_id, | ||
| messages=[{"role": "user", "content": [{"text": self._build_prompt(query)}]}], | ||
| inference_config={"maxTokens": 300, "temperature": 0.0}, | ||
| region=self.region, | ||
| ) | ||
| text = response["output"]["message"]["content"][0]["text"] | ||
| if not text: | ||
| raise ValueError("IntentAgent: LLM returned no output for the request.") | ||
|
|
||
| parsed = self._extract_json(text) | ||
| if parsed is None: | ||
| raise ValueError( | ||
| f"IntentAgent: could not parse holdings from LLM output: {text!r}" | ||
| ) | ||
|
|
||
| result = self._sanitize(parsed) | ||
| if not result["holdings"]: | ||
| raise ValueError( | ||
| f"IntentAgent: no valid holdings found in request: {query!r}" | ||
| ) | ||
| return result | ||
|
|
||
| def _build_prompt(self, query: str) -> str: | ||
| return ( | ||
| "You convert a plain-English portfolio request into JSON. Return ONLY " | ||
| "a JSON object, no prose, with exactly two keys:\n" | ||
| ' "holdings": an object mapping stock TICKER symbols (uppercase) to ' | ||
| "their weight as a decimal fraction (weights should sum to about 1.0), and\n" | ||
| ' "lookback_days": an integer number of calendar days for the analysis ' | ||
| f"window (default {DEFAULT_LOOKBACK_DAYS} if unspecified; 1 month = 30 " | ||
| "days, 1 year = 365 days).\n" | ||
| "Resolve company names to their ticker (Apple->AAPL, Microsoft->MSFT, " | ||
| "Nvidia->NVDA, etc.). If weights are given as percentages, convert to " | ||
| "fractions. If a holding has no explicit weight, split the remainder " | ||
| "equally among the unweighted holdings.\n\n" | ||
| f'Request: "{query}"\n\n' | ||
| "JSON:" | ||
| ) | ||
|
|
||
| def _extract_json(self, text: str): | ||
| """Pull the first JSON object out of the model's response text.""" | ||
| # Models sometimes wrap the JSON in prose or code fences; grab the | ||
| # outermost {...} span. | ||
| match = re.search(r"\{.*\}", text, re.DOTALL) | ||
| if not match: | ||
| return None | ||
| try: | ||
| return json.loads(match.group(0)) | ||
| except (ValueError, TypeError): | ||
| return None | ||
|
|
||
| def _sanitize(self, parsed: dict) -> dict: | ||
| """Validate types and renormalize weights to sum to 1.0.""" | ||
| raw = (parsed or {}).get("holdings") or {} | ||
| holdings = {} | ||
| for ticker, weight in raw.items(): | ||
| try: | ||
| w = float(weight) | ||
| except (ValueError, TypeError): | ||
| continue | ||
| if w > 0: | ||
| holdings[str(ticker).upper()] = w | ||
|
|
||
| total = sum(holdings.values()) | ||
| if total > 0: | ||
| holdings = {t: round(w / total, 4) for t, w in holdings.items()} | ||
|
|
||
| try: | ||
| lookback = int((parsed or {}).get("lookback_days", DEFAULT_LOOKBACK_DAYS)) | ||
| except (ValueError, TypeError): | ||
| lookback = DEFAULT_LOOKBACK_DAYS | ||
| if lookback <= 0: | ||
| lookback = DEFAULT_LOOKBACK_DAYS | ||
|
|
||
| return {"holdings": holdings, "lookback_days": lookback} | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| agent = IntentAgent() | ||
| print(agent.parse( | ||
| query="Analyze 40% Apple, 35% Microsoft and 25% Nvidia over the last 6 months" | ||
| )) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| agent: | ||
| name: IntentAgent | ||
| functions: | ||
| - name: parse | ||
| description: Parse a natural-language portfolio request into holdings + lookback. | ||
| arguments: | ||
| - name: query | ||
| type: str | ||
| returns: | ||
| type: dict |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ rules: | |
| - match: {} | ||
| access: | ||
| - Workflow | ||
| - IntentAgent | ||
| - PriceAgent | ||
| - MetricsAgent | ||
| - RiskAgent | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.