Compare commits

...
87 Commits
Author SHA1 Message Date
Mervin Praison 42051630bc Merge pull request #331 from MervinPraison/develop
Develop
2025-01-23 17:19:08 +00:00
MervinPraison bfcccb6355 Update PraisonAI to version 2.0.58 and enhance reasoning capabilities
- Bumped PraisonAI version from 2.0.57 to 2.0.58 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonaiagents` dependency version from `0.0.50` to `0.0.53` across relevant files for improved functionality.
- Enhanced reasoning features by modifying agent initialization parameters to use `reasoning_steps` instead of `show_reasoning`, improving clarity in agent behavior.
- Introduced a new script `deepseek-reasoning-multi-agents.py` for multi-agent reasoning tasks, showcasing the integration of reasoning agents.
- Added documentation for new reasoning features, including a detailed guide on creating reasoning extract agents.

These changes aim to refine the reasoning capabilities and improve the overall user experience within the PraisonAI framework.
2025-01-23 17:18:54 +00:00
MervinPraison e329afc394 Refactor reasoning capabilities and update version to 0.0.52
- Removed the `any-llm-think.py` script to streamline the agent framework.
- Enhanced `deepseek-reasoning-agents.py` to include reasoning display options and updated the method for starting agents.
- Updated `pyproject.toml` and `uv.lock` to reflect the new version 0.0.52.
- Improved `agent.py` and `llm.py` to support reasoning content in both synchronous and asynchronous calls, enhancing the overall functionality of the agent framework.

These changes aim to refine the reasoning features and improve the user experience within the PraisonAI framework.
2025-01-23 13:52:58 +00:00
MervinPraison 9417cc6457 Add new reasoning agents and update version to 0.0.51
- Introduced three new Python scripts: `any-llm-think.py`, `deepseek-reasoning-agents.py`, and `deepseek-think.py` for enhanced reasoning capabilities using the `deepseek-reasoner` model.
- Updated `pyproject.toml` and `uv.lock` to reflect the new version 0.0.51.
- Enhanced the `agent.py` file with new data classes and methods to support reasoning content in chat completions, improving the overall functionality of the agent framework.

These changes aim to expand the capabilities of the PraisonAI framework by integrating reasoning features and improving the user experience with updated versioning.
2025-01-23 10:52:15 +00:00
Mervin Praison 10a3d279ae Merge pull request #329 from MervinPraison/develop
Update index.mdx description to enhance clarity and detail
2025-01-23 06:40:49 +00:00
MervinPraison 2a916208e1 Update index.mdx description to enhance clarity and detail
- Revised the description of PraisonAI to emphasize its capabilities as a production-ready Multi-AI Agents framework with self-reflection.
- Highlighted the integration of PraisonAI Agents, AutoGen, and CrewAI as a low-code solution for automating tasks and solving complex challenges.
- Focused on the framework's strengths in simplicity, customization, and effective human-agent collaboration.

These changes aim to provide users with a clearer understanding of PraisonAI's functionalities and benefits.
2025-01-23 06:40:23 +00:00
Mervin Praison bcd0bbbd24 Merge pull request #328 from MervinPraison/develop
Refactor documentation for agent setup and usage
2025-01-23 06:38:06 +00:00
MervinPraison 5701a40f11 Refactor documentation for agent setup and usage
- Updated the introduction.mdx file to streamline the steps for installing the PraisonAI package and configuring the environment.
- Revised agent creation examples to simplify the process for both single and multiple agents, enhancing clarity and usability.
- Added a new section for creating an `agents.yaml` configuration file for no-code users, including automatic generation instructions.
- Improved the overall structure and readability of the documentation to facilitate a better user experience.

These changes aim to provide clearer guidance for users in setting up and utilizing the PraisonAI framework effectively.
2025-01-23 06:37:49 +00:00
Mervin Praison 3ffac395bb Merge pull request #327 from MervinPraison/develop
Update README and documentation with new video tutorials
2025-01-23 06:34:56 +00:00
MervinPraison 37119aa3ac Update README and documentation with new video tutorials
- Removed the License section from README.md to streamline content.
- Added a comprehensive list of video tutorials to docs/index.mdx, covering various AI agent functionalities such as self-reflection, reasoning, and multimodal capabilities.
- Enhanced the documentation's educational resources, providing users with visual aids to better understand the Praison AI framework.

These changes aim to improve user engagement and learning through accessible video content.
2025-01-23 06:34:36 +00:00
Mervin Praison 8b2d324d3b Merge pull request #326 from MervinPraison/develop
Enhance README with new AI agent video resources
2025-01-23 06:30:01 +00:00
MervinPraison 6d0b29e60d Enhance README with new AI agent video resources
- Added multiple new video links to the README.md, showcasing various AI agent functionalities including self-reflection, reasoning, multimodal capabilities, and more.
- Improved the documentation's educational value by providing visual resources for users to better understand the Praison AI framework.

These changes aim to enrich the user experience by offering accessible learning materials related to AI agents.
2025-01-23 06:29:44 +00:00
Mervin Praison 583cbc5efa Merge pull request #325 from MervinPraison/develop
Update documentation and examples for agent initialization and usage
2025-01-23 06:21:43 +00:00
MervinPraison 90dd84a152 Update documentation and examples for agent initialization and usage
- Revised the README.md to reflect the updated method for starting agents, changing `agent.chat` to `agent.start` for clarity and accuracy.
- Added a new section in the README.md for creating an `agents.yaml` file, enhancing the setup instructions for users.
- Updated the installation instructions in `docs/index.mdx` to clarify package names and improve the overall structure of the documentation.
- Streamlined code examples in `docs/concepts/agents.mdx` to focus on single and multiple agent initialization, ensuring users have clear and concise guidance.

These changes improve the clarity and usability of the documentation, making it easier for users to understand and implement the PraisonAI framework.
2025-01-23 06:21:25 +00:00
Mervin Praison ef7fa66e33 Merge pull request #324 from MervinPraison/develop
Update PraisonAI to version 2.0.57 and enhance documentation
2025-01-23 06:06:43 +00:00
MervinPraison 1659ed61bc Update PraisonAI to version 2.0.57 and enhance documentation
- Bumped PraisonAI version from 2.0.56 to 2.0.57 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonaiagents` dependency version from `0.0.49` to `0.0.50` across relevant files for improved functionality.
- Added a new `docker-compose.yml` file and multiple Dockerfiles for different services (UI, chat, development) to streamline deployment.
- Enhanced the README.md with new sections on AI agents flow, tools, memory, and various processing types, improving clarity and usability.
- Introduced a new test script `cl-test.py` for validating chat functionalities with the Gemini API.

These changes improve the overall functionality, usability, and deployment processes of the PraisonAI framework.
2025-01-23 06:06:23 +00:00
Mervin Praison b8939ef439 Merge pull request #323 from MervinPraison/develop
adding chat with pdf
2025-01-22 18:37:48 +00:00
MervinPraison 4bada9e5fc adding chat with pdf 2025-01-22 18:37:27 +00:00
Mervin Praison 51c4cb00b0 Merge pull request #322 from MervinPraison/develop
updating docs
2025-01-22 18:32:20 +00:00
MervinPraison ad96549ea3 updating docs 2025-01-22 18:32:03 +00:00
Mervin Praison 183d10d7cc Merge pull request #321 from MervinPraison/develop
Develop
2025-01-22 18:29:04 +00:00
MervinPraison bce1559ab5 docs update 2025-01-22 18:28:46 +00:00
MervinPraison 6f3fb87ba3 Update README and local development documentation for improved clarity and logging instructions
- Revised section headings in README.md to number the agent categories for better organization.
- Added logging configuration instructions to the local-development.mdx file, detailing how to set log levels for both standard and advanced logging.
- Removed outdated logging instructions from README.md to streamline the documentation.

These changes enhance the clarity of the documentation and provide users with essential logging setup information for local development.
2025-01-22 18:24:24 +00:00
Mervin Praison e7f6b2df67 Merge pull request #320 from MervinPraison/develop
Update README and agent initialization for enhanced clarity and funct…
2025-01-22 18:07:29 +00:00
MervinPraison 08d72eeb80 Update README and agent initialization for enhanced clarity and functionality
- Revised the README.md to better describe PraisonAI as a production-ready Multi-AI Agents framework, emphasizing its capabilities in automating tasks and problem-solving.
- Updated the list of features to include new agent types and functionalities, such as Code Interpreter Agents and Async & Parallel Processing.
- Simplified the agent initialization examples in the README, providing clearer instructions for users to create and run agents.
- Modified the agent client initialization in main.py to handle missing API keys more gracefully.
- Added "developers/local-development" to mint.json for improved documentation structure.

These changes enhance the user experience by providing clearer documentation and improving the robustness of agent initialization.
2025-01-22 18:07:15 +00:00
Mervin Praison 11aefae90f Merge pull request #319 from MervinPraison/develop
Enhance Streamlit UIs and Add New Model Integrations
2025-01-22 13:07:45 +00:00
MervinPraison 10d5158d27 Enhance Streamlit UIs and Add New Model Integrations
- Updated `mint.json` to include new Streamlit UIs for Deepseek, Gemini, and Ollama models, improving model accessibility.
- Expanded documentation in `models.mdx` and `google.mdx` to provide detailed setup instructions for integrating OpenAI, Litellm, and Gemini models.
- Introduced new example scripts for Gemini and Ollama Streamlit applications, showcasing interactive chat capabilities.
- Added comprehensive features and prerequisites sections in the new UI documentation to guide users in setting up their environments.

These changes enhance the usability and functionality of the PraisonAI framework, particularly in model integration and user interface development.
2025-01-22 13:07:31 +00:00
Mervin Praison 1d8b814fcd Merge pull request #318 from MervinPraison/develop
Update PraisonAI to version 2.0.56 and enhance agent functionality
2025-01-22 10:46:35 +00:00
MervinPraison 6e8a5b98a8 Update PraisonAI to version 2.0.56 and enhance agent functionality
- Bumped PraisonAI version from 2.0.55 to 2.0.56 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.46` to `0.0.49` across relevant files for improved functionality.
- Introduced new agent examples for Google Gemini and Deepseek models, enhancing the framework's capabilities.
- Enhanced logging configurations to suppress unnecessary output and improve clarity during execution.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in agent management and logging clarity.
2025-01-22 10:46:18 +00:00
Mervin Praison 59d0ff8c95 Merge pull request #317 from MervinPraison/develop
Refactor deepseek agent implementation and remove unused files
2025-01-21 19:02:39 +00:00
MervinPraison b2109faa06 Refactor deepseek agent implementation and remove unused files
- Simplified the deepseek agent setup by removing the previous configuration and task definitions, replacing them with a more streamlined agent initialization.
- Updated the agent's instructions for clarity and direct usage.
- Deleted the unused `small.pdf` file to clean up the repository.
- Added "deepseek" model to the list of available models in `mint.json` for improved model management.

These changes enhance the usability and clarity of the deepseek agent within the PraisonAI framework.
2025-01-21 19:02:25 +00:00
Mervin Praison 024eaed456 Merge pull request #316 from MervinPraison/develop
Develop
2025-01-21 17:51:15 +00:00
MervinPraison 4fd3a572cf Update PraisonAI to version 2.0.55 and adjust dependencies
- Bumped PraisonAI version from 2.0.54 to 2.0.55 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.45` to `0.0.46` across relevant files for improved functionality.
- Adjusted deployment scripts and documentation to ensure compatibility with the new version.

These changes enhance the overall functionality and usability of the PraisonAI framework, particularly in dependency management and deployment processes.
2025-01-21 17:50:53 +00:00
MervinPraison baaf8b6256 Update version to 0.0.46 and enhance memory feature checks
- Bumped the version of the `praisonaiagents` package from 0.0.45 to 0.0.46 in `pyproject.toml` and `uv.lock` to reflect the latest updates.
- Added import checks for memory features in the `Agent`, `PraisonAIAgents`, and `Task` classes to ensure proper handling of memory dependencies.
- Removed the obsolete `Memory` import from the `__init__.py` file to streamline the codebase.

These changes improve the robustness of the PraisonAI framework by ensuring that memory features are only utilized when the necessary dependencies are installed.
2025-01-21 16:47:31 +00:00
Mervin Praison fe4550d2bc Merge pull request #315 from MervinPraison/develop
2.0.54
2025-01-21 15:01:57 +00:00
MervinPraison db09a94425 Update PraisonAI to version 2.0.54 and enhance agent functionality
- Bumped PraisonAI version from 2.0.53 to 2.0.54 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.44` to `0.0.45` across relevant files for improved functionality.
- Removed the obsolete `knowledge-embedding-agents.py` file and introduced a new `vector-db-agents.py` file to enhance knowledge retrieval capabilities.
- Added new documentation for RAG (Retrieval Augmented Generation) agents, detailing their configuration and usage in `docs/features/rag.mdx`.
- Updated deployment scripts to ensure compatibility with the new version and improved agent functionalities.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in knowledge management and retrieval capabilities.
2025-01-21 15:01:12 +00:00
MervinPraison 2db36dc932 Enhance Knowledge Agent Configuration and Update Version
- Updated the Knowledge Agent configuration to include a new versioning system and improved vector store settings.
- Changed the collection name from "custom_knowledge" to "praison" for consistency across files.
- Added user_id parameter to the Knowledge Agent for better user tracking.
- Enhanced the embedding database configuration to support dynamic context management.
- Bumped the version of the `praisonaiagents` package from 0.0.44 to 0.0.45 in `pyproject.toml` to reflect these updates.

These changes improve the functionality and usability of the Knowledge Agent within the PraisonAI framework, particularly in knowledge management and retrieval capabilities.
2025-01-21 13:09:41 +00:00
Mervin Praison 8c0e4277a4 Merge pull request #313 from MervinPraison/develop
Update PraisonAI to version 2.0.53 and enhance agent functionality
2025-01-20 10:04:38 +00:00
MervinPraison 41448617d5 Update PraisonAI to version 2.0.53 and enhance agent functionality
- Bumped PraisonAI version from 2.0.52 to 2.0.53 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.43` to `0.0.44` across relevant files for improved functionality.
- Enhanced the `PraisonAIAgents` class to include a `max_iter` parameter, allowing for more control over agent iterations.
- Added new tasks to `agents/tasks.csv` to expand the capabilities of the agents in handling various writing tasks.
- Updated documentation to reflect changes in agent functionality and new task examples.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in task execution and agent capabilities.
2025-01-20 10:04:20 +00:00
Mervin Praison 49ea23c676 Merge pull request #312 from MervinPraison/develop
Introducing Repetitive Agents
2025-01-20 07:18:19 +00:00
MervinPraison bb0dc63680 Update PraisonAI to version 2.0.52 and enhance repetitive agents functionality
- Bumped PraisonAI version from 2.0.51 to 2.0.52 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.42` to `0.0.43` across relevant files for improved functionality.
- Introduced new files for repetitive agents in `agents/repetitive-agents.py` and `examples/concepts/repetitive-agents.py`, enabling automated task loops.
- Enhanced documentation with a new section on repetitive agents in `docs/features/repetitive.mdx` and updated `mint.json` to include the new feature.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in handling repetitive tasks and enhancing agent capabilities.
2025-01-20 07:17:43 +00:00
MervinPraison 7774f2c565 Add loop agent functionality and update task management in PraisonAI agents
- Introduced a new loop agent in `loop_agents.py` to create and manage a loop of tasks from a CSV file.
- Added a new file `repetitive-manual-agents.py` that implements task identification, status checking, and updating functionalities.
- Updated `process.py` to enhance task handling by allowing dynamic input files for loop tasks.
- Removed the obsolete `repeat_agents.py` file to streamline the codebase.
- Bumped the version of the `praisonaiagents` package from 0.0.42 to 0.0.43 in `pyproject.toml` and `uv.lock` to reflect these changes.

These updates improve the task execution capabilities of the PraisonAI framework, particularly in handling repetitive tasks and enhancing agent functionality.
2025-01-20 06:56:33 +00:00
MervinPraison 5533fd3476 Enhance logging and improve decision/loop task handling in PraisonAI agents
- Suppressed debug logs from the markdown parser to reduce noise in the logging output.
- Refactored decision-making logic to utilize Pydantic models for better type safety and clarity.
- Updated loop task handling to ensure proper context management and error handling.
- Introduced dynamic literal types for decision and loop tasks to enhance flexibility in task definitions.

These changes improve the overall robustness and usability of the PraisonAI framework, particularly in task execution and logging clarity.
2025-01-19 05:58:46 +00:00
Mervin Praison 262a90a235 Merge pull request #310 from MervinPraison/develop
2.0.51
2025-01-18 06:02:35 +00:00
MervinPraison 60928dcb90 Update PraisonAI to version 2.0.51 and enhance dependencies
- Bumped PraisonAI version from 2.0.50 to 2.0.51 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.41` to `0.0.42` across relevant files for improved functionality.
- Enhanced documentation with updated installation instructions for various examples, ensuring users have access to the latest package versions.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in dependency management and documentation clarity.
2025-01-18 06:02:09 +00:00
MervinPraison c8552e1158 Update PraisonAI agents package version to 0.0.42 in pyproject.toml and uv.lock
- Bumped the version from 0.0.41 to 0.0.42 to reflect recent updates and ensure users have access to the latest features and improvements.
- This change maintains the integrity of the PraisonAI framework and prepares it for future enhancements.
2025-01-18 05:48:57 +00:00
Mervin Praison c57d7db9bb Merge pull request #309 from MervinPraison/develop
Enhance Streamlit UIs for Code Analysis and Hackathon Judging
2025-01-17 22:21:06 +00:00
MervinPraison 236abc2c83 Enhance Streamlit UIs for Code Analysis and Hackathon Judging
- Updated `mint.json` to group Streamlit pages under a new "Streamlit" section, improving organization.
- Renamed titles in `code-analysis.mdx` and `hackathon-judge.mdx` to include "Agent" for clarity.
- Added new Streamlit UI files: `code-analysis-streamlit.mdx` and `hackathon-judge-streamlit.mdx`, providing interactive interfaces for code analysis and hackathon project evaluation.
- Each new UI includes detailed descriptions, features, quick start guides, and visual flowcharts to enhance user experience and understanding.

These changes significantly improve the usability and accessibility of the PraisonAI framework's Streamlit applications, offering users powerful tools for code and project evaluation.
2025-01-17 22:20:51 +00:00
Mervin Praison 76c5f8fe3f Merge pull request #308 from MervinPraison/develop
Add new code analysis and hackathon judge agents with Streamlit integ…
2025-01-17 19:03:12 +00:00
MervinPraison 82750020d2 Add new code analysis and hackathon judge agents with Streamlit integration
- Introduced `code-analysis-agents.py` and `code-analysis-streamlit.py` for comprehensive code evaluation, including metrics on architecture, maintainability, performance, and security.
- Added `context-agents-code.py` and `context-agents.py` for CV analysis capabilities, providing detailed scoring and recommendations.
- Implemented `hackathon-judge-agent.py` and `hackathon-judge-streamlit.py` for evaluating hackathon projects through video demonstrations, offering scores and feedback on innovation, technical complexity, and presentation quality.
- Enhanced documentation with new examples for code analysis and hackathon judging, improving user guidance and showcasing agent capabilities.
- Updated `mint.json` to include new examples, enriching the available resources for users.

These additions significantly expand the functionality of the PraisonAI framework, providing users with powerful tools for code and project evaluation.
2025-01-17 19:02:56 +00:00
Mervin Praison f49ad9fbc2 Merge pull request #306 from MervinPraison/develop
Develop
2025-01-17 17:35:18 +00:00
MervinPraison c086c60fd6 Update PraisonAI to version 2.0.50 and enhance dependencies
- Bumped PraisonAI version from 2.0.49 to 2.0.50 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.40` to `0.0.41` across relevant files for improved functionality.
- Added a new `context-agents.py` file to introduce a CV analysis agent with comprehensive evaluation capabilities.
- Modified deployment scripts to ensure compatibility with the updated package version.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in dependency management and the introduction of new agent capabilities.
2025-01-17 17:35:00 +00:00
MervinPraison 4f8f4f2036 Update package version to 0.0.41 in uv.lock
- Bumped the version of the PraisonAI agents package from 0.0.40 to 0.0.41 to reflect recent updates.
- This change ensures that the latest features and improvements are properly versioned and available for users.
2025-01-17 17:26:51 +00:00
MervinPraison 8e91c20967 Update package version to 0.0.41 in pyproject.toml
- Bumped the version of the PraisonAI agents package from 0.0.40 to 0.0.41 to reflect recent updates.
- This change ensures that the latest features and improvements are properly versioned and available for users.

These updates maintain the integrity of the PraisonAI framework and prepare it for future enhancements.
2025-01-17 17:26:34 +00:00
MervinPraison 6f092c1507 Refactor agent context handling and improve task prompt generation
- Updated `crewai-tools-example.py` to remove unnecessary whitespace.
- Modified `agent.py` to replace `schema_json()` with `model_json_schema()` for JSON output consistency.
- Enhanced context handling in `agents.py` to avoid duplicates and improve clarity in task prompts by using lists instead of strings.
- Added support for passing content to tasks in both `start` and `astart` methods, allowing for dynamic context management.
- Improved task prompt generation in `task.py` to handle various context types, ensuring better output formatting.

These changes enhance the functionality and usability of the PraisonAI agents, particularly in context management and task execution clarity.
2025-01-17 17:25:58 +00:00
Mervin Praison 8f553d3a54 Merge pull request #305 from MervinPraison/develop
2.0.49
2025-01-17 12:24:16 +00:00
MervinPraison 2d647e25b5 Update PraisonAI to version 2.0.49 and enhance dependencies
- Bumped PraisonAI version from 2.0.48 to 2.0.49 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.39` to `0.0.40` across relevant files for improved functionality.
- Modified deployment scripts to ensure compatibility with the updated package version.
- Enhanced documentation by adding a new "Tools" section in `mint.json` and updating the title in `custom.mdx` for better clarity.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in dependency management and documentation clarity.
2025-01-17 12:23:44 +00:00
MervinPraison 039bb772f5 Update version to 0.0.40 and enhance agent functionality
- Bumped the package version in `pyproject.toml` and `uv.lock` from `0.0.39` to `0.0.40` to reflect recent updates.
- Improved the `Agent` class in `agent.py` to support both Langchain and CrewAI tools by adding checks for the presence of `run` and `_run` methods, allowing for more flexible function handling.

These changes enhance the functionality of the PraisonAI agents, ensuring compatibility with different toolsets and improving overall usability.
2025-01-17 12:13:08 +00:00
Mervin Praison 459c2f2b70 Merge pull request #304 from MervinPraison/develop
Add new examples and enhance documentation for AI agent use cases
2025-01-17 10:34:16 +00:00
MervinPraison ee59706357 Add new examples and enhance documentation for AI agent use cases
- Introduced multiple new example files for various AI agent applications, including Climate Impact, Crypto Validator, DeFi Market Maker, Medicine Protocol, Neural Architecture, Quantum Optimiser, Research Assistant, Space Mission, and Vulnerability Detection.
- Updated `mint.json` to include new examples, improving the breadth of use cases available for users.
- Enhanced the `examples.mdx` file to provide links and descriptions for the newly added examples, facilitating easier navigation and understanding of the capabilities of PraisonAI.

These changes significantly expand the documentation and practical examples available to users, showcasing the versatility of the PraisonAI framework in various domains.
2025-01-17 10:33:58 +00:00
Mervin Praison 2a51644773 Merge pull request #303 from MervinPraison/develop
Refactor documentation and enhance quickstart guide for PraisonAI
2025-01-16 11:45:30 +00:00
MervinPraison cce908fa22 Refactor documentation and enhance quickstart guide for PraisonAI
- Removed unnecessary note from the introduction section of `introduction.mdx` for improved clarity.
- Updated the `quickstart.mdx` to provide a more comprehensive and user-friendly guide, including detailed steps for both code and no-code approaches to creating AI agents.
- Enhanced the `knowledge.mdx` file by renaming the vector store from "Chroma" to "Vector DB" for better clarity in terminology.
- Added prerequisites and tips to the quickstart guide to assist users in setting up their environment effectively.

These changes improve the overall usability and clarity of the documentation, making it easier for users to get started with PraisonAI.
2025-01-16 11:45:01 +00:00
Mervin Praison acf476f715 Merge pull request #302 from MervinPraison/develop
Develop
2025-01-16 11:13:41 +00:00
MervinPraison e5d77de79c Update PraisonAI to version 2.0.48 and enhance dependencies
- Bumped PraisonAI version from 2.0.47 to 2.0.48 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Updated the `praisonaiagents` dependency version from `0.0.38` to `0.0.39` across relevant files for improved functionality.
- Modified deployment scripts to ensure compatibility with the updated package version.
- Removed outdated references in documentation and improved clarity in agent-related concepts.

These changes enhance the overall functionality and usability of the PraisonAI framework, particularly in dependency management and deployment processes.
2025-01-16 11:13:22 +00:00
MervinPraison 9ab444b54c Update knowledge agent configuration and versioning
- Changed the knowledge source in `knowledge-agents.py` from `small.pdf` to `large.pdf` to utilize a more comprehensive dataset.
- Bumped the package version in `pyproject.toml` and `uv.lock` from `0.0.38` to `0.0.39` to reflect recent updates.
- Enhanced the `Knowledge` class in `knowledge.py` by adding a progress display for memory storage operations, improving user experience during knowledge updates.

These changes improve the functionality and usability of the knowledge management system within the PraisonAI framework.
2025-01-16 10:14:11 +00:00
Mervin Praison e13f543c6d Merge pull request #301 from MervinPraison/develop
v0.0.38
2025-01-16 08:27:58 +00:00
MervinPraison 4f235d358c Update PraisonAI to version 2.0.47 and enhance knowledge management features
- Bumped PraisonAI version from 2.0.46 to 2.0.47 in `Dockerfile`, `pyproject.toml`, and `uv.lock` to reflect the latest updates.
- Updated the `praisonai.rb` formula to point to the new version's tarball.
- Enhanced the knowledge management system by adding a new `knowledge.mdx` file and related examples for creating knowledge-based agents.
- Updated documentation to include new concepts and improve clarity on knowledge management functionalities.
- Refactored deployment scripts to ensure compatibility with the updated package version.

These changes improve the overall functionality and usability of the PraisonAI framework, particularly in knowledge management and deployment processes.
2025-01-16 08:27:33 +00:00
MervinPraison b7847feb1e Update package version and enhance logging in Knowledge class
- Bumped the package version in `pyproject.toml` and `uv.lock` from `0.0.37` to `0.0.38` to reflect recent changes.
- Modified the `Knowledge` class in `knowledge.py` to include a `verbose` parameter for improved logging control.
- Implemented an internal logging helper method to streamline log messages and manage logging levels based on the `verbose` setting.
- Updated various logging statements to utilize the new logging helper, enhancing clarity and consistency in log outputs.

These changes improve the maintainability and usability of the knowledge management system by providing better logging capabilities.
2025-01-16 08:14:21 +00:00
MervinPraison 7ac730462c Update knowledge agent configuration and enhance memory management
- Changed the knowledge source in `knowledge-agents.py` from `large.pdf` to `small.pdf` for improved testing consistency.
- Bumped the package version in `pyproject.toml` from `0.0.36` to `0.0.37` to reflect recent changes.
- Updated the `chromadb` dependency version in `pyproject.toml` to `0.5.23` for compatibility.
- Enhanced the `CustomMemory` class in `knowledge.py` to allow dynamic memory management without relying on LLM, improving performance and flexibility.
- Introduced cached properties in the `Knowledge` class for better configuration handling and memory management.

These changes improve the knowledge agent's functionality and ensure better performance in memory operations.
2025-01-16 08:07:08 +00:00
MervinPraison 9cbc8d082d Add chunking functionality and update knowledge management features
Knowledge working without lazy loading

- Introduced a new `chunking-direct-test.py` file to demonstrate the usage of the `Chunking` class for text chunking with various strategies.
- Updated `knowledge-agents.py` to change the knowledge source from `2409.13731v3.pdf` to `large.pdf` and modified the agent's query for clarity.
- Revised `knowledge-direct-test.py` to replace the reference to `sample.pdf` with `small.pdf`, ensuring consistency in test file usage.
- Added `knowledge-large-pdf-test.py` to test the handling of large PDF files, integrating logging for better traceability.
- Updated `pyproject.toml` to include the new `chonkie` dependency for chunking functionalities.
- Removed the deprecated `sample.pdf` and added `small.pdf` to the agents directory for testing purposes.
- Enhanced the `Knowledge` class in `knowledge.py` to utilize the new `Chunking` class for improved memory management and content processing.

These changes enhance the knowledge management system's capabilities by integrating chunking strategies and improving file handling processes.
2025-01-16 07:56:32 +00:00
MervinPraison 7fb0aed7ac Refactor memory handling in knowledge-direct-test.py and knowledge.py
- Updated memory retrieval, updating, and deletion methods in `knowledge-direct-test.py` to correctly access memory IDs from the new results structure.
- Enhanced logging to provide clearer information about memory operations, including warnings for unexpected memory formats.
- Modified the `Knowledge` class in `knowledge.py` to ensure all memory results are returned in a consistent format, improving the handling of stored memories.
- Improved error handling and added checks for valid memory formats when verifying stored content from text and PDF files.

These changes enhance the robustness and clarity of memory management within the knowledge management system.
2025-01-16 06:24:15 +00:00
MervinPraison 206f0d01e7 Add new knowledge management features and files
- Introduced a new `knowledge-agents-task.py` script to define and execute tasks for knowledge agents, enhancing the framework's capabilities for knowledge retrieval and management.
- Added `knowledge-agents.py` to create a knowledge agent with specific instructions and knowledge sources, allowing for more tailored interactions.
- Implemented `knowledge-direct-test.py` for testing memory storage and retrieval functionalities, showcasing the new capabilities of the knowledge management system.
- Created `md.py` for handling Markdown file conversions, integrating with the knowledge management features.
- Updated `pyproject.toml` to specify the exact version of the `chromadb` dependency, ensuring compatibility with the new features.
- Added new PDF and DOCX files to the agents directory for testing and demonstration purposes.
- Enhanced the `Knowledge` class in `knowledge.py` to support user and agent identifiers, improving memory management and retrieval processes.

This commit significantly expands the knowledge management functionalities within the PraisonAI framework, providing new tools and scripts for better handling of knowledge content.
2025-01-16 05:36:08 +00:00
MervinPraison e19a310314 Update dependencies and enhance knowledge management system
- Updated the `chainlit` dependency version from `2.0.1` to `2.0.3` across multiple configurations in `pyproject.toml` and `agents/pyproject.toml` to ensure compatibility with the latest features and fixes.
- Introduced a new optional dependency group `knowledge` in `agents/pyproject.toml` for enhanced knowledge management capabilities, including `mem0ai` and `markitdown`.
- Refactored the `Knowledge` class in `knowledge.py` to improve initialization and memory management, allowing for better handling of user and agent identifiers.
- Enhanced methods for storing, retrieving, and managing memories, including new functionalities for updating and deleting memories.
- Updated UI components in `mint.json` and `realtime.py` to reflect changes in model naming conventions, improving user experience and clarity.

This commit strengthens the overall functionality and usability of the PraisonAI framework, particularly in knowledge management and UI interactions.
2025-01-15 17:00:15 +00:00
MervinPraison 1ea572689e Refactor Knowledge Management System in knowledge.py
- Overhauled the `Knowledge` class to enhance the knowledge management system, introducing a more flexible initialization with user and agent identifiers, and improved configuration options.
- Streamlined methods for adding, searching, and deleting knowledge, integrating a new memory management system for better performance and organization.
- Updated vector store and embedding configurations to support a wider range of providers and models, including options for graph capabilities.
- Enhanced error handling and debugging features for improved troubleshooting.
- Removed deprecated methods and optimized existing functionality for clarity and efficiency.

This commit significantly improves the structure and capabilities of the knowledge management system within the PraisonAI framework, facilitating better content handling and retrieval.
2025-01-15 06:52:26 +00:00
MervinPraison 96df649b05 Add Knowledge Management System in knowledge.py
- Introduced a new `Knowledge` class for managing knowledge content, including methods for adding, updating, searching, and deleting knowledge.
- Implemented support for various vector store types (Chroma, Pinecone, PGVector, Qdrant, Milvus) for storing embeddings.
- Added functionality for chunking text, generating embeddings using different models (OpenAI, Cohere, SentenceTransformers, HuggingFace), and optional encryption of content.
- Enhanced caching mechanism for search results to improve performance.
- Included comprehensive error handling and debug mode for better troubleshooting.

This commit establishes a robust framework for knowledge management within the PraisonAI agents, enhancing the system's capabilities for handling and retrieving information efficiently.
2025-01-15 06:18:33 +00:00
Mervin Praison 5aed75837a Merge pull request #300 from MervinPraison/develop
Refactor UI documentation and update navigation structure
2025-01-15 05:18:38 +00:00
MervinPraison 9c8f68a05f Refactor UI documentation and update navigation structure
- Renamed and reorganized the UI documentation in `ui.mdx`, changing the title and sidebar title for clarity.
- Updated the installation instructions to provide a more streamlined setup process.
- Removed the previous table of available interfaces and replaced it with a concise description of features.
- Adjusted the `mint.json` file to reflect the new UI documentation structure, enhancing navigation for users.

This commit improves the clarity and accessibility of the user interface documentation, making it easier for users to understand and utilize the PraisonAI framework.
2025-01-15 05:18:07 +00:00
Mervin Praison 9778a69c4d Merge pull request #299 from MervinPraison/develop
Remove deprecated use case documentation and update navigation structure
2025-01-14 17:12:40 +00:00
MervinPraison 73c7994380 Remove deprecated use case documentation and update navigation structure
- Deleted multiple use case files including "Examples," "Adaptive Learning," "Code Review," "Customer Service," "Emergency Response," "Fraud Detection," "Healthcare Diagnosis," "Multilingual Content," "Predictive Maintenance," "Smart City," and "Supply Chain" to streamline documentation.
- Updated `mint.json` to replace "Use Cases" with "Examples" in the navigation, enhancing clarity and organization.
- Adjusted navigation groups to reflect the new structure, ensuring users can easily find relevant information.

This commit focuses on cleaning up outdated documentation and improving the overall user experience by refining the navigation structure.
2025-01-14 17:12:26 +00:00
Mervin Praison 82b83ded41 Merge pull request #298 from MervinPraison/develop
Update PraisonAI and praisonaiagents to versions 2.0.46 and 0.0.36 re…
2025-01-14 13:47:58 +00:00
MervinPraison fc80db32c2 Update PraisonAI and praisonaiagents to versions 2.0.46 and 0.0.36 respectively
- Bumped the PraisonAI package version from 2.0.45 to 2.0.46 in Dockerfile, pyproject.toml, and related files.
- Updated the installation command in Dockerfile and deployment scripts to reflect the new version.
- Updated the praisonaiagents package version from 0.0.35 to 0.0.36 in relevant files.
- Introduced new agents for data analysis, finance, image processing, and more, enhancing the framework's capabilities.
- Added new example scripts demonstrating the usage of the newly created agents.
- Updated documentation to include new agents and their functionalities, improving user guidance and accessibility.

This commit enhances the overall functionality of the PraisonAI framework while ensuring that all components are up-to-date.
2025-01-14 13:46:43 +00:00
Mervin Praison 3f115ca7ba Merge pull request #297 from MervinPraison/develop
Refactor multimodal agent execution and enhance documentation structure
2025-01-14 09:48:14 +00:00
MervinPraison a32d45e6da Refactor multimodal agent execution and enhance documentation structure
- Simplified the execution of the multimodal agent by removing unnecessary result printing, allowing for a cleaner start method call.
- Updated `mint.json` to include new tabs for "Documentation" and "Use Cases," improving navigation and accessibility of relevant information.
- Added a new "Usecases" group in the navigation section of `mint.json`, detailing various use cases for better user guidance.

This commit streamlines the multimodal agent's functionality and enhances the documentation for improved user experience.
2025-01-14 09:47:50 +00:00
Mervin Praison 8823df26ff Merge pull request #294 from MervinPraison/develop
Add EXASearchTool class and integrate with AI agents
2025-01-13 13:20:26 +00:00
MervinPraison 9c2126fbd6 Add EXASearchTool class and integrate with AI agents
- Introduced a new `EXASearchTool` class to interact with the EXA Search API, allowing AI agents to perform searches and retrieve results.
- Implemented methods for running queries and parsing results into a readable format.
- Created a `SearchAgent` to utilize the `EXASearchTool` for searching information about the 'AI Agents Framework'.
- Added a task definition for the `SearchAgent` to demonstrate the tool's functionality.
- Updated documentation to include the new `tools_class` and provide a comprehensive guide on using class-based tools with AI agents.
2025-01-13 13:20:00 +00:00
Mervin Praison 741b01bdf0 Merge pull request #293 from MervinPraison/develop
Refactor autonomous agent workflow and enhance documentation
2025-01-13 12:25:56 +00:00
MervinPraison 6ed9a69cd8 Refactor autonomous agent workflow and enhance documentation
- Renamed and refactored functions in `autonomous-agent.py` to improve clarity and functionality, including changing `get_environment_feedback` to `get_environment_state`.
- Introduced new agents: `Environment Monitor`, `Action Executor`, and `Feedback Processor` to better structure the workflow.
- Updated task definitions to create a more coherent feedback loop and action execution process.
- Added a `main` function to encapsulate the workflow execution and result printing.
- Updated `mint.json` to include a new "Workflows" group for better organization of documentation.
- Removed the outdated `agenticrouting.mdx` documentation file to streamline content.

This commit enhances the overall structure and readability of the autonomous agent system while improving documentation organization.
2025-01-13 12:24:51 +00:00
276 changed files with 28439 additions and 1375 deletions

No files matched your search

+434 -443
View File
@@ -20,7 +20,7 @@
</div>
PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human–agent collaboration.
PraisonAI is a production-ready Multi-AI Agents framework with self-reflection, designed to create AI Agents to automate and solve problems ranging from simple tasks to complex challenges. By integrating PraisonAI Agents, AutoGen, and CrewAI into a low-code solution, it streamlines the building and management of multi-agent LLM systems, emphasising simplicity, customisation, and effective human-agent collaboration.
<div align="center">
<a href="https://docs.praison.ai">
@@ -37,35 +37,24 @@ PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application
- 🧠 Reasoning AI Agents
- 👁️ Multi Modal AI Agents
- 🤝 Multi Agent Collaboration
- ⚡ AI Agent Workflow
- 🔄 Use CrewAI or AutoGen Framework
- 🎭 AI Agent Workflow
- 📚 Add Custom Knowledge
- 🧠 Agents with Short and Long Term Memory
- 📄 Chat with PDF Agents
- 💻 Code Interpreter Agents
- 📚 RAG Agents
- 🤔 Async & Parallel Processing
- 🔄 Auto Agents
- 🔢 Math Agents
- 🎯 Structured Output Agents
- 🔗 LangChain Integrated Agents
- 📞 Callback Agents
- 🤏 Mini AI Agents
- 🛠️ 100+ Custom Tools
- 📄 YAML Configuration
- 💯 100+ LLM Support
- 💻 Chat with ENTIRE Codebase
- 🎨 Interactive UIs
- 📄 YAML-based Configuration
- 🛠️ Custom Tool Integration
- 🔍 Internet Search Capability (using Crawl4AI and Tavily)
- 🖼️ Vision Language Model (VLM) Support
- 🎙️ Real-time Voice Interaction
## Using No Code
### Auto Mode:
```bash
pip install praisonai
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
praisonai --auto create a movie script about Robots in Mars
```
### Initialise Mode:
```bash
pip install praisonai
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
praisonai --init create a movie script about Robots in Mars
praisonai
```
## Using Coding
## Using Code
Light weight package dedicated for coding:
```bash
@@ -76,58 +65,13 @@ pip install praisonaiagents
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
```
### 1. Single Agent
Create app.py file and add the code below:
```python
from praisonaiagents import Agent, Task, PraisonAIAgents
# 1. Create agents
researcher = Agent(
name="Researcher",
role="Senior Research Analyst",
goal="Uncover cutting-edge developments in AI and data science",
backstory="""You are an expert at a technology research group,
skilled in identifying trends and analyzing complex data.""",
verbose=True,
llm="gpt-4o",
markdown=True
)
writer = Agent(
name="Writer",
role="Tech Content Strategist",
goal="Craft compelling content on tech advancements",
backstory="""You are a content strategist known for
making complex tech topics interesting and easy to understand.""",
llm="gpt-4o",
markdown=True
)
# 2. Define Tasks
task1 = Task(
name="research_task",
description="""Analyze 2024's AI advancements.
Find major trends, new technologies, and their effects.""",
expected_output="""A detailed report on 2024 AI advancements""",
agent=researcher
)
task2 = Task(
name="writing_task",
description="""Create a blog post about major AI advancements using the insights you have.
Make it interesting, clear, and suited for tech enthusiasts.
It should be at least 4 paragraphs long.""",
expected_output="A blog post of at least 4 paragraphs",
agent=writer,
)
agents = PraisonAIAgents(
agents=[researcher, writer],
tasks=[task1, task2],
verbose=False,
process="hierarchical",
manager_llm="gpt-4o"
)
result = agents.start()
from praisonaiagents import Agent
agent = Agent(instructions="Your are a helpful AI assistant")
agent.start("Write a movie script about a robot in Mars")
```
Run:
@@ -135,6 +79,381 @@ Run:
python app.py
```
### 2. Multi Agents
Create app.py file and add the code below:
```python
from praisonaiagents import Agent, PraisonAIAgents
research_agent = Agent(instructions="Research about AI")
summarise_agent = Agent(instructions="Summarise research agent's findings")
agents = PraisonAIAgents(agents=[research_agent, summarise_agent])
agents.start()
```
Run:
```bash
python app.py
```
## Using No Code
### Auto Mode:
```bash
pip install praisonai
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
praisonai --auto create a movie script about Robots in Mars
```
## AI Agents Flow
```mermaid
graph LR
%% Define the main flow
Start([▶ Start]) --> Agent1
Agent1 --> Process[⚙ Process]
Process --> Agent2
Agent2 --> Output([✓ Output])
Process -.-> Agent1
%% Define subgraphs for agents and their tasks
subgraph Agent1[ ]
Task1[📋 Task]
AgentIcon1[🤖 AI Agent]
Tools1[🔧 Tools]
Task1 --- AgentIcon1
AgentIcon1 --- Tools1
end
subgraph Agent2[ ]
Task2[📋 Task]
AgentIcon2[🤖 AI Agent]
Tools2[🔧 Tools]
Task2 --- AgentIcon2
AgentIcon2 --- Tools2
end
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
classDef tools fill:#2E8B57,stroke:#7C90A0,color:#fff
classDef transparent fill:none,stroke:none
class Start,Output,Task1,Task2 input
class Process,AgentIcon1,AgentIcon2 process
class Tools1,Tools2 tools
class Agent1,Agent2 transparent
```
## AI Agents with Tools
Create AI agents that can use tools to interact with external systems and perform actions.
```mermaid
flowchart TB
subgraph Tools
direction TB
T3[Internet Search]
T1[Code Execution]
T2[Formatting]
end
Input[Input] ---> Agents
subgraph Agents
direction LR
A1[Agent 1]
A2[Agent 2]
A3[Agent 3]
end
Agents ---> Output[Output]
T3 --> A1
T1 --> A2
T2 --> A3
style Tools fill:#189AB4,color:#fff
style Agents fill:#8B0000,color:#fff
style Input fill:#8B0000,color:#fff
style Output fill:#8B0000,color:#fff
```
## AI Agents with Memory
Create AI agents with memory capabilities for maintaining context and information across tasks.
```mermaid
flowchart TB
subgraph Memory
direction TB
STM[Short Term]
LTM[Long Term]
end
subgraph Store
direction TB
DB[(Vector DB)]
end
Input[Input] ---> Agents
subgraph Agents
direction LR
A1[Agent 1]
A2[Agent 2]
A3[Agent 3]
end
Agents ---> Output[Output]
Memory <--> Store
Store <--> A1
Store <--> A2
Store <--> A3
style Memory fill:#189AB4,color:#fff
style Store fill:#2E8B57,color:#fff
style Agents fill:#8B0000,color:#fff
style Input fill:#8B0000,color:#fff
style Output fill:#8B0000,color:#fff
```
## AI Agents with Different Processes
### Sequential Process
The simplest form of task execution where tasks are performed one after another.
```mermaid
graph LR
Input[Input] --> A1
subgraph Agents
direction LR
A1[Agent 1] --> A2[Agent 2] --> A3[Agent 3]
end
A3 --> Output[Output]
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
classDef transparent fill:none,stroke:none
class Input,Output input
class A1,A2,A3 process
class Agents transparent
```
### Hierarchical Process
Uses a manager agent to coordinate task execution and agent assignments.
```mermaid
graph TB
Input[Input] --> Manager
subgraph Agents
Manager[Manager Agent]
subgraph Workers
direction LR
W1[Worker 1]
W2[Worker 2]
W3[Worker 3]
end
Manager --> W1
Manager --> W2
Manager --> W3
end
W1 --> Manager
W2 --> Manager
W3 --> Manager
Manager --> Output[Output]
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
classDef transparent fill:none,stroke:none
class Input,Output input
class Manager,W1,W2,W3 process
class Agents,Workers transparent
```
### Workflow Process
Advanced process type supporting complex task relationships and conditional execution.
```mermaid
graph LR
Input[Input] --> Start
subgraph Workflow
direction LR
Start[Start] --> C1{Condition}
C1 --> |Yes| A1[Agent 1]
C1 --> |No| A2[Agent 2]
A1 --> Join
A2 --> Join
Join --> A3[Agent 3]
end
A3 --> Output[Output]
classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
classDef decision fill:#2E8B57,stroke:#7C90A0,color:#fff
classDef transparent fill:none,stroke:none
class Input,Output input
class Start,A1,A2,A3,Join process
class C1 decision
class Workflow transparent
```
#### Agentic Routing Workflow
Create AI agents that can dynamically route tasks to specialized LLM instances.
```mermaid
flowchart LR
In[In] --> Router[LLM Call Router]
Router --> LLM1[LLM Call 1]
Router --> LLM2[LLM Call 2]
Router --> LLM3[LLM Call 3]
LLM1 --> Out[Out]
LLM2 --> Out
LLM3 --> Out
style In fill:#8B0000,color:#fff
style Router fill:#2E8B57,color:#fff
style LLM1 fill:#2E8B57,color:#fff
style LLM2 fill:#2E8B57,color:#fff
style LLM3 fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
#### Agentic Orchestrator Worker
Create AI agents that orchestrate and distribute tasks among specialized workers.
```mermaid
flowchart LR
In[In] --> Router[LLM Call Router]
Router --> LLM1[LLM Call 1]
Router --> LLM2[LLM Call 2]
Router --> LLM3[LLM Call 3]
LLM1 --> Synthesizer[Synthesizer]
LLM2 --> Synthesizer
LLM3 --> Synthesizer
Synthesizer --> Out[Out]
style In fill:#8B0000,color:#fff
style Router fill:#2E8B57,color:#fff
style LLM1 fill:#2E8B57,color:#fff
style LLM2 fill:#2E8B57,color:#fff
style LLM3 fill:#2E8B57,color:#fff
style Synthesizer fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
#### Agentic Autonomous Workflow
Create AI agents that can autonomously monitor, act, and adapt based on environment feedback.
```mermaid
flowchart LR
Human[Human] <--> LLM[LLM Call]
LLM -->|ACTION| Environment[Environment]
Environment -->|FEEDBACK| LLM
LLM --> Stop[Stop]
style Human fill:#8B0000,color:#fff
style LLM fill:#2E8B57,color:#fff
style Environment fill:#8B0000,color:#fff
style Stop fill:#333,color:#fff
```
#### Agentic Parallelization
Create AI agents that can execute tasks in parallel for improved performance.
```mermaid
flowchart LR
In[In] --> LLM2[LLM Call 2]
In --> LLM1[LLM Call 1]
In --> LLM3[LLM Call 3]
LLM1 --> Aggregator[Aggregator]
LLM2 --> Aggregator
LLM3 --> Aggregator
Aggregator --> Out[Out]
style In fill:#8B0000,color:#fff
style LLM1 fill:#2E8B57,color:#fff
style LLM2 fill:#2E8B57,color:#fff
style LLM3 fill:#2E8B57,color:#fff
style Aggregator fill:#fff,color:#000
style Out fill:#8B0000,color:#fff
```
#### Agentic Prompt Chaining
Create AI agents with sequential prompt chaining for complex workflows.
```mermaid
flowchart LR
In[In] --> LLM1[LLM Call 1] --> Gate{Gate}
Gate -->|Pass| LLM2[LLM Call 2] -->|Output 2| LLM3[LLM Call 3] --> Out[Out]
Gate -->|Fail| Exit[Exit]
style In fill:#8B0000,color:#fff
style LLM1 fill:#2E8B57,color:#fff
style LLM2 fill:#2E8B57,color:#fff
style LLM3 fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
style Exit fill:#8B0000,color:#fff
```
#### Agentic Evaluator Optimizer
Create AI agents that can generate and optimize solutions through iterative feedback.
```mermaid
flowchart LR
In[In] --> Generator[LLM Call Generator]
Generator -->|SOLUTION| Evaluator[LLM Call Evaluator] -->|ACCEPTED| Out[Out]
Evaluator -->|REJECTED + FEEDBACK| Generator
style In fill:#8B0000,color:#fff
style Generator fill:#2E8B57,color:#fff
style Evaluator fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
#### Repetitive Agents
Create AI agents that can efficiently handle repetitive tasks through automated loops.
```mermaid
flowchart LR
In[Input] --> LoopAgent[("Looping Agent")]
LoopAgent --> Task[Task]
Task --> |Next iteration| LoopAgent
Task --> |Done| Out[Output]
style In fill:#8B0000,color:#fff
style LoopAgent fill:#2E8B57,color:#fff,shape:circle
style Task fill:#2E8B57,color:#fff
style Out fill:#8B0000,color:#fff
```
## Adding Models
<div align="center">
<a href="https://docs.praison.ai/models">
<p align="center">
<img src="https://img.shields.io/badge/%F0%9F%93%9A_Models-Visit_docs.praison.ai-blue?style=for-the-badge&logo=bookstack&logoColor=white" alt="Models" />
</p>
</a>
</div>
## Ollama Integration
```bash
export OPENAI_BASE_URL=http://localhost:11434/v1
@@ -147,267 +466,16 @@ export OPENAI_API_KEY=xxxxxxxxxxx
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
```
## Logging
```bash
export LOGLEVEL=info
```
Advanced logging:
```bash
export LOGLEVEL=debug
```
<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="docs/images/architecture-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="docs/images/architecture-light.png" />
<img alt="PraisonAI Architecture" src="docs/images/architecture-light.png" />
</picture>
</div>
## Different User Interfaces:
| Interface | Description | URL |
|---|---|---|
| **UI** | Multi Agents such as CrewAI or AutoGen | [https://docs.praison.ai/ui/ui](https://docs.praison.ai/ui/ui) |
| **Chat** | Chat with 100+ LLMs, single AI Agent | [https://docs.praison.ai/ui/chat](https://docs.praison.ai/ui/chat) |
| **Code** | Chat with entire Codebase, single AI Agent | [https://docs.praison.ai/ui/code](https://docs.praison.ai/ui/code) |
| **Realtime** | Real-time voice interaction with AI | [https://docs.praison.ai/ui/realtime](https://docs.praison.ai/ui/realtime) |
| Other Features | Description | Docs |
|---|---|---|
| **Train** | Fine-tune LLMs using your custom data | [https://docs.praison.ai/train](https://docs.praison.ai/train) |
## Google Colab Multi Agents
| | Cookbook | Open in Colab |
| ------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Basic | PraisonAI | <a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-googlecolab.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" /></a> |
| Include Tools | PraisonAI Tools | <a target="_blank" href="https://colab.research.google.com/github/MervinPraison/PraisonAI/blob/main/cookbooks/praisonai-tools-googlecolab.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab" /></a> |
## Installation Options
### Using pip
```bash
pip install praisonai
```
### Framework-specific Installation
```bash
# Install with CrewAI support
pip install "praisonai[crewai]"
# Install with AutoGen support
pip install "praisonai[autogen]"
# Install with both frameworks
pip install "praisonai[crewai,autogen]"
```
### UI and Additional Features
```bash
# Install UI support
pip install "praisonai[ui]"
# Install Chat interface
pip install "praisonai[chat]"
# Install Code interface
pip install "praisonai[code]"
# Install Realtime voice interaction
pip install "praisonai[realtime]"
# Install Call feature
pip install "praisonai[call]"
```
## Quick Start
```bash
# Set your OpenAI API key
export OPENAI_API_KEY="Enter your API key"
# Initialize with CrewAI (default)
praisonai --init "create a movie script about dog in moon"
# Or initialize with AutoGen
praisonai --framework autogen --init "create a movie script about dog in moon"
# Run the agents
praisonai
```
## Full Automatic Mode
```bash
# With CrewAI (default)
praisonai --auto "create a movie script about Dog in Moon"
# With AutoGen
praisonai --framework autogen --auto "create a movie script about Dog in Moon"
```
## Framework-specific Features
### CrewAI
When installing with `pip install "praisonai[crewai]"`, you get:
- CrewAI framework support
- PraisonAI tools integration
- Task delegation capabilities
- Sequential and parallel task execution
### AutoGen
When installing with `pip install "praisonai[autogen]"`, you get:
- AutoGen framework support
- PraisonAI tools integration
- Multi-agent conversation capabilities
- Code execution environment
## TL;DR Multi Agents
```bash
pip install praisonai
export OPENAI_API_KEY="Enter your API key"
praisonai --init create a movie script about dog in moon
praisonai
```
## Table of Contents
- [Installation](#installation)
- [Initialise](#initialise)
- [Run](#run)
- [Full Automatic Mode](#full-automatic-mode)
- [User Interface](#user-interface)
- [Praison AI Chat](#praison-ai-chat)
- [Create Custom Tools](#create-custom-tools)
- [Agents Playbook](#agents-playbook)
- [Include praisonai package in your project](#include-praisonai-package-in-your-project)
- [Commands to Install Dev Dependencies](#commands-to-install-dependencies)
- [Other Models](#other-models)
- [Contributing](#contributing)
- [Star History](#star-history)
## Installation Multi Agents
```bash
pip install praisonai
```
## Initialise
```bash
export OPENAI_API_KEY="Enter your API key"
```
Generate your OPENAI API KEY from here: https://platform.openai.com/api-keys
Note: You can use other providers such as Ollama, Mistral ... etc. Details are provided at the bottom.
```bash
praisonai --init create a movie script about dog in moon
```
This will automatically create agents.yaml file in the current directory.
### To initialise with a specific agent framework (Optional):
```bash
praisonai --framework autogen --init create movie script about cat in mars
```
## Run
```bash
praisonai
```
or
```bash
python -m praisonai
```
### Specify the agent framework (Optional):
```bash
praisonai --framework autogen
```
### Full Automatic Mode
```bash
praisonai --auto create a movie script about Dog in Moon
```
## User Interface
## PraisonAI User Interfaces:
| Interface | Description | URL |
| --------- | ------------------------------------------ | --------------------------------------------------------------------- |
| **UI** | Multi Agents such as CrewAI or AutoGen | [https://docs.praisonai.com/ui/ui](https://docs.praison.ai/ui/ui) |
| **Chat** | Chat with 100+ LLMs, single AI Agent | [https://docs.praisonai.com/ui/chat](https://docs.praison.ai/ui/chat) |
| **Code** | Chat with entire Codebase, single AI Agent | [https://docs.praisonai.com/ui/code](https://docs.praison.ai/ui/code) |
```bash
pip install -U "praisonai[ui]"
export OPENAI_API_KEY="Enter your API key"
chainlit create-secret
export CHAINLIT_AUTH_SECRET=xxxxxxxx
praisonai ui
```
or
```
python -m praisonai ui
```
## Praison AI Chat
- https://docs.praison.ai/chat/
```bash
pip install "praisonai[chat]"
export OPENAI_API_KEY="Enter your API key"
praisonai chat
```
### Internet Search
Praison AI Chat and Praison AI Code now includes internet search capabilities using Crawl4AI and Tavily, allowing you to retrieve up-to-date information during your conversations.
### Vision Language Model Support
You can now upload images and ask questions based on them using Vision Language Models. This feature enables visual understanding and analysis within your chat sessions.
## Praison AI Code
```bash
pip install "praisonai[code]"
export OPENAI_API_KEY="Enter your API key"
praisonai code
```
### Internet Search
Praison AI Code also includes internet search functionality, enabling you to find relevant code snippets and programming information online.
## Create Custom Tools
- https://docs.praison.ai/tools/custom/
## No Code Options
## Agents Playbook
### Simple Playbook Example
Create `agents.yaml` file and add the code below:
```yaml
framework: crewai
framework: praisonai
topic: Artificial Intelligence
roles:
screenwriter:
@@ -420,62 +488,25 @@ roles:
expected_output: "Complete script ready for production."
```
*To run the playbook:*
```bash
praisonai agents.yaml
```
## Use 100+ Models
- https://docs.praison.ai/models/
<div align="center">
<a href="https://docs.praison.ai">
<p align="center">
<img src="https://img.shields.io/badge/📚_Documentation-Visit_docs.praison.ai-blue?style=for-the-badge&logo=bookstack&logoColor=white" alt="Documentation" />
</p>
</a>
</div>
## Include praisonai package in your project
## Development:
- https://docs.praison.ai/developers/wrapper
- https://docs.praison.ai/developers/wrapper-tools/
## Option 1: Using RAW YAML
```python
from praisonai import PraisonAI
# Example agent_yaml content
agent_yaml = """
framework: "crewai"
topic: "Space Exploration"
roles:
astronomer:
role: "Space Researcher"
goal: "Discover new insights about {topic}"
backstory: "You are a curious and dedicated astronomer with a passion for unraveling the mysteries of the cosmos."
tasks:
investigate_exoplanets:
description: "Research and compile information about exoplanets discovered in the last decade."
expected_output: "A summarized report on exoplanet discoveries, including their size, potential habitability, and distance from Earth."
"""
# Create a PraisonAI instance with the agent_yaml content
praisonai = PraisonAI(agent_yaml=agent_yaml)
# Run PraisonAI
result = praisonai.run()
# Print the result
print(result)
```
## Option 2: Using separate agents.yaml file
Note: Please create agents.yaml file before hand.
```python
from praisonai import PraisonAI
def basic(): # Basic Mode
praisonai = PraisonAI(agent_file="agents.yaml")
praisonai.run()
if __name__ == "__main__":
basic()
```
## Commands to Install Dependencies:
Below is used for development only.
### Using uv
```bash
@@ -500,18 +531,33 @@ uv pip install -r pyproject.toml --extra "crewai,autogen"
- Submit a pull request via GitHub's web interface.
- Await feedback from project maintainers.
## Other Features
- 🔄 Use CrewAI or AutoGen Framework
- 💻 Chat with ENTIRE Codebase
- 🎨 Interactive UIs
- 📄 YAML-based Configuration
- 🛠️ Custom Tool Integration
- 🔍 Internet Search Capability (using Crawl4AI and Tavily)
- 🖼️ Vision Language Model (VLM) Support
- 🎙️ Real-time Voice Interaction
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=MervinPraison/PraisonAI&type=Date)](https://docs.praison.ai)
## License
Praison AI is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.
## Video Tutorials
| Topic | Video |
|-------|--------|
| AI Agents with Self Reflection | [![Self Reflection](https://img.youtube.com/vi/vLXobEN2Vc8/0.jpg)](https://www.youtube.com/watch?v=vLXobEN2Vc8) |
| AI Agents with Reasoning | [![Reasoning](https://img.youtube.com/vi/KNDVWGN3TpM/0.jpg)](https://www.youtube.com/watch?v=KNDVWGN3TpM) |
| Multimodal AI Agents | [![Multimodal](https://img.youtube.com/vi/hjAWmUT1qqY/0.jpg)](https://www.youtube.com/watch?v=hjAWmUT1qqY) |
| AI Agents Workflow | [![Workflow](https://img.youtube.com/vi/yWTH44QPl2A/0.jpg)](https://www.youtube.com/watch?v=yWTH44QPl2A) |
| Async AI Agents | [![Async](https://img.youtube.com/vi/VhVQfgo00LE/0.jpg)](https://www.youtube.com/watch?v=VhVQfgo00LE) |
| Mini AI Agents | [![Mini](https://img.youtube.com/vi/OkvYp5aAGSg/0.jpg)](https://www.youtube.com/watch?v=OkvYp5aAGSg) |
| AI Agents with Memory | [![Memory](https://img.youtube.com/vi/1hVfVxvPnnQ/0.jpg)](https://www.youtube.com/watch?v=1hVfVxvPnnQ) |
| Repetitive Agents | [![Repetitive](https://img.youtube.com/vi/dAYGxsjDOPg/0.jpg)](https://www.youtube.com/watch?v=dAYGxsjDOPg) |
| Introduction | [![Introduction](https://img.youtube.com/vi/Fn1lQjC0GO0/0.jpg)](https://www.youtube.com/watch?v=Fn1lQjC0GO0) |
| Tools Overview | [![Tools Overview](https://img.youtube.com/vi/XaQRgRpV7jo/0.jpg)](https://www.youtube.com/watch?v=XaQRgRpV7jo) |
| Custom Tools | [![Custom Tools](https://img.youtube.com/vi/JSU2Rndh06c/0.jpg)](https://www.youtube.com/watch?v=JSU2Rndh06c) |
@@ -525,58 +571,3 @@ Praison AI is an open-sourced software licensed under the **[MIT license](https:
| Realtime Voice Interface | [![Realtime](https://img.youtube.com/vi/frRHfevTCSw/0.jpg)](https://www.youtube.com/watch?v=frRHfevTCSw) |
| Call Interface | [![Call](https://img.youtube.com/vi/m1cwrUG2iAk/0.jpg)](https://www.youtube.com/watch?v=m1cwrUG2iAk) |
## License
Praison AI is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.
## Local Docker Development with Live Reload
To facilitate local development with live reload, you can use Docker. Follow the steps below:
1. **Create a `Dockerfile.dev`**:
```dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install flask praisonai==2.0.18 watchdog
EXPOSE 5555
ENV FLASK_ENV=development
CMD ["flask", "run", "--host=0.0.0.0"]
```
2. **Create a `docker-compose.yml`**:
```yaml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/app
ports:
- "5555:5555"
environment:
FLASK_ENV: development
command: flask run --host=0.0.0.0
watch:
image: alpine:latest
volumes:
- .:/app
command: sh -c "apk add --no-cache inotify-tools && while inotifywait -r -e modify,create,delete /app; do kill -HUP 1; done"
```
3. **Run Docker Compose**:
```bash
docker-compose up
```
This setup will allow you to develop locally with live reload, making it easier to test and iterate on your code.
+43
View File
@@ -0,0 +1,43 @@
FROM mcr.microsoft.com/devcontainers/python:3.11
# Prevent apt from showing prompts
ENV DEBIAN_FRONTEND=noninteractive
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Create a non-root user
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# Create the user and group only if they don't exist
RUN if ! getent group $USER_GID > /dev/null 2>&1; then \
groupadd --gid $USER_GID $USERNAME; \
fi && \
if ! getent passwd $USER_UID > /dev/null 2>&1; then \
useradd --uid $USER_UID --gid $USER_GID -m $USERNAME; \
fi && \
apt-get update && \
apt-get install -y sudo && \
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME && \
chmod 0440 /etc/sudoers.d/$USERNAME
# Set Python environment variables
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
# Install Python dependencies
COPY requirements.txt /tmp/pip-tmp/
RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
&& rm -rf /tmp/pip-tmp
# Switch to non-root user
USER $USERNAME
# Set the default shell to bash
ENV SHELL=/bin/bash
+36
View File
@@ -0,0 +1,36 @@
{
"name": "PraisonAI Development",
"dockerFile": "Dockerfile",
"context": "..",
"runArgs": [
"--env-file",
".env",
"--network=host"
],
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.black-formatter",
"ms-toolsai.jupyter",
"yzhang.markdown-all-in-one",
"streetsidesoftware.code-spell-checker"
],
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.formatting.provider": "black",
"editor.formatOnSave": true,
"editor.rulers": [88],
"files.trimTrailingWhitespace": true
}
}
},
"remoteUser": "vscode",
"updateRemoteUserUID": false,
"forwardPorts": [],
"appPort": ["56040:56040"],
"overrideCommand": false,
"init": true
}
+45
View File
@@ -0,0 +1,45 @@
from praisonaiagents import Agent
# Detailed LLM configuration
llm_config = {
"model": "gemini/gemini-1.5-flash-latest", # Model name without provider prefix
# Core settings
"temperature": 0.7, # Controls randomness (like temperature)
"timeout": 30, # Timeout in seconds
"top_p": 0.9, # Nucleus sampling parameter
"max_tokens": 1000, # Max tokens in response
# Advanced parameters
"presence_penalty": 0.1, # Penalize repetition of topics (-2.0 to 2.0)
"frequency_penalty": 0.1, # Penalize token repetition (-2.0 to 2.0)
# API settings (optional)
"api_key": None, # Your API key (or use environment variable)
"base_url": None, # Custom API endpoint if needed
# Response formatting
"response_format": { # Force specific response format
"type": "text" # Options: "text", "json_object"
},
# Additional controls
"seed": 42, # For reproducible responses
"stop_phrases": ["##", "END"], # Custom stop sequences
}
agent = Agent(
instructions="You are a helpful Assistant specialized in scientific explanations. "
"Provide clear, accurate, and engaging responses.",
llm=llm_config, # Pass the detailed configuration
verbose=True, # Enable detailed output
markdown=True, # Format responses in markdown
self_reflect=True, # Enable self-reflection
max_reflect=3, # Maximum reflection iterations
min_reflect=1 # Minimum reflection iterations
)
# Test the agent
response = agent.start("Why is the sky blue? Please explain in simple terms.")
print(response)
+18
View File
@@ -0,0 +1,18 @@
import asyncio
from praisonaiagents import Agent
async def main():
agent = Agent(
instructions="You are a helpful assistant",
llm="gemini/gemini-1.5-flash-8b",
self_reflect=True,
verbose=True
)
# Use achat instead of start/chat for async operation
response = await agent.achat("Why sky is Blue in 1000 words?")
print(response)
if __name__ == "__main__":
# Run the async main function
asyncio.run(main())
+10
View File
@@ -0,0 +1,10 @@
from praisonaiagents import Agent
agent = Agent(
instructions="You are a helpful assistant",
llm="gemini/gemini-1.5-flash-8b",
self_reflect=True,
verbose=True
)
agent.start("Why sky is Blue?")
+127
View File
@@ -0,0 +1,127 @@
import asyncio
import logging
from typing import List, Dict, Any
from pydantic import BaseModel
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
from tavily import AsyncTavilyClient
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
llm_config = {
"model": "gemini/gemini-1.5-flash-8b",
"response_format": {
"type": "text"
}
}
# Define output model
class SearchResult(BaseModel):
query: str
results: List[Dict[str, Any]]
total_results: int
# Define Tavily search tool
async def tavily_search(query) -> Dict[str, Any]:
"""Async Tavily search tool that returns structured results"""
client = AsyncTavilyClient()
try:
results = await client.search(query)
print(f"Tavily search results: {results}")
return {
"query": query,
"results": results.get("results", []),
"total_results": len(results.get("results", []))
}
except Exception as e:
logging.error(f"Tavily search error: {e}")
return {
"query": query,
"results": [],
"total_results": 0
}
# Define async callback
async def async_callback(output: TaskOutput):
if output.output_format == "JSON":
logging.info(f"Search completed: {output.json_dict.get('query', '')}")
elif output.output_format == "Pydantic":
logging.info(f"Search completed: {output.pydantic}")
async def run_parallel_searches():
# Create search agent with direct tool function
search_agent = Agent(
name="TavilySearchAgent",
role="Search Specialist",
goal="Perform parallel web searches with high accuracy",
backstory="Expert in web search and information retrieval",
tools=[tavily_search],
llm=llm_config
)
# Create summary agent
summary_agent = Agent(
name="ContentSynthesizer",
role="Research Analyst",
goal="Synthesize search results into coherent insights",
backstory="Expert in analyzing and combining multiple sources of information",
llm=llm_config
)
# Define search topics
search_topics = [
"Latest AI breakthroughs 2024",
"Future of quantum computing",
"Advancements in robotics"
]
# Create parallel search tasks
search_tasks = [
Task(
name=f"search_{i}",
description=f"Search and analyze: {topic}",
expected_output="Comprehensive search results with analysis",
agent=search_agent,
async_execution=True,
callback=async_callback,
) for i, topic in enumerate(search_topics)
]
# Create summary task
summary_task = Task(
name="synthesize_results",
description="Create a comprehensive summary of all search findings",
expected_output="Synthesized insights from all searches",
agent=summary_agent,
async_execution=False,
context=search_tasks
)
# Initialize agents manager
agents = PraisonAIAgents(
agents=[search_agent, summary_agent],
tasks=search_tasks + [summary_task]
)
# Execute tasks
results = await agents.astart()
return {
"search_results": [str(results["task_results"][i]) for i in range(len(search_tasks))],
"summary": str(results["task_results"][summary_task.id]),
"topics": search_topics
}
async def main():
try:
logging.info("Starting parallel Tavily searches...")
results = await run_parallel_searches()
logging.info("Search process completed successfully")
print("\nResults Summary:")
for topic, result in zip(results["topics"], results["search_results"]):
print(f"\n{topic}:\n{result}")
print(f"\nFinal Summary:\n{results['summary']}")
except Exception as e:
logging.error(f"Error in execution: {e}")
if __name__ == "__main__":
asyncio.run(main())
+119
View File
@@ -0,0 +1,119 @@
import asyncio
import logging
from typing import List, Dict, Any
from pydantic import BaseModel
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
from tavily import AsyncTavilyClient
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Define output model
class SearchResult(BaseModel):
query: str
results: List[Dict[str, Any]]
total_results: int
# Define Tavily search tool
async def tavily_search(query: str) -> Dict[str, Any]:
"""Async Tavily search tool that returns structured results"""
client = AsyncTavilyClient()
try:
results = await client.search(query)
print(f"Tavily search results: {results}")
return {
"query": query,
"results": results.get("results", []),
"total_results": len(results.get("results", []))
}
except Exception as e:
logging.error(f"Tavily search error: {e}")
return {
"query": query,
"results": [],
"total_results": 0
}
# Define async callback
async def async_callback(output: TaskOutput):
if output.output_format == "JSON":
logging.info(f"Search completed: {output.json_dict.get('query', '')}")
elif output.output_format == "Pydantic":
logging.info(f"Search completed: {output.pydantic}")
async def run_parallel_searches():
# Create search agent with direct tool function
search_agent = Agent(
name="TavilySearchAgent",
role="Search Specialist",
goal="Perform parallel web searches with high accuracy",
backstory="Expert in web search and information retrieval",
tools=[tavily_search]
)
# Create summary agent
summary_agent = Agent(
name="ContentSynthesizer",
role="Research Analyst",
goal="Synthesize search results into coherent insights",
backstory="Expert in analyzing and combining multiple sources of information"
)
# Define search topics
search_topics = [
"Latest AI breakthroughs 2024",
"Future of quantum computing",
"Advancements in robotics"
]
# Create parallel search tasks
search_tasks = [
Task(
name=f"search_{i}",
description=f"Search and analyze: {topic}",
expected_output="Comprehensive search results with analysis",
agent=search_agent,
async_execution=True,
callback=async_callback,
output_json=SearchResult
) for i, topic in enumerate(search_topics)
]
# Create summary task
summary_task = Task(
name="synthesize_results",
description="Create a comprehensive summary of all search findings",
expected_output="Synthesized insights from all searches",
agent=summary_agent,
async_execution=False,
context=search_tasks
)
# Initialize agents manager
agents = PraisonAIAgents(
agents=[search_agent, summary_agent],
tasks=search_tasks + [summary_task]
)
# Execute tasks
results = await agents.astart()
return {
"search_results": [str(results["task_results"][i]) for i in range(len(search_tasks))],
"summary": str(results["task_results"][summary_task.id]),
"topics": search_topics
}
async def main():
try:
logging.info("Starting parallel Tavily searches...")
results = await run_parallel_searches()
logging.info("Search process completed successfully")
print("\nResults Summary:")
for topic, result in zip(results["topics"], results["search_results"]):
print(f"\n{topic}:\n{result}")
print(f"\nFinal Summary:\n{results['summary']}")
except Exception as e:
logging.error(f"Error in execution: {e}")
if __name__ == "__main__":
asyncio.run(main())
+24 -3
View File
@@ -12,6 +12,14 @@ from praisonaiagents.main import (
)
from duckduckgo_search import DDGS
from pydantic import BaseModel
import logging
# Configure logging with more detail
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(name)s:%(lineno)d - %(message)s'
)
logger = logging.getLogger(__name__)
console = Console()
@@ -48,7 +56,7 @@ def sync_search_tool(query: str) -> List[Dict]:
error_logs.append(error_msg)
return []
async def async_search_tool(query: str) -> List[Dict]:
async def async_search_tool(query: str) -> Dict:
"""
Asynchronous search using DuckDuckGo.
Args:
@@ -56,23 +64,36 @@ async def async_search_tool(query: str) -> List[Dict]:
Returns:
list: Search results
"""
logger.debug(f"Starting async_search_tool with query: {query}")
display_tool_call(f"Running async search for: {query}", console)
await asyncio.sleep(1) # Simulate network delay
try:
results = []
ddgs = DDGS()
logger.debug("Performing DuckDuckGo search")
for result in ddgs.text(keywords=query, max_results=5):
results.append({
"title": result.get("title", ""),
"url": result.get("href", ""),
"snippet": result.get("body", "")
})
return results
logger.debug(f"Search completed, found {len(results)} results")
return {
"query": query,
"results": results,
"total_results": len(results)
}
except Exception as e:
error_msg = f"Error during async search: {e}"
logger.error(f"Error in async_search_tool: {e}", exc_info=True)
display_error(error_msg, console)
error_logs.append(error_msg)
return []
return {
"query": query,
"results": [],
"total_results": 0
}
# 3. Define both sync and async callbacks
def sync_callback(output: TaskOutput):
+7
View File
@@ -4,6 +4,13 @@ from typing import List, Dict
from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput
from duckduckgo_search import DDGS
from pydantic import BaseModel
import logging
# Configure logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s'
)
# 1. Define output model for structured results
class SearchResult(BaseModel):
+88 -33
View File
@@ -1,59 +1,114 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
def get_environment_feedback():
"""Simulates environment feedback based on time"""
def get_environment_state():
"""Simulates getting current environment state"""
current_time = int(time.time())
states = ["normal", "critical", "optimal"]
state = states[current_time % 3]
print(f"Environment state: {state}")
return state
def perform_action(state: str):
"""Simulates performing an action based on state"""
actions = {
"normal": "maintain",
"critical": "fix",
"optimal": "enhance"
}
action = actions.get(state, "observe")
print(f"Performing action: {action} for state: {state}")
return action
def get_feedback():
"""Simulates environment feedback"""
current_time = int(time.time())
feedback = "positive" if current_time % 2 == 0 else "negative"
print(f"Environment feedback: {feedback}")
print(f"Feedback received: {feedback}")
return feedback
# Create autonomous agent
autonomous_agent = Agent(
name="Autonomous Agent",
role="Environment interactor",
goal="Interact with environment and learn from feedback",
instructions="Take actions based on environment state and adapt from feedback",
tools=[get_environment_feedback]
# Create specialized agents
llm_caller = Agent(
name="Environment Monitor",
role="State analyzer",
goal="Monitor environment and analyze state",
instructions="Check environment state and provide analysis",
tools=[get_environment_state]
)
# Create tasks for the autonomous loop
action_task = Task(
name="take_action",
description="Analyze environment and take appropriate action",
expected_output="Action taken and its rationale",
agent=autonomous_agent,
action_agent = Agent(
name="Action Executor",
role="Action performer",
goal="Execute appropriate actions based on state",
instructions="Determine and perform actions based on environment state",
tools=[perform_action]
)
feedback_agent = Agent(
name="Feedback Processor",
role="Feedback analyzer",
goal="Process environment feedback and adapt strategy",
instructions="Analyze feedback and provide adaptation recommendations",
tools=[get_feedback]
)
# Create tasks for autonomous workflow
monitor_task = Task(
name="monitor_environment",
description="Monitor and analyze environment state",
expected_output="Current environment state analysis",
agent=llm_caller,
is_start=True,
task_type="decision",
next_tasks=["process_feedback"],
next_tasks=["execute_action"],
condition={
"continue": ["process_feedback"], # Continue to get feedback
"stop": [""] # Stop when goal is achieved
"normal": ["execute_action"],
"critical": ["execute_action"],
"optimal": "exit"
}
)
action_task = Task(
name="execute_action",
description="Execute appropriate action based on state",
expected_output="Action execution result",
agent=action_agent,
next_tasks=["process_feedback"]
)
feedback_task = Task(
name="process_feedback",
description="Process environment feedback and adapt strategy",
expected_output="Adapted strategy based on feedback",
agent=autonomous_agent,
next_tasks=["take_action"],
context=[action_task] # Access to previous action for learning
description="Process feedback and adapt strategy",
expected_output="Strategy adaptation based on feedback",
agent=feedback_agent,
next_tasks=["monitor_environment"], # Create feedback loop
context=[monitor_task, action_task] # Access to previous states and actions
)
# Create workflow manager
workflow = PraisonAIAgents(
agents=[autonomous_agent],
tasks=[action_task, feedback_task],
agents=[llm_caller, action_agent, feedback_agent],
tasks=[monitor_task, action_task, feedback_task],
process="workflow",
verbose=True
)
# Run autonomous workflow
results = workflow.start()
def main():
print("\nStarting Autonomous Agent Workflow...")
print("=" * 50)
# Run autonomous workflow
results = workflow.start()
# Print results
print("\nAutonomous Agent Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
task_name = result.description
print(f"\nTask: {task_name}")
print(f"Result: {result.raw}")
print("-" * 50)
# Print results
print("\nAutonomous Agent Results:")
for task_id, result in results["task_results"].items():
if result:
print(f"Task {task_id}: {result.raw}")
if __name__ == "__main__":
main()
+8
View File
@@ -0,0 +1,8 @@
from praisonaiagents import Agent
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-4o-mini"
)
agent.start("Why sky is Blue?")
+14
View File
@@ -0,0 +1,14 @@
from praisonaiagents.knowledge import Chunking
# No heavy imports or initialization happens here
chunking = Chunking(chunker_type='token')
# Chunker is only initialized when first used
chunks = chunking.chunk("Your text here")
# Embedding model is only loaded if using semantic chunking
semantic_chunking = Chunking(chunker_type='recursive')
# Embedding model and chunker are loaded here on first use
semantic_chunks = semantic_chunking.chunk("Your text here")
print(semantic_chunks)
+97
View File
@@ -0,0 +1,97 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
from gitingest import ingest
class CodeMetrics(BaseModel):
category: str
score: int
findings: List[str]
class CodeAnalysisReport(BaseModel):
overall_quality: int
code_metrics: List[CodeMetrics]
architecture_score: int
maintainability_score: int
performance_score: int
security_score: int
test_coverage: int
key_strengths: List[str]
improvement_areas: List[str]
tech_stack: List[str]
recommendations: List[str]
complexity_metrics: Dict[str, int]
best_practices: List[Dict[str, str]]
potential_risks: List[str]
documentation_quality: int
code_analyzer = Agent(
role="Code Analysis Expert",
goal="Provide comprehensive code evaluation and recommendations",
backstory="""Expert code analyst specializing in architecture review,
best practices, and technical debt assessment.""",
verbose=True
)
code_analysis_task = Task(
description="""Analyze code repository and provide structured evaluation:
1. Overall Quality (0-100)
2. Core Metrics Analysis:
- Architecture and Design
- Code Maintainability
- Performance Optimization
- Security Practices
- Test Coverage
3. Technical Assessment:
- Technology Stack Review
- Code Complexity Analysis
- Best Practices Adherence
- Risk Assessment
4. Recommendations:
- Key Improvements
- Architecture Suggestions
- Security Enhancements""",
expected_output="Detailed code analysis report with metrics and recommendations",
agent=code_analyzer,
output_pydantic=CodeAnalysisReport
)
def analyze_code(code_source: str) -> CodeAnalysisReport:
"""
Analyze code from directory path or GitHub URL
"""
# Ingest code content
summary, tree, content = ingest(code_source)
# Concatenate context into structured format
context_text = f"""
CODE REPOSITORY ANALYSIS
=======================
SUMMARY
-------
{summary}
REPOSITORY STRUCTURE
-------------------
{tree}
SOURCE CODE
-----------
{content}
"""
# Initialize and run analysis
agents = PraisonAIAgents(
agents=[code_analyzer],
tasks=[code_analysis_task]
)
return agents.start(context_text)
if __name__ == "__main__":
# Example usage
code_source = "https://github.com/openai/openai-python/tree/main/src/openai/cli/_api/chat" # GitHub URL or local directory
result = analyze_code(code_source)
print(result)
+217
View File
@@ -0,0 +1,217 @@
import streamlit as st
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict, Any
from gitingest import ingest
# Import the same classes and code from code-analysis-agents.py
class CodeMetrics(BaseModel):
category: str
score: int
findings: List[str]
class CodeAnalysisReport(BaseModel):
overall_quality: int
code_metrics: List[CodeMetrics]
architecture_score: int
maintainability_score: int
performance_score: int
security_score: int
test_coverage: int
key_strengths: List[str]
improvement_areas: List[str]
tech_stack: List[str]
recommendations: List[str]
complexity_metrics: Dict[str, int]
best_practices: List[Dict[str, str]]
potential_risks: List[str]
documentation_quality: int
def analyze_code(code_source: str) -> CodeAnalysisReport:
"""
Analyze code from directory path or GitHub URL
"""
# Create code analyzer agent
code_analyzer = Agent(
role="Code Analysis Expert",
goal="Provide comprehensive code evaluation and recommendations",
backstory="""Expert code analyst specializing in architecture review,
best practices, and technical debt assessment.""",
verbose=True
)
# Create analysis task
code_analysis_task = Task(
description="""Analyze code repository and provide structured evaluation:
1. Overall Quality (0-100)
2. Core Metrics Analysis:
- Architecture and Design
- Code Maintainability
- Performance Optimization
- Security Practices
- Test Coverage
3. Technical Assessment:
- Technology Stack Review
- Code Complexity Analysis
- Best Practices Adherence
- Risk Assessment
4. Recommendations:
- Key Improvements
- Architecture Suggestions
- Security Enhancements""",
expected_output="Detailed code analysis report with metrics and recommendations",
agent=code_analyzer,
output_pydantic=CodeAnalysisReport
)
# Ingest code content
summary, tree, content = ingest(code_source)
# Concatenate context into structured format
context_text = f"""
CODE REPOSITORY ANALYSIS
=======================
SUMMARY
-------
{summary}
REPOSITORY STRUCTURE
-------------------
{tree}
SOURCE CODE
-----------
{content}
"""
# Initialize and run analysis
agents = PraisonAIAgents(
agents=[code_analyzer],
tasks=[code_analysis_task]
)
result = agents.start(context_text)
# Extract the Pydantic model from the result
if isinstance(result, dict) and 'task_results' in result:
# Get the first task result's pydantic output
analysis_result = result['task_results'][0].pydantic
if isinstance(analysis_result, CodeAnalysisReport):
return analysis_result
# If we can't get the Pydantic model, create one from the raw data
return CodeAnalysisReport(**result)
def display_code_metrics(metrics, cols):
"""Display code metrics in columns with color-coded scores"""
for i, metric in enumerate(metrics):
score = metric.score
color = "red" if score < 60 else "orange" if score < 75 else "green"
# Use modulo to alternate between columns
with cols[i % len(cols)]:
st.markdown(f"### {metric.category}")
st.markdown(f"**Score:** :{color}[{score}%]")
for finding in metric.findings:
st.markdown(f"• {finding}")
def display_section(title: str, items: list, icon: str = "•"):
"""Display a section with items in a consistent format"""
st.markdown(f"### {title}")
for item in items:
if isinstance(item, dict):
for key, value in item.items():
st.markdown(f"{icon} **{key}**: {value}")
else:
st.markdown(f"{icon} {item}")
def main():
st.set_page_config(
page_title="Code Analysis Agent",
layout="wide",
initial_sidebar_state="expanded"
)
st.title("Code Analysis Agent")
with st.sidebar:
st.header("Input")
code_source = st.text_input(
"GitHub URL or Local Path",
placeholder="https://github.com/username/repo or /path/to/directory"
)
analyze_button = st.button("Analyze Code", type="primary")
if analyze_button and code_source:
try:
with st.spinner("Analyzing code..."):
result = analyze_code(code_source)
# Overall Metrics
st.header("Overall Metrics")
cols = st.columns(6)
metrics = {
"Overall Quality": result.overall_quality,
"Architecture": result.architecture_score,
"Maintainability": result.maintainability_score,
"Performance": result.performance_score,
"Security": result.security_score,
"Test Coverage": result.test_coverage
}
for (metric, value), col in zip(metrics.items(), cols):
color = "red" if value < 60 else "orange" if value < 75 else "green"
col.metric(metric, f"{value}%")
col.markdown(f":{color}[{'●' * (value // 20)}]")
# Detailed Analysis
st.header("Detailed Analysis")
metric_cols = st.columns(2)
display_code_metrics(result.code_metrics, metric_cols)
# Technology Stack
col1, col2 = st.columns(2)
with col1:
st.header("Technology Stack")
for tech in result.tech_stack:
st.markdown(f"🔧 {tech}")
with col2:
st.header("Complexity Metrics")
for metric, value in result.complexity_metrics.items():
st.metric(metric.replace('_', ' ').title(), value)
# Key Findings
st.header("Key Findings")
cols = st.columns(2)
with cols[0]:
display_section("✅ Strengths", result.key_strengths)
display_section("🔄 Best Practices", result.best_practices)
with cols[1]:
display_section("⚠️ Areas for Improvement", result.improvement_areas)
display_section("❗ Potential Risks", result.potential_risks)
# Recommendations
st.header("Recommendations")
for i, rec in enumerate(result.recommendations, 1):
st.markdown(f"**{i}.** {rec}")
# Documentation Quality
st.header("Documentation")
doc_score = result.documentation_quality
color = "red" if doc_score < 60 else "orange" if doc_score < 75 else "green"
st.markdown(f"Documentation Quality: :{color}[{doc_score}%]")
except Exception as e:
st.error(f"Error analyzing code: {str(e)}")
st.exception(e)
elif analyze_button:
st.warning("Please enter a GitHub URL or local path")
if __name__ == "__main__":
main()
+108
View File
@@ -0,0 +1,108 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import time
from typing import List, Dict
def analyze_code_changes():
"""Simulates code analysis"""
issues = [
{"type": "style", "severity": "low", "file": "main.py"},
{"type": "security", "severity": "high", "file": "auth.py"},
{"type": "performance", "severity": "medium", "file": "data.py"}
]
return issues[int(time.time()) % 3]
def suggest_fixes(issue: Dict):
"""Simulates fix suggestions"""
fixes = {
"style": "Apply PEP 8 formatting",
"security": "Implement input validation",
"performance": "Use list comprehension"
}
return fixes.get(issue["type"], "Review manually")
def apply_automated_fix(fix: str):
"""Simulates applying automated fixes"""
success = int(time.time()) % 2 == 0
return "fixed" if success else "manual_review"
# Create specialized agents
analyzer = Agent(
name="Code Analyzer",
role="Code analysis",
goal="Analyze code changes and identify issues",
instructions="Review code changes and report issues",
tools=[analyze_code_changes]
)
fix_suggester = Agent(
name="Fix Suggester",
role="Solution provider",
goal="Suggest fixes for identified issues",
instructions="Provide appropriate fix suggestions",
tools=[suggest_fixes]
)
fix_applier = Agent(
name="Fix Applier",
role="Fix implementation",
goal="Apply suggested fixes automatically when possible",
instructions="Implement suggested fixes and report results",
tools=[apply_automated_fix]
)
# Create workflow tasks
analysis_task = Task(
name="analyze_code",
description="Analyze code changes for issues",
expected_output="Identified code issues",
agent=analyzer,
is_start=True,
next_tasks=["suggest_fixes"]
)
suggestion_task = Task(
name="suggest_fixes",
description="Suggest fixes for identified issues",
expected_output="Fix suggestions",
agent=fix_suggester,
next_tasks=["apply_fixes"]
)
fix_task = Task(
name="apply_fixes",
description="Apply suggested fixes",
expected_output="Fix application status",
agent=fix_applier,
task_type="decision",
condition={
"fixed": "",
"manual_review": ["suggest_fixes"] # Loop back for manual review
}
)
# Create workflow
workflow = PraisonAIAgents(
agents=[analyzer, fix_suggester, fix_applier],
tasks=[analysis_task, suggestion_task, fix_task],
process="workflow",
verbose=True
)
def main():
print("\nStarting Code Review Workflow...")
print("=" * 50)
# Run workflow
results = workflow.start()
# Print results
print("\nCode Review Results:")
print("=" * 50)
for task_id, result in results["task_results"].items():
if result:
print(f"\nTask: {task_id}")
print(f"Result: {result.raw}")
print("-" * 50)
if __name__ == "__main__":
main()
+98
View File
@@ -0,0 +1,98 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
class SkillMetrics(BaseModel):
name: str
score: int
comments: str
class CVAnalysisReport(BaseModel):
overall_score: int
skill_metrics: List[SkillMetrics]
experience_score: int
education_score: int
presentation_score: int
achievement_impact_score: int
market_readiness: int
key_strengths: List[str]
areas_for_improvement: List[str]
market_fit: str
recommendations: List[str]
technical_skills: List[Dict[str, int]]
soft_skills: List[Dict[str, int]]
skill_gaps: List[str]
key_achievements: List[str]
impact_metrics: List[Dict[str, str]]
areas_of_expertise: List[str]
# Create single CV analysis agent
cv_analyzer = Agent(
role="CV Analysis Expert",
goal="Provide comprehensive CV evaluation and recommendations",
backstory="""You are an expert CV analyst with deep knowledge of industry requirements,
market trends, and talent assessment. You excel at evaluating skills, experience,
and providing actionable recommendations.""",
verbose=True
)
# Single comprehensive analysis task
cv_analysis_task = Task(
description="""Perform a detailed CV analysis with scoring metrics and provide output in the following format:
1. Overall Score (0-100):
- Calculate based on weighted average of all metrics
2. Individual Skill Metrics:
- For each major skill found in CV:
* Name of skill
* Score (0-100)
* Specific feedback/comments
3. Core Metrics (0-100 each):
- Experience Score: Based on relevance and years
- Education Score: Based on relevance and level
- Presentation Score: CV format, clarity, structure
- Achievement Impact Score: Measurable results
- Market Readiness: Current market fit
4. Technical Skills:
- List each skill with proficiency score (0-100)
- Example: {"Python": 85, "AWS": 70}
5. Soft Skills:
- List each skill with proficiency score (0-100)
- Example: {"Communication": 90, "Leadership": 75}
6. Detailed Analysis:
- Key Strengths: Top 3-5 standout points
- Areas for Improvement: 3-5 specific points
- Market Fit: Current industry alignment
- Skill Gaps: Missing critical skills for target role
- Key Achievements: Quantifiable accomplishments
- Impact Metrics: {"metric": "value"}
- Areas of Expertise: Primary domains of expertise
7. Recommendations:
- 3-5 actionable steps for improvement
Provide clear justification for all scores and ensure feedback is specific and actionable.""",
expected_output="Structured CV analysis report with detailed metrics and scoring justification",
agent=cv_analyzer,
output_pydantic=CVAnalysisReport
)
# Create and run the agent
agents = PraisonAIAgents(
agents=[cv_analyzer],
tasks=[cv_analysis_task]
)
# Read and pass CV content through start()
with open('cv.txt', 'r') as file:
cv_content = file.read()
# Start the analysis by passing CV content
result = agents.start(cv_content)
print(result)
+202
View File
@@ -0,0 +1,202 @@
import streamlit as st
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import json
import asyncio
import nest_asyncio
from functools import partial
# Enable nested event loops
nest_asyncio.apply()
class SkillMetrics(BaseModel):
name: str
score: int
comments: str
class CVAnalysisReport(BaseModel):
overall_score: int
skill_metrics: List[SkillMetrics]
experience_score: int
education_score: int
presentation_score: int
achievement_impact_score: int
market_readiness: int
key_strengths: List[str]
areas_for_improvement: List[str]
market_fit: str
recommendations: List[str]
technical_skills: List[Dict[str, int]]
soft_skills: List[Dict[str, int]]
skill_gaps: List[str]
key_achievements: List[str]
impact_metrics: List[Dict[str, str]]
areas_of_expertise: List[str]
async def analyze_cv_async(cv_content):
cv_analyzer = Agent(
role="CV Analysis Expert",
goal="Provide comprehensive CV evaluation and recommendations",
backstory="""You are an expert CV analyst with deep knowledge of industry requirements,
market trends, and talent assessment. You excel at evaluating skills, experience,
and providing actionable recommendations.""",
verbose=True
)
cv_analysis_task = Task(
description="""Perform a detailed CV analysis with scoring metrics and provide output in the following format:
1. Overall Score (0-100):
- Calculate based on weighted average of all metrics
2. Individual Skill Metrics:
- For each major skill found in CV:
* Name of skill
* Score (0-100)
* Specific feedback/comments
3. Core Metrics (0-100 each):
- Experience Score: Based on relevance and years
- Education Score: Based on relevance and level
- Presentation Score: CV format, clarity, structure
- Achievement Impact Score: Measurable results
- Market Readiness: Current market fit
4. Technical Skills:
- List each skill with proficiency score (0-100)
5. Soft Skills:
- List each skill with proficiency score (0-100)
6. Detailed Analysis sections
7. Recommendations:
- 3-5 actionable steps for improvement""",
expected_output="Structured CV analysis report with detailed metrics and scoring justification",
agent=cv_analyzer,
output_pydantic=CVAnalysisReport
)
agents = PraisonAIAgents(
agents=[cv_analyzer],
tasks=[cv_analysis_task]
)
try:
result = await agents.astart(cv_content)
return result['task_results'][0].pydantic
except Exception as e:
print(f"Error during analysis: {str(e)}")
raise e
def analyze_cv(cv_content):
async def run_analysis():
return await analyze_cv_async(cv_content)
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
result = loop.run_until_complete(run_analysis())
return result
except Exception as e:
raise e
finally:
loop.close()
def main():
st.set_page_config(page_title="CV Analyzer", layout="wide")
st.title("Professional CV Analyzer")
# File upload
cv_file = st.file_uploader("Upload your CV (TXT format)", type=['txt'])
if cv_file:
cv_content = cv_file.read().decode()
with st.spinner('Analyzing your CV...'):
try:
analysis = analyze_cv(cv_content)
# Display Overall Score
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Overall Score", f"{analysis.overall_score}/100")
with col2:
st.metric("Market Readiness", f"{analysis.market_readiness}/100")
with col3:
st.metric("Experience Score", f"{analysis.experience_score}/100")
# Core Metrics
st.subheader("Core Metrics")
metrics_cols = st.columns(4)
with metrics_cols[0]:
st.metric("Education", f"{analysis.education_score}/100")
with metrics_cols[1]:
st.metric("Presentation", f"{analysis.presentation_score}/100")
with metrics_cols[2]:
st.metric("Achievement Impact", f"{analysis.achievement_impact_score}/100")
with metrics_cols[3]:
st.metric("Market Readiness", f"{analysis.market_readiness}/100")
# Skill Metrics
st.subheader("Detailed Skill Analysis")
for skill in analysis.skill_metrics:
with st.expander(f"{skill.name} - Score: {skill.score}/100"):
st.write(skill.comments)
# Technical and Soft Skills
col1, col2 = st.columns(2)
with col1:
st.subheader("Technical Skills")
for skill in analysis.technical_skills:
for skill_name, score in skill.items():
st.progress(score/100)
st.caption(f"{skill_name}: {score}/100")
with col2:
st.subheader("Soft Skills")
for skill in analysis.soft_skills:
for skill_name, score in skill.items():
st.progress(score/100)
st.caption(f"{skill_name}: {score}/100")
# Key Information
st.subheader("Key Analysis")
col1, col2 = st.columns(2)
with col1:
st.write("🎯 Key Strengths")
for strength in analysis.key_strengths:
st.write(f"• {strength}")
st.write("🎮 Areas of Expertise")
for expertise in analysis.areas_of_expertise:
st.write(f"• {expertise}")
with col2:
st.write("🔄 Areas for Improvement")
for area in analysis.areas_for_improvement:
st.write(f"• {area}")
st.write("⚠️ Skill Gaps")
for gap in analysis.skill_gaps:
st.write(f"• {gap}")
# Impact Metrics
st.subheader("Impact Metrics")
for metric in analysis.impact_metrics:
for key, value in metric.items():
st.metric(key, value)
# Recommendations
st.subheader("📋 Recommendations")
for rec in analysis.recommendations:
st.write(f"• {rec}")
except Exception as e:
st.error(f"An error occurred during analysis: {str(e)}")
else:
st.info("Please upload your CV in TXT format to begin the analysis")
if __name__ == "__main__":
main()
+61
View File
@@ -0,0 +1,61 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
class CVAnalysisReport(BaseModel):
overall_score: int
key_strengths: List[str]
areas_for_improvement: List[str]
market_fit: str
recommendations: List[str]
technical_skills: List[str]
soft_skills: List[str]
skill_gaps: List[str]
key_achievements: List[str]
impact_metrics: List[Dict[str, str]]
areas_of_expertise: List[str]
# Create single CV analysis agent
cv_analyzer = Agent(
role="CV Analysis Expert",
goal="Provide comprehensive CV evaluation and recommendations",
backstory="""You are an expert CV analyst with deep knowledge of industry requirements,
market trends, and talent assessment. You excel at evaluating skills, experience,
and providing actionable recommendations.""",
verbose=True
)
# Read CV content first
with open('cv.txt', 'r') as file:
cv_content = file.read()
cv_key_strengths = Task(
description="List the key strengths to look",
expected_output="List of key strengths",
agent=cv_analyzer,
)
# Single comprehensive analysis task with CV content in context
cv_analysis_task = Task(
description="""Analyze the CV comprehensively including:
1. Technical and soft skills assessment
2. Experience and achievements evaluation
3. Overall CV evaluation with recommendations
Provide detailed insights and actionable recommendations.""",
expected_output="Complete CV analysis report",
agent=cv_analyzer,
output_pydantic=CVAnalysisReport,
context=[cv_content, cv_key_strengths] # Pass CV content directly in task context
)
# Create and run the agent
agents = PraisonAIAgents(
agents=[cv_analyzer],
tasks=[cv_key_strengths,cv_analysis_task],
process="sequential"
)
# Start the analysis - no need to pass content again since it's in task context
result = agents.start()
print(result)
+27
View File
@@ -0,0 +1,27 @@
# example tools.py
from duckduckgo_search import DDGS
from praisonai_tools import BaseTool
class InternetSearchTool(BaseTool):
name: str = "InternetSearchTool"
description: str = "Search Internet for relevant information based on a query or latest news"
def _run(self, query: str):
ddgs = DDGS()
results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
return results
# Example agent
from praisonaiagents import Agent
from praisonaiagents import PraisonAIAgents
agent = Agent(
name="Internet Search Agent",
tools=[InternetSearchTool],
instructions="""
You are an agent that can search the internet for relevant information based on a query or latest news.
"""
)
# Run the agent
result = PraisonAIAgents(agents=[agent], verbose=10).start()
print(result)
+57
View File
@@ -0,0 +1,57 @@
Name: Alex Johnson
Location: London, UK
Professional Summary
Dynamic and results-oriented leader with a proven track record of driving innovation, scaling operations, and achieving transformational growth. Over 15 years of experience in engineering, strategic management, and executive leadership in the automotive and renewable energy sectors. Passionate about sustainable technologies and visionary leadership.
Professional Experience
Chief Operating Officer (COO)
NextGen Mobility Ltd. | Palo Alto, CA | 2020 – Present
Spearheaded global operations for an electric vehicle company, scaling production by 200% in three years.
Introduced automation-driven supply chain strategies, reducing costs by 15%.
Collaborated with R&D to launch three new EV models, driving 25% revenue growth annually.
Vice President of Engineering
ElectroDrive Systems | San Francisco, CA | 2015 – 2020
Led a team of 500+ engineers in developing next-generation EV batteries, achieving a 30% increase in energy efficiency.
Secured $50M in government funding for sustainable energy innovation.
Drove cross-functional collaboration, aligning product development with market needs.
Director of Renewable Energy Initiatives
GreenTech Innovations | London, UK | 2011 – 2015
Oversaw £100M projects in solar and wind energy deployment across Europe.
Established partnerships with policymakers to influence renewable energy legislation.
Pioneered a smart energy grid system, enhancing energy distribution efficiency by 40%.
Senior Project Manager
Innovate Auto Ltd. | Munich, Germany | 2008 – 2011
Managed R&D projects for autonomous driving technologies.
Delivered projects 20% under budget through strategic resource allocation.
Filed 10+ patents in automotive AI and renewable integration.
Mechanical Engineer
AutoFusion Technologies | Berlin, Germany | 2005 – 2008
Designed core systems for EV powertrains, optimising energy consumption by 15%.
Collaborated with suppliers to improve material efficiency, cutting costs by £5M annually.
Education
MBA in Strategic Management
Harvard Business School | Cambridge, MA | 2015
MSc in Renewable Energy Engineering
Imperial College London | London, UK | 2007
BSc in Mechanical Engineering
Technical University of Munich | Munich, Germany | 2005
Skills
Strategic Leadership & Visionary Thinking
Electric Vehicle Engineering
Renewable Energy Systems
Global Operations Management
Policy Advocacy & Government Relations
Supply Chain Optimisation
Achievements
Featured in Forbes 30 Under 40 for innovations in EV technology.
Author of The Future of Sustainable Mobility.
Keynote speaker at World Energy Summit, 2023.
+10
View File
@@ -0,0 +1,10 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import read_csv, read_excel, write_csv, write_excel, filter_data, get_summary, group_by, pivot_table
import os
agent = Agent(instructions="You are a Data Analyst Agent", tools=[read_csv, read_excel, write_csv, write_excel, filter_data, get_summary, group_by, pivot_table])
agent.start(f"""
Read the data from the csv file {os.path.join(os.path.dirname(__file__), "tesla-stock-price.csv")}
Analyse the data and give me the insights
read_csv to read the file
""")
+9
View File
@@ -0,0 +1,9 @@
# pip install praisonaiagents
# export OPENAI_BASE_URL=http://localhost:11434/v1
# ollama pull deepseek-r1
from praisonaiagents import Agent
agent = Agent(instructions="You are helpful Assisant", llm="deepseek-r1")
agent.start("Why sky is Blue?")
+62
View File
@@ -0,0 +1,62 @@
import streamlit as st
from praisonaiagents import Agent
def init_agent():
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
},
"llm": {
"provider": "ollama",
"config": {
"model": "deepseek-r1:latest",
"temperature": 0,
"max_tokens": 8000,
"ollama_base_url": "http://localhost:11434",
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
"ollama_base_url": "http://localhost:11434",
"embedding_dims": 1536
},
},
}
return Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["kag-research-paper.pdf"],
knowledge_config=config,
user_id="user1",
llm="deepseek-r1"
)
st.title("Knowledge Agent Chat")
if "agent" not in st.session_state:
st.session_state.agent = init_agent()
st.session_state.messages = []
if "messages" in st.session_state:
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
prompt = st.chat_input("Ask a question...")
if prompt:
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
response = st.session_state.agent.start(prompt)
st.markdown(response)
st.session_state.messages.append({"role": "assistant", "content": response})
+54
View File
@@ -0,0 +1,54 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
},
"llm": {
"provider": "ollama",
"config": {
"model": "deepseek-r1:latest",
"temperature": 0,
"max_tokens": 8000,
"ollama_base_url": "http://localhost:11434",
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
"ollama_base_url": "http://localhost:11434",
},
},
}
# Create an agent
rag_agent = Agent(
name="RAG Agent",
role="Information Specialist",
goal="Retrieve knowledge efficiently",
llm="deepseek-r1"
)
# Define a task for the agent
rag_task = Task(
name="RAG Task",
description="What is KAG?",
expected_output="Answer to the question",
agent=rag_agent,
context=[config] # Vector Database provided as context
)
# Build Agents
agents = PraisonAIAgents(
agents=[rag_agent],
tasks=[rag_task],
user_id="user1"
)
# Start Agents
agents.start()
+62
View File
@@ -0,0 +1,62 @@
import streamlit as st
from praisonaiagents import Agent
def init_agent():
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
},
"llm": {
"provider": "ollama",
"config": {
"model": "deepseek-r1:latest",
"temperature": 0,
"max_tokens": 8000,
"ollama_base_url": "http://localhost:11434",
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
"ollama_base_url": "http://localhost:11434",
"embedding_dims": 1536
},
},
}
return Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["kag-research-paper.pdf"],
knowledge_config=config,
user_id="user1",
llm="deepseek-r1"
)
st.title("Knowledge Agent Chat")
if "agent" not in st.session_state:
st.session_state.agent = init_agent()
st.session_state.messages = []
if "messages" in st.session_state:
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
prompt = st.chat_input("Ask a question...")
if prompt:
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
response = st.session_state.agent.start(prompt)
st.markdown(response)
st.session_state.messages.append({"role": "assistant", "content": response})
+39
View File
@@ -0,0 +1,39 @@
from praisonaiagents import Agent
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
},
"llm": {
"provider": "ollama",
"config": {
"model": "deepseek-r1:latest",
"temperature": 0,
"max_tokens": 8000,
"ollama_base_url": "http://localhost:11434",
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
"ollama_base_url": "http://localhost:11434",
"embedding_dims": 1536
},
},
}
agent = Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["kag-research-paper.pdf"], # Indexing
knowledge_config=config,
user_id="user1",
llm="deepseek-r1"
)
agent.start("What is KAG in one line?") # Retrieval
+6
View File
@@ -0,0 +1,6 @@
from praisonaiagents import Agent
agent = Agent(instructions="You are helpful Assisant", llm="deepseek-reasoner", reasoning_steps=True)
result = agent.start("Why sky is Blue?")
print(result)
+14
View File
@@ -0,0 +1,14 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
reasoning_agent = Agent(role="Helpful Assistant", reasoning_steps=True, llm="deepseek/deepseek-reasoner")
small_agent = Agent(role="Helpful Assistant", llm="gpt-3.5-turbo")
reasoning_task = Task(description="How many r's in the word 'Strawberry'?", agent=reasoning_agent)
small_task = Task(description="With the provided reasoning tell me how many r's in the word 'Strawberry'?", agent=small_agent)
agents = PraisonAIAgents(
agents=[reasoning_agent, small_agent],
tasks=[reasoning_task, small_task]
)
agents.start()
+18
View File
@@ -0,0 +1,18 @@
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="deepseek-reasoner",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Why sky is Blue?"},
],
stream=True
)
for chunk in response:
if chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end="", flush=True)
if chunk.choices[0].delta.reasoning_content is not None:
print(chunk.choices[0].delta.reasoning_content, end="", flush=True)
+3
View File
@@ -0,0 +1,3 @@
I am Mervin Praison, a software engineer and entrepreneur.
I am the founder of Praison AI, a company that is building AI agents to help people with their daily tasks.
+5
View File
@@ -0,0 +1,5 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import get_stock_price, get_stock_info, get_historical_data
agent = Agent(instructions="You are a Research Agent", tools=[get_stock_price, get_stock_info, get_historical_data])
agent.start("Understand current stock price and historical data of Apple and Google. Tell me if I can invest in them")
+34
View File
@@ -0,0 +1,34 @@
import gradio as gr
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
def research(query):
agent = Agent(instructions="You are a Research Agent", tools=[duckduckgo])
result = agent.start(query)
# Format the result with enhanced markdown
formatted_result = f"""
{result}
----
*Generated by PraisonAI Research Assistant*
"""
return formatted_result
# Create a simple Gradio interface
demo = gr.Interface(
fn=research,
inputs=gr.Textbox(
label="Research Query",
placeholder="Enter your research topic...",
lines=2
),
outputs=gr.Markdown(
show_copy_button=True,
height=500,
container=True
),
title="AI Research Assistant",
description="Enter your research query below to get started!",
)
if __name__ == "__main__":
demo.launch()
View File
Whitespace-only changes.
+159
View File
@@ -0,0 +1,159 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import os
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Create Vision Analysis Agent
hackathon_judge = Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
# If response is a string, try to parse it as JSON
elif isinstance(response, str):
evaluation_data = json.loads(response)
# If response is a dict with task_status
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
print(f"Debug - Parsed evaluation_data: {evaluation_data}")
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
if __name__ == "__main__":
# Example usage
current_dir = os.path.dirname(os.path.abspath(__file__))
video_path = os.path.join(current_dir, "presentation.mp4")
result = evaluate_project(video_path) # Now returns ProjectEvaluation directly
print("\nHackathon Project Evaluation")
print("===========================")
print(f"\nOverall Score: {result.overall_score}/100")
print("\nDetailed Scores:")
print(f"Innovation: {result.innovation_score}/100")
print(f"Technical Complexity: {result.technical_complexity}/100")
print(f"Presentation: {result.presentation_quality}/100")
print(f"User Experience: {result.user_experience}/100")
print(f"Completeness: {result.completeness}/100")
print("\nKey Strengths:")
for strength in result.key_strengths:
print(f"- {strength}")
print("\nAreas for Improvement:")
for area in result.areas_for_improvement:
print(f"- {area}")
print("\nTechnical Highlights:")
for highlight in result.technical_highlights:
print(f"- {highlight}")
print("\nRecommendations:")
for rec in result.recommendations:
print(f"- {rec}")
print(f"\nMarket Potential: {result.market_potential}")
print(f"\nScalability Assessment: {result.scalability_assessment}")
+159
View File
@@ -0,0 +1,159 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import os
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Create Vision Analysis Agent
hackathon_judge = Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
# If response is a string, try to parse it as JSON
elif isinstance(response, str):
evaluation_data = json.loads(response)
# If response is a dict with task_status
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
print(f"Debug - Parsed evaluation_data: {evaluation_data}")
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
if __name__ == "__main__":
# Example usage
current_dir = os.path.dirname(os.path.abspath(__file__))
video_path = os.path.join(current_dir, "presentation.mp4")
result = evaluate_project(video_path) # Now returns ProjectEvaluation directly
print("\nHackathon Project Evaluation")
print("===========================")
print(f"\nOverall Score: {result.overall_score}/100")
print("\nDetailed Scores:")
print(f"Innovation: {result.innovation_score}/100")
print(f"Technical Complexity: {result.technical_complexity}/100")
print(f"Presentation: {result.presentation_quality}/100")
print(f"User Experience: {result.user_experience}/100")
print(f"Completeness: {result.completeness}/100")
print("\nKey Strengths:")
for strength in result.key_strengths:
print(f"- {strength}")
print("\nAreas for Improvement:")
for area in result.areas_for_improvement:
print(f"- {area}")
print("\nTechnical Highlights:")
for highlight in result.technical_highlights:
print(f"- {highlight}")
print("\nRecommendations:")
for rec in result.recommendations:
print(f"- {rec}")
print(f"\nMarket Potential: {result.market_potential}")
print(f"\nScalability Assessment: {result.scalability_assessment}")
+210
View File
@@ -0,0 +1,210 @@
import streamlit as st
import os
from praisonaiagents import Agent, Task, PraisonAIAgents
from pydantic import BaseModel
from typing import List, Dict
import tempfile
import json
class ProjectEvaluation(BaseModel):
innovation_score: int # 0-100
technical_complexity: int # 0-100
presentation_quality: int # 0-100
user_experience: int # 0-100
completeness: int # 0-100
overall_score: int # 0-100
key_strengths: List[str]
areas_for_improvement: List[str]
notable_features: List[str]
technical_highlights: List[str]
recommendations: List[str]
market_potential: str
scalability_assessment: str
# Set page config
st.set_page_config(
page_title="Hackathon Project Evaluator",
page_icon="🏆",
layout="wide"
)
# Create Vision Analysis Agent
@st.cache_resource
def get_hackathon_judge():
return Agent(
name="HackathonJudge",
role="Technical Project Evaluator",
goal="Evaluate hackathon projects through video demonstrations",
backstory="""You are an experienced hackathon judge and technical expert.
You excel at evaluating innovation, technical implementation, and presentation quality.
You provide constructive feedback and identify both strengths and areas for improvement.""",
llm="gpt-4o-mini", # Using vision-capable model
self_reflect=False,
knowledge=""
)
def evaluate_project(video_path: str) -> ProjectEvaluation:
"""
Evaluate a hackathon project based on its video demonstration
"""
hackathon_judge = get_hackathon_judge()
evaluation_task = Task(
name="project_evaluation",
description="""Analyze this hackathon project video demonstration and provide a comprehensive evaluation:
1. Score the following aspects (0-100):
- Innovation and Creativity
- Technical Complexity
- Presentation Quality
- User Experience
- Project Completeness
2. Identify:
- Key strengths and standout features
- Areas that could be improved
- Notable technical implementations
- Market potential and scalability
3. Provide:
- Specific recommendations for improvement
- Technical suggestions
- Potential future enhancements""",
expected_output="Detailed project evaluation with scores and feedback",
agent=hackathon_judge,
output_pydantic=ProjectEvaluation,
images=[video_path] # Video input for multimodal analysis
)
# Initialize and run evaluation
agents = PraisonAIAgents(
agents=[hackathon_judge],
tasks=[evaluation_task],
process="sequential",
verbose=True
)
response = agents.start()
try:
# If response contains task_results, extract the Pydantic model directly
if isinstance(response, dict) and 'task_results' in response:
task_output = response['task_results'][0]
if hasattr(task_output, 'pydantic'):
return task_output.pydantic
elif hasattr(task_output, 'raw'):
# Extract JSON from raw string if it's wrapped in ```json
raw_text = task_output.raw
if raw_text.startswith('```json'):
raw_text = raw_text.split('\n', 1)[1].rsplit('\n', 1)[0]
evaluation_data = json.loads(raw_text)
else:
evaluation_data = json.loads(task_output) if isinstance(task_output, str) else task_output
elif isinstance(response, str):
evaluation_data = json.loads(response)
elif isinstance(response, dict) and 'task_status' in response:
content = response['task_status']
if isinstance(content, dict):
evaluation_data = content
else:
evaluation_data = json.loads(content) if isinstance(content, str) else content
else:
evaluation_data = response
# Create and return ProjectEvaluation instance
return ProjectEvaluation(
innovation_score=int(evaluation_data.get('innovation_score', 0)),
technical_complexity=int(evaluation_data.get('technical_complexity', 0)),
presentation_quality=int(evaluation_data.get('presentation_quality', 0)),
user_experience=int(evaluation_data.get('user_experience', 0)),
completeness=int(evaluation_data.get('completeness', 0)),
overall_score=int(evaluation_data.get('overall_score', 0)),
key_strengths=evaluation_data.get('key_strengths', []),
areas_for_improvement=evaluation_data.get('areas_for_improvement', []),
notable_features=evaluation_data.get('notable_features', []),
technical_highlights=evaluation_data.get('technical_highlights', []),
recommendations=evaluation_data.get('recommendations', []),
market_potential=str(evaluation_data.get('market_potential', '')),
scalability_assessment=str(evaluation_data.get('scalability_assessment', ''))
)
except Exception as e:
print(f"Debug - Raw response: {response}")
print(f"Error processing response: {e}")
raise
# Title and description
st.title("🏆 Hackathon Judge Agent")
st.markdown("""
Upload your hackathon project demonstration video for an AI-powered evaluation.
Get comprehensive feedback on various aspects of your project.
""")
# File uploader
uploaded_file = st.file_uploader("Choose a video file", type=['mp4', 'avi', 'mov', 'mkv'])
if uploaded_file:
# Create a temporary file to store the video
with tempfile.NamedTemporaryFile(delete=False, suffix='.'+uploaded_file.name.split('.')[-1]) as tmp_file:
tmp_file.write(uploaded_file.getvalue())
video_path = tmp_file.name
with st.spinner("🤖 AI is evaluating your project..."):
try:
# Evaluate the project
result = evaluate_project(video_path)
# Display results
st.header("Overall Score")
st.metric("Overall Score", f"{result.overall_score}/100")
# Display detailed scores
st.header("Detailed Scores")
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Innovation", f"{result.innovation_score}/100")
st.metric("Technical Complexity", f"{result.technical_complexity}/100")
with col2:
st.metric("Presentation", f"{result.presentation_quality}/100")
st.metric("User Experience", f"{result.user_experience}/100")
with col3:
st.metric("Completeness", f"{result.completeness}/100")
# Display qualitative feedback
st.header("Key Strengths")
for strength in result.key_strengths:
st.write(f"• {strength}")
st.header("Areas for Improvement")
for area in result.areas_for_improvement:
st.write(f"• {area}")
st.header("Technical Highlights")
for highlight in result.technical_highlights:
st.write(f"• {highlight}")
st.header("Notable Features")
for feature in result.notable_features:
st.write(f"• {feature}")
st.header("Recommendations")
for rec in result.recommendations:
st.write(f"• {rec}")
# Market Analysis
st.header("Market Analysis")
col1, col2 = st.columns(2)
with col1:
st.subheader("Market Potential")
st.write(result.market_potential)
with col2:
st.subheader("Scalability Assessment")
st.write(result.scalability_assessment)
except Exception as e:
st.error(f"Error evaluating the project: {str(e)}")
finally:
# Clean up the temporary file
os.unlink(video_path)
else:
# Display placeholder content
st.info("👆 Upload a video file to get started!")
+47
View File
@@ -0,0 +1,47 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
agent = Agent(instructions="You are a Image Analysis Agent", tools=[duckduckgo])
agent.start("I want to go London next week, find me a good hotel and flight")
from praisonaiagents import Agent, Task, PraisonAIAgents
# Create Image Analysis Agent
image_agent = Agent(
name="ImageAnalyst",
role="Image Analysis Specialist",
goal="Analyze images and videos to extract meaningful information",
backstory="""You are an expert in computer vision and image analysis.
You excel at describing images, detecting objects, and understanding visual content.""",
llm="gpt-4o-mini",
self_reflect=False
)
# 1. Task with Image URL
task1 = Task(
name="analyze_landmark",
description="Describe this famous landmark and its architectural features.",
expected_output="Detailed description of the landmark's architecture and significance",
agent=image_agent,
images=["https://upload.wikimedia.org/wikipedia/commons/b/bf/Krakow_-_Kosciol_Mariacki.jpg"]
)
# 2. Task with Local Image File
task2 = Task(
name="analyze_local_image",
description="What objects can you see in this image? Describe their arrangement.",
expected_output="Detailed description of objects and their spatial relationships",
agent=image_agent,
images=["image.jpg"]
)
# Create PraisonAIAgents instance
agents = PraisonAIAgents(
agents=[image_agent],
tasks=[task1, task2],
process="sequential",
verbose=1
)
# Run all tasks
agents.start()
+47
View File
@@ -0,0 +1,47 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
agent = Agent(instructions="You are a Image Analysis Agent", tools=[duckduckgo])
agent.start("I want to go London next week, find me a good hotel and flight")
from praisonaiagents import Agent, Task, PraisonAIAgents
# Create Image Analysis Agent
image_agent = Agent(
name="ImageAnalyst",
role="Image Analysis Specialist",
goal="Analyze images and videos to extract meaningful information",
backstory="""You are an expert in computer vision and image analysis.
You excel at describing images, detecting objects, and understanding visual content.""",
llm="gpt-4o-mini",
self_reflect=False
)
# 1. Task with Image URL
task1 = Task(
name="analyze_landmark",
description="Describe this famous landmark and its architectural features.",
expected_output="Detailed description of the landmark's architecture and significance",
agent=image_agent,
images=["https://upload.wikimedia.org/wikipedia/commons/b/bf/Krakow_-_Kosciol_Mariacki.jpg"]
)
# 2. Task with Local Image File
task2 = Task(
name="analyze_local_image",
description="What objects can you see in this image? Describe their arrangement.",
expected_output="Detailed description of objects and their spatial relationships",
agent=image_agent,
images=["image.jpg"]
)
# Create PraisonAIAgents instance
agents = PraisonAIAgents(
agents=[image_agent],
tasks=[task1, task2],
process="sequential",
verbose=1
)
# Run all tasks
agents.start()
Binary file not shown.
+70
View File
@@ -0,0 +1,70 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import logging
import os
import json
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# Define the configuration for the Knowledge instance
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
# Create an agent with knowledge capabilities
knowledge_agent = Agent(
name="KnowledgeAgent",
role="Information Specialist",
goal="Store and retrieve knowledge efficiently",
backstory="Expert in managing and utilizing stored knowledge",
verbose=True
)
# Define a task for the agent
knowledge_task = Task(
name="knowledge_task",
description="KAG",
expected_output="Answer to the question",
agent=knowledge_agent,
context=[
{
"embedding_db_config": json.dumps(config["vector_store"])
}
]
)
# Create and start the agents
agents = PraisonAIAgents(
agents=[knowledge_agent],
tasks=[knowledge_task],
process="sequential",
user_id="user1"
)
# Start execution
result = agents.start()
+21
View File
@@ -0,0 +1,21 @@
from praisonaiagents import Agent
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison",
}
}
}
agent = Agent(
name="Knowledge Agent",
instructions="You answer questions based on the provided knowledge.",
knowledge=["large.pdf"],
knowledge_config=config,
user_id="user1"
)
agent.start("What is KAG in one line?")
+44
View File
@@ -0,0 +1,44 @@
import logging
from praisonaiagents.knowledge import Knowledge
import os
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
knowledge = Knowledge(config)
# Search for memories based on a query
query = "KAG"
logger.info(f"Searching for memories with query: {query}")
search_results = knowledge.search(query, user_id="user1")
logger.info(f"Search results: {search_results}")
print(f"\nSearch results for '{query}':")
print(search_results)
+171
View File
@@ -0,0 +1,171 @@
import logging
from praisonaiagents.knowledge import Knowledge
import os
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "test",
"path": ".praison",
}
}
}
knowledge = Knowledge(config)
# Store memories
logger.info("Storing memories...")
cricket_memory = knowledge.store("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
logger.info(f"Stored cricket memory: {cricket_memory}")
tennis_memory = knowledge.store("Enjoys playing tennis with friends", user_id="alice", metadata={"category": "hobbies"})
logger.info(f"Stored tennis memory: {tennis_memory}")
work_memory = knowledge.store("Works as a software engineer", user_id="alice", metadata={"category": "work"})
logger.info(f"Stored work memory: {work_memory}")
print("Stored memories:")
print(cricket_memory)
print(tennis_memory)
print(work_memory)
# Retrieve all memories for a user
logger.info("Retrieving all memories for Alice...")
alice_memories = knowledge.get_all(user_id="alice")
logger.info(f"Retrieved memories for Alice: {alice_memories}")
print("\nAll memories for Alice:")
for memory in alice_memories:
print(memory)
# Retrieve a specific memory by ID
logger.info(f"Retrieving memory with ID: {cricket_memory['results'][0]['id']}")
retrieved_memory = knowledge.get(cricket_memory['results'][0]["id"])
logger.info(f"Retrieved memory: {retrieved_memory}")
print("\nRetrieved memory:")
print(retrieved_memory)
# Search for memories based on a query
query = "What are Alice's hobbies?"
logger.info(f"Searching for memories with query: {query}")
search_results = knowledge.search(query, user_id="alice")
logger.info(f"Search results: {search_results}")
print(f"\nSearch results for '{query}':")
for memory in search_results:
print(memory)
# Update a memory
logger.info(f"Updating memory with ID: {tennis_memory['results'][0]['id']}")
updated_memory = knowledge.update(memory_id=tennis_memory['results'][0]["id"], data="Loves playing tennis on weekends")
logger.info(f"Updated memory: {updated_memory}")
print("\nUpdated memory:")
print(updated_memory)
# Get memory history
logger.info(f"Retrieving memory history for ID: {tennis_memory['results'][0]['id']}")
memory_history = knowledge.history(memory_id=tennis_memory['results'][0]["id"])
logger.info(f"Memory history: {memory_history}")
print("\nMemory history:")
for entry in memory_history:
print(entry)
# Delete a memory
logger.info(f"Deleting memory with ID: {work_memory['results'][0]['id']}")
knowledge.delete(memory_id=work_memory['results'][0]["id"])
logger.info("Memory deleted")
print("\nDeleted memory")
# Retrieve memories after deletion
logger.info("Retrieving memories after deletion...")
alice_memories = knowledge.get_all(user_id="alice")
logger.info(f"Retrieved memories after deletion: {alice_memories}")
print("\nMemories after deletion:")
for memory in alice_memories:
print(memory)
# Delete all memories for a user
logger.info("Deleting all memories for Alice...")
knowledge.delete_all(user_id="alice")
logger.info("All memories for Alice deleted")
print("\nAll memories for Alice deleted")
# Retrieve memories after deleting all
logger.info("Retrieving memories after deleting all...")
alice_memories = knowledge.get_all(user_id="alice")
logger.info(f"Retrieved memories after deleting all: {alice_memories}")
print("\nMemories after deleting all:")
print(alice_memories)
# Reset all memories
logger.info("Resetting all memories...")
knowledge.reset()
logger.info("All memories reset")
print("\nAll memories reset")
# Test file handling
logger.info("Testing file handling...")
try:
# Get absolute path to test files
current_dir = os.path.dirname(os.path.abspath(__file__))
pdf_file = os.path.join(current_dir, "small.pdf")
txt_file = os.path.join(current_dir, "sample.txt")
# Test text file
logger.info(f"Testing text file: {txt_file}")
# Read and display content
with open(txt_file, 'r') as file:
txt_content = file.read()
print("\nText file content:")
print(txt_content)
# Store the text file using add
txt_memory = knowledge.add(txt_file, user_id="bob", metadata={"type": "text"})
logger.info(f"Stored text file: {txt_memory}")
print("\nStored text content:")
if txt_memory and 'results' in txt_memory and txt_memory['results']:
for mem in txt_memory['results']:
print(mem)
else:
print("No valid memories were stored from the text file")
# Verify text memories are stored
if txt_memory and 'results' in txt_memory and txt_memory['results']:
logger.info("Verifying text memories...")
for mem in txt_memory['results']:
if isinstance(mem, dict) and 'id' in mem:
stored = knowledge.get(mem['id'])
logger.info(f"Verified text memory: {stored}")
else:
logger.warning(f"Unexpected memory format: {mem}")
else:
logger.warning("No valid memories were stored from the text file")
# Test pdf file
logger.info(f"Testing pdf file: {pdf_file}")
pdf_memory = knowledge.add(pdf_file, user_id="bob", metadata={"type": "pdf"})
logger.info(f"Stored pdf file: {pdf_memory}")
print("\nStored pdf content:")
if pdf_memory and 'results' in pdf_memory and pdf_memory['results']:
for mem in pdf_memory['results']:
print(mem)
else:
print("No valid memories were stored from the PDF file")
# Verify stored content
if pdf_memory and 'results' in pdf_memory and pdf_memory['results']:
for memory in pdf_memory['results']:
if isinstance(memory, dict) and 'id' in memory:
stored_memory = knowledge.get(memory['id'])
logger.info(f"Verified stored memory: {stored_memory}")
print("\nVerified content:")
print(stored_memory)
else:
logger.warning(f"Unexpected memory format: {memory}")
else:
logger.warning("No valid memories were stored from the PDF file")
except Exception as e:
logger.error(f"Error during file handling test: {str(e)}")
raise
+40
View File
@@ -0,0 +1,40 @@
import logging
from praisonaiagents.knowledge import Knowledge
import os
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
knowledge = Knowledge()
try:
# Get absolute path to test files
current_dir = os.path.dirname(os.path.abspath(__file__))
pdf_file = os.path.join(current_dir, "large.pdf")
# Test pdf file
logger.info(f"Testing pdf file: {pdf_file}")
pdf_memory = knowledge.add(pdf_file, user_id="bob", metadata={"type": "pdf"})
logger.info(f"Stored pdf file: {pdf_memory}")
print("\nStored pdf content:")
if pdf_memory and 'results' in pdf_memory and pdf_memory['results']:
for mem in pdf_memory['results']:
print(mem)
else:
print("No valid memories were stored from the PDF file")
# Verify stored content
if pdf_memory and 'results' in pdf_memory and pdf_memory['results']:
for memory in pdf_memory['results']:
if isinstance(memory, dict) and 'id' in memory:
stored_memory = knowledge.get(memory['id'])
logger.info(f"Verified stored memory: {stored_memory}")
print("\nVerified content:")
print(stored_memory)
else:
logger.warning(f"Unexpected memory format: {memory}")
else:
logger.warning("No valid memories were stored from the PDF file")
except Exception as e:
logger.error(f"Error during file handling test: {str(e)}")
raise
BIN
View File
Binary file not shown.
+14
View File
@@ -0,0 +1,14 @@
from litellm import completion
messages = [{"role": "user", "content": "What is 1+1?"}]
resp = completion(
model="deepseek/deepseek-reasoner",
messages=messages,
stream=False
)
reasoning_content = resp.choices[0].message.provider_specific_fields["reasoning_content"]
content = resp.choices[0].message.content
print(reasoning_content)
print(content)
View File
Whitespace-only changes.
+9
View File
@@ -0,0 +1,9 @@
from praisonaiagents import Agent
agent = Agent(
instructions="You are helpful Assisant",
llm="deepseek/deepseek-reasoner"
)
result = agent.start("Why sky is Blue?")
print(result)
+10
View File
@@ -0,0 +1,10 @@
from praisonaiagents import Agent
agent = Agent(
instructions="You are helpful Assisant",
llm="deepseek/deepseek-reasoner",
reasoning_steps=True
)
result = agent.start("Why sky is Blue?")
print(result)
+4
View File
@@ -0,0 +1,4 @@
from praisonaiagents import Agent
agent = Agent(instructions="You are a Markdown Agent, output in markdown format")
agent.start("Write a blog post about AI")
+5
View File
@@ -0,0 +1,5 @@
from markitdown import MarkItDown
md = MarkItDown()
result = md.convert("sample.txt")
print(result.text_content)
+220
View File
@@ -0,0 +1,220 @@
from mem0 import Memory
import logging
import json
import os
import time
from datetime import datetime
from typing import Dict, Any, Optional
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class MemoryManager:
def __init__(self):
"""Initialize Mem0 Memory manager with configuration"""
# Define the complete configuration with only supported fields
config = {
"version": "v1.1",
"custom_prompt": None,
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison/storage"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
# Ensure storage directory exists
storage_path = os.path.abspath("./.praison/storage")
if os.path.exists(storage_path):
logger.info(f"Clearing existing storage at {storage_path}")
import shutil
shutil.rmtree(storage_path)
os.makedirs(storage_path, exist_ok=True)
logger.info(f"Created storage path: {storage_path}")
# Initialize memory
self.memory = Memory.from_config(config)
logger.info("Memory manager initialized")
def pretty_print(self, data: Any) -> None:
"""Helper function to print memory data in a readable format"""
if isinstance(data, (dict, list)):
print(json.dumps(data, indent=2))
else:
print(data)
def extract_memory_id(self, result: Any) -> Optional[str]:
"""Extract memory ID from the result, handling different formats"""
try:
if isinstance(result, dict):
# v1.1 format
memories = result.get('results', [])
return memories[0]['id'] if memories else None
elif isinstance(result, list):
# v1.0 format
return result[0]['id'] if result else None
return None
except (KeyError, IndexError) as e:
logger.warning(f"Could not extract memory ID from result: {e}")
return None
def prepare_metadata(self, metadata: Optional[Dict]) -> Dict:
"""Prepare metadata by converting values to acceptable types"""
if not metadata:
return {}
clean_metadata = {}
for key, value in metadata.items():
if isinstance(value, (str, int, float, bool)):
clean_metadata[key] = value
elif isinstance(value, list):
clean_metadata[key] = ','.join(map(str, value))
elif isinstance(value, dict):
clean_metadata[key] = json.dumps(value)
else:
clean_metadata[key] = str(value)
return clean_metadata
def verify_memory_addition(self, user_id: str, max_retries: int = 3) -> bool:
"""Verify that memory was added successfully"""
for attempt in range(max_retries):
try:
time.sleep(0.5) # Brief pause to allow indexing
memories = self.memory.get_all(user_id=user_id)
if len(memories.get('results', [])) > 0:
return True
logger.warning(f"Memory not found on attempt {attempt + 1}")
except Exception as e:
logger.warning(f"Verification attempt {attempt + 1} failed: {e}")
if attempt < max_retries - 1:
time.sleep(1)
return False
def add_memory(self, text: str, user_id: Optional[str] = None, metadata: Optional[Dict] = None) -> Dict:
"""Add a new memory with error handling and verification"""
try:
logger.info(f"Adding memory for user {user_id}")
clean_metadata = self.prepare_metadata(metadata)
logger.debug(f"Prepared metadata: {clean_metadata}")
messages = [{"role": "user", "content": text}]
result = self.memory.add(
messages=messages,
user_id=user_id,
metadata=clean_metadata
)
if self.verify_memory_addition(user_id):
logger.info("Memory added and verified successfully")
else:
logger.warning("Memory addition could not be verified")
return result
except Exception as e:
logger.error(f"Failed to add memory: {str(e)}")
raise
def get_all_memories(self, user_id: Optional[str] = None) -> Dict:
"""Retrieve all memories for a user"""
try:
logger.info(f"Retrieving all memories for user {user_id}")
memories = self.memory.get_all(user_id=user_id)
count = len(memories.get('results', []))
logger.info(f"Retrieved {count} memories")
return memories
except Exception as e:
logger.error(f"Failed to retrieve memories: {str(e)}")
raise
def search_memories(self, query: str, user_id: Optional[str] = None, limit: int = 5) -> Dict:
"""Search memories with a query"""
try:
logger.info(f"Searching memories with query: {query}")
results = self.memory.search(
query=query,
user_id=user_id,
limit=limit
)
count = len(results.get('results', []))
logger.info(f"Found {count} matching memories")
return results
except Exception as e:
logger.error(f"Search failed: {str(e)}")
raise
def main():
try:
# Initialize memory manager
manager = MemoryManager()
# Add a test memory
print("\n1. Adding a new memory:")
metadata = {
"category": "hobbies",
"timestamp": datetime.now().isoformat(),
"tags": "tennis,learning",
"priority": 1,
"source": "user_input"
}
result = manager.add_memory(
text="I am working on improving my tennis skills. Suggest some online courses.",
user_id="alice",
metadata=metadata
)
manager.pretty_print(result)
# Wait briefly for indexing
time.sleep(1)
print("\n2. Retrieving all memories:")
all_memories = manager.get_all_memories(user_id="alice")
manager.pretty_print(all_memories)
print("\n3. Searching memories:")
search_results = manager.search_memories(
query="What are Alice's hobbies?",
user_id="alice",
limit=5
)
manager.pretty_print(search_results)
# Print summary
print("\nMemory Store Summary:")
total_memories = len(all_memories.get('results', []))
print(f"Total memories stored: {total_memories}")
if total_memories > 0:
print("Available memories:")
for mem in all_memories['results']:
print(f"- {mem.get('memory', 'No content')}")
except Exception as e:
logger.error(f"Main process failed: {str(e)}", exc_info=True)
raise
if __name__ == "__main__":
main()
+143
View File
@@ -0,0 +1,143 @@
from mem0 import Memory
import logging
import json
import os
from typing import Dict, Any, Optional
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class MemorySearcher:
def __init__(self):
"""Initialize Mem0 Memory searcher with configuration"""
# Define the configuration
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison/storage"),
"host": None,
"port": None
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small",
"embedding_dims": 1536
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0,
"max_tokens": 1000
}
}
}
# Initialize memory
self.memory = Memory.from_config(config)
logger.info("Memory searcher initialized")
def pretty_print(self, data: Any) -> None:
"""Helper function to print data in a readable format"""
if isinstance(data, (dict, list)):
print(json.dumps(data, indent=2))
else:
print(data)
def get_all_memories(self, user_id: Optional[str] = None) -> Dict:
"""Retrieve all memories for a user"""
try:
logger.info(f"Retrieving all memories for user {user_id}")
memories = self.memory.get_all(user_id=user_id)
count = len(memories.get('results', []))
logger.info(f"Retrieved {count} memories")
return memories
except Exception as e:
logger.error(f"Failed to retrieve memories: {str(e)}")
raise
def search_memories(self, query: str, user_id: Optional[str] = None, limit: int = 5) -> Dict:
"""Search memories with a query"""
try:
logger.info(f"Searching memories with query: {query}")
results = self.memory.search(
query=query,
user_id=user_id,
limit=limit
)
count = len(results.get('results', []))
logger.info(f"Found {count} matching memories")
return results
except Exception as e:
logger.error(f"Search failed: {str(e)}")
raise
def list_unique_users(self) -> list:
"""List all unique users in the memory store"""
try:
all_memories = self.memory.get_all()
users = set()
for memory in all_memories.get('results', []):
if 'user_id' in memory:
users.add(memory['user_id'])
return sorted(list(users))
except Exception as e:
logger.error(f"Failed to list users: {str(e)}")
raise
def main():
try:
# Initialize memory searcher
searcher = MemorySearcher()
# Get list of users
print("\n1. Available users in the memory store:")
users = searcher.list_unique_users()
searcher.pretty_print(users)
if not users:
print("No users found in the memory store. Please add some memories first.")
return
# Example user (using first user found)
example_user = users[0]
print(f"\n2. All memories for user '{example_user}':")
all_memories = searcher.get_all_memories(user_id=example_user)
searcher.pretty_print(all_memories)
print(f"\n3. Searching memories for user '{example_user}':")
search_results = searcher.search_memories(
query="What are their hobbies?",
user_id=example_user,
limit=5
)
searcher.pretty_print(search_results)
# Print summary
print("\nMemory Store Summary:")
total_memories = len(all_memories.get('results', []))
print(f"Total memories for {example_user}: {total_memories}")
if total_memories > 0:
print("Available memories:")
for mem in all_memories['results']:
print(f"- {mem.get('memory', 'No content')}")
if 'metadata' in mem:
print(f" Metadata: {mem['metadata']}")
except Exception as e:
logger.error(f"Main process failed: {str(e)}", exc_info=True)
raise
if __name__ == "__main__":
main()
+26
View File
@@ -0,0 +1,26 @@
from mem0 import Memory
import os
import json
# Basic configuration
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison",
}
}
}
# Initialize memory
memory = Memory.from_config(config)
# Search Alice's hobbies
search_results = memory.search(
query="KAG",
user_id="user1",
limit=5
)
print(search_results)
+46
View File
@@ -0,0 +1,46 @@
from mem0 import Memory
import os
import json
# Basic configuration
config = {
"version": "v1.1",
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": os.path.abspath("./.praison/storage")
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small"
}
},
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini"
}
}
}
# Initialize memory
memory = Memory.from_config(config)
# Search Alice's hobbies
search_results = memory.search(
query="What are Alice's hobbies?",
user_id="alice",
limit=5
)
# Print results in a readable format
print("\nAlice's Memories:")
for memory in search_results['results']:
print(f"\nMemory: {memory['memory']}")
print(f"Score: {memory['score']}")
if 'metadata' in memory:
print("Metadata:")
print(json.dumps(memory['metadata'], indent=2))
+1 -6
View File
@@ -51,9 +51,4 @@ agents = PraisonAIAgents(
)
# Run all tasks
result = agents.start()
# Print results
for task_id, task_result in result["task_results"].items():
print(f"\nTask {task_id} Result:")
print(task_result.raw)
agents.start()
+41
View File
@@ -0,0 +1,41 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
# Create PDF Analysis Agent
pdf_agent = Agent(
name="PDFAnalyst",
role="PDF Document Specialist",
goal="Analyze PDF documents to extract meaningful information",
backstory="""You are an expert in PDF document analysis and text extraction.
You excel at understanding document structure, extracting content, and analyzing textual information.""",
llm="gpt-4o-mini",
self_reflect=False
)
# 1. Task with PDF URL
task1 = Task(
name="analyze_pdf_url",
description="Extract and analyze content from this PDF document.",
expected_output="Detailed analysis of the PDF content and structure",
agent=pdf_agent,
input=["https://example.com/document.pdf"]
)
# 2. Task with Local PDF File
task2 = Task(
name="analyze_local_pdf",
description="What information can you extract from this PDF? Analyze its content.",
expected_output="Detailed analysis of the PDF content and structure",
agent=pdf_agent,
input=["document.pdf"]
)
# Create PraisonAIAgents instance
agents = PraisonAIAgents(
agents=[pdf_agent],
tasks=[task1, task2],
process="sequential",
verbose=1
)
# Run all tasks
agents.start()
+5
View File
@@ -0,0 +1,5 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
agent = Agent(instructions="You are a Planning Agent", tools=[duckduckgo])
agent.start("I want to go London next week, find me a good hotel and flight")
+4 -2
View File
@@ -7,7 +7,8 @@ from .agents.agents import PraisonAIAgents
from .task.task import Task
from .tools.tools import Tools
from .agents.autoagents import AutoAgents
from .memory.memory import Memory
from .knowledge.knowledge import Knowledge
from .knowledge.chunking import Chunking
from .main import (
TaskOutput,
ReflectionOutput,
@@ -36,7 +37,6 @@ __all__ = [
'TaskOutput',
'ReflectionOutput',
'AutoAgents',
'Memory',
'display_interaction',
'display_self_reflection',
'display_instruction',
@@ -48,4 +48,6 @@ __all__ = [
'register_display_callback',
'sync_display_callbacks',
'async_display_callbacks',
'Knowledge',
'Chunking'
]
File diff suppressed because it is too large. Load diff
+138 -31
View File
@@ -12,6 +12,7 @@ from ..agent.agent import Agent
from ..task.task import Task
from ..process.process import Process, LoopItems
import asyncio
import uuid
# Set up logger
logger = logging.getLogger(__name__)
@@ -44,10 +45,29 @@ def process_video(video_path: str, seconds_per_frame=2):
return base64_frames
class PraisonAIAgents:
def __init__(self, agents, tasks=None, verbose=0, completion_checker=None, max_retries=5, process="sequential", manager_llm=None, memory=False, memory_config=None, embedder=None):
def __init__(self, agents, tasks=None, verbose=0, completion_checker=None, max_retries=5, process="sequential", manager_llm=None, memory=False, memory_config=None, embedder=None, user_id=None, max_iter=10):
# Add check at the start if memory is requested
if memory:
try:
from ..memory.memory import Memory
MEMORY_AVAILABLE = True
except ImportError:
raise ImportError(
"Memory features requested but memory dependencies not installed. "
"Please install with: pip install \"praisonaiagents[memory]\""
)
if not agents:
raise ValueError("At least one agent must be provided")
self.run_id = str(uuid.uuid4()) # Auto-generate run_id
self.user_id = user_id or "praison" # Optional user_id
self.max_iter = max_iter # Add max_iter parameter
# Pass user_id to each agent
for agent in agents:
agent.user_id = self.user_id
self.agents = agents
self.tasks = {}
if max_retries < 3:
@@ -221,15 +241,46 @@ You need to do the following task: {task.description}.
Expected Output: {task.expected_output}.
"""
if task.context:
context_results = ""
for context_task in task.context:
if context_task.result:
context_results += f"Result of previous task {context_task.name if context_task.name else context_task.description}: {context_task.result.raw}\n"
else:
context_results += f"Previous task {context_task.name if context_task.name else context_task.description} had no result.\n"
context_results = [] # Use list to avoid duplicates
for context_item in task.context:
if isinstance(context_item, str):
context_results.append(f"Input Content:\n{context_item}")
elif isinstance(context_item, list):
context_results.append(f"Input Content: {' '.join(str(x) for x in context_item)}")
elif hasattr(context_item, 'result'): # Task object
if context_item.result:
context_results.append(
f"Result of previous task {context_item.name if context_item.name else context_item.description}:\n{context_item.result.raw}"
)
else:
context_results.append(
f"Previous task {context_item.name if context_item.name else context_item.description} has no result yet."
)
elif isinstance(context_item, dict) and "vector_store" in context_item:
from ..knowledge.knowledge import Knowledge
try:
# Handle both string and dict configs
cfg = context_item["vector_store"]
if isinstance(cfg, str):
cfg = json.loads(cfg)
knowledge = Knowledge(config={"vector_store": cfg}, verbose=self.verbose)
# Only use user_id as filter
db_results = knowledge.search(
task.description,
user_id=self.user_id if self.user_id else None
)
context_results.append(f"[DB Context]: {str(db_results)}")
except Exception as e:
context_results.append(f"[Vector DB Error]: {e}")
# Join unique context results
unique_contexts = list(dict.fromkeys(context_results)) # Remove duplicates
task_prompt += f"""
Here are the results of previous tasks that might be useful:\n
{context_results}
Context:
{' '.join(unique_contexts)}
"""
task_prompt += "Please provide only the final result of your work. Do not add any conversation or extra explanation."
@@ -339,7 +390,8 @@ Here are the results of previous tasks that might be useful:\n
task.status = "completed"
# Run execute_callback for memory operations
try:
await task.execute_callback(task_output)
# Use the new sync wrapper to avoid pending coroutine issues
task.execute_callback_sync(task_output)
except Exception as e:
logger.error(f"Error executing memory callback for task {task_id}: {e}")
logger.exception(e)
@@ -348,7 +400,12 @@ Here are the results of previous tasks that might be useful:\n
if task.callback:
try:
if asyncio.iscoroutinefunction(task.callback):
await task.callback(task_output)
if asyncio.get_event_loop().is_running():
asyncio.create_task(task.callback(task_output))
else:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(task.callback(task_output))
else:
task.callback(task_output)
except Exception as e:
@@ -381,7 +438,8 @@ Here are the results of previous tasks that might be useful:\n
tasks=self.tasks,
agents=self.agents,
manager_llm=self.manager_llm,
verbose=self.verbose
verbose=self.verbose,
max_iter=self.max_iter
)
if self.process == "workflow":
@@ -419,8 +477,16 @@ Here are the results of previous tasks that might be useful:\n
else:
self.run_task(task_id)
async def astart(self):
async def astart(self, content=None, **kwargs):
"""Async version of start method"""
if content:
# Add content to context of all tasks
for task in self.tasks.values():
if isinstance(content, (str, list)):
if not task.context:
task.context = []
task.context.append(content)
await self.arun_all_tasks()
return {
"task_status": self.get_all_tasks_status(),
@@ -477,16 +543,48 @@ You need to do the following task: {task.description}.
Expected Output: {task.expected_output}.
"""
if task.context:
context_results = ""
for context_task in task.context:
if context_task.result:
context_results += f"Result of previous task {context_task.name if context_task.name else context_task.description}: {context_task.result.raw}\n"
else:
context_results += f"Previous task {context_task.name if context_task.name else context_task.description} had no result.\n"
context_results = [] # Use list to avoid duplicates
for context_item in task.context:
if isinstance(context_item, str):
context_results.append(f"Input Content:\n{context_item}")
elif isinstance(context_item, list):
context_results.append(f"Input Content: {' '.join(str(x) for x in context_item)}")
elif hasattr(context_item, 'result'): # Task object
if context_item.result:
context_results.append(
f"Result of previous task {context_item.name if context_item.name else context_item.description}:\n{context_item.result.raw}"
)
else:
context_results.append(
f"Previous task {context_item.name if context_item.name else context_item.description} has no result yet."
)
elif isinstance(context_item, dict) and "vector_store" in context_item:
from ..knowledge.knowledge import Knowledge
try:
# Handle both string and dict configs
cfg = context_item["vector_store"]
if isinstance(cfg, str):
cfg = json.loads(cfg)
knowledge = Knowledge(config={"vector_store": cfg}, verbose=self.verbose)
# Only use user_id as filter
db_results = knowledge.search(
task.description,
user_id=self.user_id if self.user_id else None
)
context_results.append(f"[DB Context]: {str(db_results)}")
except Exception as e:
context_results.append(f"[Vector DB Error]: {e}")
# Join unique context results
unique_contexts = list(dict.fromkeys(context_results)) # Remove duplicates
task_prompt += f"""
Here are the results of previous tasks that might be useful:\n
{context_results}
Context:
{' '.join(unique_contexts)}
"""
# Add memory context if available
if task.memory:
try:
@@ -615,12 +713,8 @@ Here are the results of previous tasks that might be useful:\n
task.status = "completed"
# Run execute_callback for memory operations
try:
if asyncio.get_event_loop().is_running():
asyncio.create_task(task.execute_callback(task_output))
else:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(task.execute_callback(task_output))
# Use the new sync wrapper to avoid pending coroutine issues
task.execute_callback_sync(task_output)
except Exception as e:
logger.error(f"Error executing memory callback for task {task_id}: {e}")
logger.exception(e)
@@ -667,7 +761,8 @@ Here are the results of previous tasks that might be useful:\n
tasks=self.tasks,
agents=self.agents,
manager_llm=self.manager_llm,
verbose=self.verbose
verbose=self.verbose,
max_iter=self.max_iter
)
if self.process == "workflow":
@@ -706,12 +801,24 @@ Here are the results of previous tasks that might be useful:\n
return str(agent[0])
return None
def start(self):
def start(self, content=None, **kwargs):
"""Start agent execution with optional content and config"""
if content:
# Add content to context of all tasks
for task in self.tasks.values():
if isinstance(content, (str, list)):
# If context is empty, initialize it
if not task.context:
task.context = []
# Add content to context
task.context.append(content)
# Run tasks as before
self.run_all_tasks()
return {
"task_status": self.get_all_tasks_status(),
"task_results": {task_id: self.get_task_result(task_id) for task_id in self.tasks}
}
}
def set_state(self, key: str, value: Any) -> None:
"""Set a state value"""
@@ -0,0 +1,8 @@
"""
PraisonAI Knowledge - Advanced knowledge management system with configurable features
"""
from praisonaiagents.knowledge.knowledge import Knowledge
from praisonaiagents.knowledge.chunking import Chunking
__all__ = ["Knowledge", "Chunking"]
@@ -0,0 +1,182 @@
from typing import List, Union, Optional, Dict, Any
from functools import cached_property
import importlib
class Chunking:
"""A unified class for text chunking with various chunking strategies."""
CHUNKER_PARAMS = {
'token': ['chunk_size', 'chunk_overlap', 'tokenizer'],
'word': ['chunk_size', 'chunk_overlap', 'tokenizer'],
'sentence': ['chunk_size', 'chunk_overlap', 'tokenizer'],
'semantic': ['chunk_size', 'embedding_model', 'tokenizer'],
'sdpm': ['chunk_size', 'embedding_model', 'tokenizer'],
'late': ['chunk_size', 'embedding_model', 'tokenizer'],
'recursive': ['chunk_size', 'tokenizer']
}
@cached_property
def SUPPORTED_CHUNKERS(self) -> Dict[str, Any]:
"""Lazy load chunker classes."""
try:
from chonkie.chunker import (
TokenChunker,
WordChunker,
SentenceChunker,
SemanticChunker,
SDPMChunker,
LateChunker,
RecursiveChunker
)
except ImportError:
raise ImportError(
"chonkie package not found. Please install it using: pip install 'praisonaiagents[knowledge]'"
)
return {
'token': TokenChunker,
'word': WordChunker,
'sentence': SentenceChunker,
'semantic': SemanticChunker,
'sdpm': SDPMChunker,
'late': LateChunker,
'recursive': RecursiveChunker
}
def __init__(
self,
chunker_type: str = 'token',
chunk_size: int = 512,
chunk_overlap: int = 128,
tokenizer: str = "gpt2",
embedding_model: Optional[Union[str, Any]] = None,
**kwargs
):
"""Initialize the Chunking class."""
if chunker_type not in self.CHUNKER_PARAMS:
raise ValueError(
f"Unsupported chunker type: {chunker_type}. "
f"Must be one of: {list(self.CHUNKER_PARAMS.keys())}"
)
self.chunker_type = chunker_type
self.chunk_size = chunk_size
self.chunk_overlap = chunk_overlap
self.tokenizer = tokenizer
self._embedding_model = embedding_model
self.kwargs = kwargs
# Initialize these as None for lazy loading
self._chunker = None
self._embeddings = None
@cached_property
def embedding_model(self):
"""Lazy load the embedding model."""
if self._embedding_model is None and self.chunker_type in ['semantic', 'sdpm', 'late']:
from chonkie.embeddings import AutoEmbeddings
return AutoEmbeddings.get_embeddings("all-MiniLM-L6-v2")
elif isinstance(self._embedding_model, str):
from chonkie.embeddings import AutoEmbeddings
return AutoEmbeddings.get_embeddings(self._embedding_model)
return self._embedding_model
def _get_chunker_params(self) -> Dict[str, Any]:
"""Get the appropriate parameters for the current chunker type."""
allowed_params = self.CHUNKER_PARAMS[self.chunker_type]
params = {'chunk_size': self.chunk_size}
if 'chunk_overlap' in allowed_params:
params['chunk_overlap'] = self.chunk_overlap
if 'tokenizer' in allowed_params:
if self.chunker_type in ['semantic', 'sdpm', 'late']:
params['tokenizer'] = self.embedding_model.get_tokenizer_or_token_counter()
else:
params['tokenizer'] = self.tokenizer
if 'embedding_model' in allowed_params:
params['embedding_model'] = self.embedding_model
# Add any additional kwargs that are in allowed_params
for key, value in self.kwargs.items():
if key in allowed_params:
params[key] = value
return params
@cached_property
def chunker(self):
"""Lazy load the chunker instance."""
if self._chunker is None:
chunker_cls = self.SUPPORTED_CHUNKERS[self.chunker_type]
common_params = self._get_chunker_params()
self._chunker = chunker_cls(**common_params)
return self._chunker
def _get_overlap_refinery(self, context_size: Optional[int] = None, **kwargs):
"""Lazy load the overlap refinery."""
try:
from chonkie.refinery import OverlapRefinery
except ImportError:
raise ImportError("Failed to import OverlapRefinery from chonkie.refinery")
if context_size is None:
context_size = self.chunk_overlap
return OverlapRefinery(
context_size=context_size,
tokenizer=self.chunker.tokenizer,
**kwargs
)
def add_overlap_context(
self,
chunks: List[Any],
context_size: int = None,
mode: str = "suffix",
merge_context: bool = True
) -> List[Any]:
"""Add overlap context to chunks using OverlapRefinery."""
refinery = self._get_overlap_refinery(
context_size=context_size,
mode=mode,
merge_context=merge_context
)
return refinery.refine(chunks)
def chunk(
self,
text: Union[str, List[str]],
add_context: bool = False,
context_params: Optional[Dict[str, Any]] = None
) -> Union[List[Any], List[List[Any]]]:
"""Chunk text using the configured chunking strategy."""
chunks = self.chunker(text)
if add_context:
context_params = context_params or {}
if isinstance(text, str):
chunks = self.add_overlap_context(chunks, **context_params)
else:
chunks = [self.add_overlap_context(c, **context_params) for c in chunks]
return chunks
def __call__(
self,
text: Union[str, List[str]],
add_context: bool = False,
context_params: Optional[Dict[str, Any]] = None
) -> Union[List[Any], List[List[Any]]]:
"""Make the Chunking instance callable."""
return self.chunk(text, add_context, context_params)
def __repr__(self) -> str:
"""String representation of the Chunking instance."""
return (
f"Chunking(chunker_type='{self.chunker_type}', "
f"chunk_size={self.chunk_size}, "
f"chunk_overlap={self.chunk_overlap})"
)
@@ -0,0 +1,321 @@
import os
import logging
import uuid
import time
from .chunking import Chunking
from functools import cached_property
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn
logger = logging.getLogger(__name__)
class CustomMemory:
@classmethod
def from_config(cls, config):
from mem0 import Memory
return type('CustomMemory', (Memory,), {
'_add_to_vector_store': cls._add_to_vector_store
}).from_config(config)
@staticmethod
def _add_to_vector_store(self, messages, metadata, filters):
# Custom implementation that doesn't use LLM
parsed_messages = "\n".join([msg["content"] for msg in messages])
# Create a simple fact without using LLM
new_retrieved_facts = [parsed_messages]
# Process embeddings and continue with vector store operations
new_message_embeddings = {}
for new_mem in new_retrieved_facts:
messages_embeddings = self.embedding_model.embed(new_mem)
new_message_embeddings[new_mem] = messages_embeddings
# Create the memory
memory_id = self._create_memory(
data=parsed_messages,
existing_embeddings=new_message_embeddings,
metadata=metadata
)
return [{
"id": memory_id,
"memory": parsed_messages,
"event": "ADD"
}]
class Knowledge:
def __init__(self, config=None, verbose=None):
self._config = config
self._verbose = verbose or 0
os.environ['ANONYMIZED_TELEMETRY'] = 'False' # Chromadb
# Configure logging levels based on verbose setting
if not self._verbose:
# Suppress logs from all relevant dependencies
for logger_name in [
'mem0',
'chromadb',
'local_persistent_hnsw',
'_client',
'main'
]:
logging.getLogger(logger_name).setLevel(logging.WARNING)
# Disable OpenAI API request logging
logging.getLogger('openai').setLevel(logging.WARNING)
# Set root logger to warning to catch any uncategorized logs
logging.getLogger().setLevel(logging.WARNING)
@cached_property
def _deps(self):
try:
from markitdown import MarkItDown
import chromadb
return {
'chromadb': chromadb,
'markdown': MarkItDown()
}
except ImportError:
raise ImportError(
"Required packages not installed. Please install using: "
'pip install "praisonaiagents[knowledge]"'
)
@cached_property
def config(self):
# Generate unique collection name for each instance (only if not provided in config)
default_collection = f"test_{int(time.time())}_{str(uuid.uuid4())[:8]}"
persist_dir = ".praison"
# Create persistent client config
base_config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": default_collection,
"path": persist_dir,
"client": self._deps['chromadb'].PersistentClient(path=persist_dir),
"host": None,
"port": None
}
},
"version": "v1.1",
"custom_prompt": "Return {{\"facts\": [text]}} where text is the exact input provided and json response"
}
# If config is provided, merge it with base config
if self._config:
# Merge version if provided
if "version" in self._config:
base_config["version"] = self._config["version"]
# Merge vector_store config
if "vector_store" in self._config:
if "provider" in self._config["vector_store"]:
base_config["vector_store"]["provider"] = self._config["vector_store"]["provider"]
if "config" in self._config["vector_store"]:
config_copy = self._config["vector_store"]["config"].copy()
# Only exclude client as it's managed internally
if "client" in config_copy:
del config_copy["client"]
base_config["vector_store"]["config"].update(config_copy)
# Merge embedder config if provided
if "embedder" in self._config:
base_config["embedder"] = self._config["embedder"]
# Merge llm config if provided
if "llm" in self._config:
base_config["llm"] = self._config["llm"]
return base_config
@cached_property
def memory(self):
try:
return CustomMemory.from_config(self.config)
except (NotImplementedError, ValueError) as e:
if "list_collections" in str(e) or "Extra fields not allowed" in str(e):
# Keep only allowed fields
vector_store_config = {
"collection_name": self.config["vector_store"]["config"]["collection_name"],
"path": self.config["vector_store"]["config"]["path"]
}
self.config["vector_store"]["config"] = vector_store_config
from mem0 import Memory
return Memory.from_config(self.config)
raise
@cached_property
def markdown(self):
return self._deps['markdown']
@cached_property
def chunker(self):
return Chunking(
chunker_type='recursive',
chunk_size=512,
chunk_overlap=50
)
def _log(self, message, level=2):
"""Internal logging helper"""
if self._verbose and self._verbose >= level:
logger.info(message)
def store(self, content, user_id=None, agent_id=None, run_id=None, metadata=None):
"""Store a memory."""
try:
if isinstance(content, str):
if any(content.lower().endswith(ext) for ext in ['.pdf', '.doc', '.docx', '.txt']):
self._log(f"Content appears to be a file path, processing file: {content}")
return self.add(content, user_id=user_id, agent_id=agent_id, run_id=run_id, metadata=metadata)
content = content.strip()
if not content:
return []
result = self.memory.add(content, user_id=user_id, agent_id=agent_id, run_id=run_id, metadata=metadata)
self._log(f"Store operation result: {result}")
return result
except Exception as e:
logger.error(f"Error storing content: {str(e)}")
return []
def get_all(self, user_id=None, agent_id=None, run_id=None):
"""Retrieve all memories."""
return self.memory.get_all(user_id=user_id, agent_id=agent_id, run_id=run_id)
def get(self, memory_id):
"""Retrieve a specific memory by ID."""
return self.memory.get(memory_id)
def search(self, query, user_id=None, agent_id=None, run_id=None):
"""Search for memories related to a query."""
return self.memory.search(query, user_id=user_id, agent_id=agent_id, run_id=run_id)
def update(self, memory_id, data):
"""Update a memory."""
return self.memory.update(memory_id, data)
def history(self, memory_id):
"""Get the history of changes for a memory."""
return self.memory.history(memory_id)
def delete(self, memory_id):
"""Delete a memory."""
self.memory.delete(memory_id)
def delete_all(self, user_id=None, agent_id=None, run_id=None):
"""Delete all memories."""
self.memory.delete_all(user_id=user_id, agent_id=agent_id, run_id=run_id)
def reset(self):
"""Reset all memories."""
self.memory.reset()
def normalize_content(self, content):
"""Normalize content for consistent storage."""
# Example normalization: strip whitespace, convert to lowercase
return content.strip().lower()
def add(self, file_path, user_id=None, agent_id=None, run_id=None, metadata=None):
"""Read file content and store it in memory.
Args:
file_path: Can be:
- A string path to local file
- A URL string
- A list containing file paths and/or URLs
"""
if isinstance(file_path, (list, tuple)):
results = []
for path in file_path:
result = self._process_single_input(path, user_id, agent_id, run_id, metadata)
results.extend(result.get('results', []))
return {'results': results, 'relations': []}
return self._process_single_input(file_path, user_id, agent_id, run_id, metadata)
def _process_single_input(self, input_path, user_id=None, agent_id=None, run_id=None, metadata=None):
"""Process a single input which can be a file path or URL."""
try:
# Define supported file extensions
DOCUMENT_EXTENSIONS = {
'document': ('.pdf', '.ppt', '.pptx', '.doc', '.docx', '.xls', '.xlsx'),
'media': ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.mp3', '.wav', '.ogg', '.m4a'),
'text': ('.txt', '.csv', '.json', '.xml', '.md', '.html', '.htm'),
'archive': '.zip'
}
# Check if input is URL
if isinstance(input_path, str) and (input_path.startswith('http://') or input_path.startswith('https://')):
self._log(f"Processing URL: {input_path}")
raise NotImplementedError("URL processing not yet implemented")
# Check if input ends with any supported extension
is_supported_file = any(input_path.lower().endswith(ext)
for exts in DOCUMENT_EXTENSIONS.values()
for ext in (exts if isinstance(exts, tuple) else (exts,)))
if is_supported_file:
self._log(f"Processing as file path: {input_path}")
if not os.path.exists(input_path):
logger.error(f"File not found: {input_path}")
raise FileNotFoundError(f"File not found: {input_path}")
file_ext = '.' + input_path.lower().split('.')[-1] # Get extension reliably
# Process file based on type
if file_ext in DOCUMENT_EXTENSIONS['text']:
with open(input_path, 'r', encoding='utf-8') as file:
content = file.read().strip()
if not content:
raise ValueError("Empty text file")
memories = [self.normalize_content(content)]
else:
# Use MarkItDown for documents and media
result = self.markdown.convert(input_path)
content = result.text_content
if not content:
raise ValueError("No content could be extracted from file")
chunks = self.chunker.chunk(content)
memories = [chunk.text.strip() if hasattr(chunk, 'text') else str(chunk).strip()
for chunk in chunks if chunk]
# Set metadata for file
if not metadata:
metadata = {}
metadata['file_type'] = file_ext.lstrip('.')
metadata['filename'] = os.path.basename(input_path)
else:
# Treat as raw text content only if no file extension
memories = [self.normalize_content(input_path)]
# Create progress display
progress = Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
BarColumn(),
TaskProgressColumn(),
transient=True
)
# Store memories with progress bar
all_results = []
with progress:
store_task = progress.add_task(f"Adding to Knowledge from {os.path.basename(input_path)}", total=len(memories))
for memory in memories:
if memory:
memory_result = self.store(memory, user_id=user_id, agent_id=agent_id,
run_id=run_id, metadata=metadata)
if memory_result:
all_results.extend(memory_result.get('results', []))
progress.advance(store_task)
return {'results': all_results, 'relations': []}
except Exception as e:
logger.error(f"Error processing input {input_path}: {str(e)}", exc_info=True)
raise
+20
View File
@@ -0,0 +1,20 @@
import logging
import warnings
# Suppress all relevant logs at module level
logging.getLogger("litellm").setLevel(logging.ERROR)
logging.getLogger("openai").setLevel(logging.ERROR)
logging.getLogger("httpx").setLevel(logging.ERROR)
logging.getLogger("httpcore").setLevel(logging.ERROR)
logging.getLogger("pydantic").setLevel(logging.ERROR)
# Suppress pydantic warnings
warnings.filterwarnings("ignore", category=UserWarning, module="pydantic")
# Configure logging to suppress all INFO messages
logging.basicConfig(level=logging.WARNING)
# Import after suppressing warnings
from .llm import LLM, LLMContextLengthExceededException
__all__ = ["LLM", "LLMContextLengthExceededException"]
File diff suppressed because it is too large. Load diff
+14 -1
View File
@@ -14,6 +14,15 @@ from rich.logging import RichHandler
from rich.live import Live
import asyncio
# # Configure root logger
# logging.basicConfig(level=logging.WARNING)
# Suppress litellm logs
logging.getLogger("litellm").handlers = []
logging.getLogger("litellm.utils").handlers = []
logging.getLogger("litellm").propagate = False
logging.getLogger("litellm.utils").propagate = False
LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper()
logging.basicConfig(
@@ -23,6 +32,10 @@ logging.basicConfig(
handlers=[RichHandler(rich_tracebacks=True)]
)
# Add these lines to suppress markdown parser debug logs
logging.getLogger('markdown_it').setLevel(logging.WARNING)
logging.getLogger('rich.markdown').setLevel(logging.WARNING)
# Global list to store error logs
error_logs = []
@@ -340,7 +353,7 @@ class ReflectionOutput(BaseModel):
reflection: str
satisfactory: Literal["yes", "no"]
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
client = OpenAI(api_key=(os.environ["OPENAI_API_KEY"] if os.environ.get("OPENAI_API_KEY") else "xxxx"))
class TaskOutput(BaseModel):
description: str
+1 -1
View File
@@ -15,7 +15,7 @@ try:
CHROMADB_AVAILABLE = True
except ImportError:
CHROMADB_AVAILABLE = False
logger.warning("To use memory features, please run: pip install \"praisonaiagents[memory]\"")
pass
try:
import mem0
+157 -76
View File
@@ -5,6 +5,8 @@ from pydantic import BaseModel
from ..agent.agent import Agent
from ..task.task import Task
from ..main import display_error, client
import csv
import os
class LoopItems(BaseModel):
items: List[Any]
@@ -62,46 +64,47 @@ class Process:
if prev_task and prev_task.result:
# Handle loop data
if current_task.task_type == "loop":
# create a loop manager Agent
loop_manager = Agent(
name="Loop Manager",
role="Loop data processor",
goal="Process loop data and convert it to list format",
backstory="Expert at handling loop data and converting it to proper format",
llm=self.manager_llm,
verbose=self.verbose,
markdown=True
)
# # create a loop manager Agent
# loop_manager = Agent(
# name="Loop Manager",
# role="Loop data processor",
# goal="Process loop data and convert it to list format",
# backstory="Expert at handling loop data and converting it to proper format",
# llm=self.manager_llm,
# verbose=self.verbose,
# markdown=True
# )
# get the loop data convert it to list using calling Agent class chat
loop_prompt = f"""
Process this data into a list format:
{prev_task.result.raw}
# # get the loop data convert it to list using calling Agent class chat
# loop_prompt = f"""
# Process this data into a list format:
# {prev_task.result.raw}
Return a JSON object with an 'items' array containing the items to process.
"""
if current_task.async_execution:
loop_data_str = await loop_manager.achat(
prompt=loop_prompt,
output_json=LoopItems
)
else:
loop_data_str = loop_manager.chat(
prompt=loop_prompt,
output_json=LoopItems
)
# Return a JSON object with an 'items' array containing the items to process.
# """
# if current_task.async_execution:
# loop_data_str = await loop_manager.achat(
# prompt=loop_prompt,
# output_json=LoopItems
# )
# else:
# loop_data_str = loop_manager.chat(
# prompt=loop_prompt,
# output_json=LoopItems
# )
try:
# The response will already be parsed into LoopItems model
loop_data[f"loop_{current_task.name}"] = {
"items": loop_data_str.items,
"index": 0,
"remaining": len(loop_data_str.items)
}
context += f"\nCurrent loop item: {loop_data_str.items[0]}"
except Exception as e:
display_error(f"Failed to process loop data: {e}")
context += f"\n{prev_name}: {prev_task.result.raw}"
# try:
# # The response will already be parsed into LoopItems model
# loop_data[f"loop_{current_task.name}"] = {
# "items": loop_data_str.items,
# "index": 0,
# "remaining": len(loop_data_str.items)
# }
# context += f"\nCurrent loop item: {loop_data_str.items[0]}"
# except Exception as e:
# display_error(f"Failed to process loop data: {e}")
# context += f"\n{prev_name}: {prev_task.result.raw}"
context += f"\n{prev_name}: {prev_task.result.raw}"
else:
context += f"\n{prev_name}: {prev_task.result.raw}"
@@ -144,13 +147,17 @@ Return a JSON object with an 'items' array containing the items to process.
next_task = None
if current_task and current_task.result:
if current_task.task_type in ["decision", "loop"]:
result = current_task.result.raw.lower()
# MINIMAL CHANGE: use pydantic decision if present
decision_str = current_task.result.raw.lower()
if current_task.result.pydantic and hasattr(current_task.result.pydantic, "decision"):
decision_str = current_task.result.pydantic.decision.lower()
# Check conditions
for condition, tasks in current_task.condition.items():
if condition.lower() in result:
if condition.lower() == decision_str:
# Handle both list and direct string values
task_value = tasks[0] if isinstance(tasks, list) else tasks
if not task_value or task_value == "exit": # If empty or explicit exit
if not task_value or task_value == "exit":
logging.info("Workflow exit condition met, ending workflow")
current_task = None
break
@@ -322,7 +329,76 @@ Provide a JSON with the structure:
if not start_task:
start_task = list(self.tasks.values())[0]
logging.info("No start task marked, using first task")
# If loop type and no input_file, default to tasks.csv
if start_task and start_task.task_type == "loop" and not start_task.input_file:
start_task.input_file = "tasks.csv"
# --- If loop + input_file, read file & create tasks
if start_task and start_task.task_type == "loop" and getattr(start_task, "input_file", None):
try:
file_ext = os.path.splitext(start_task.input_file)[1].lower()
new_tasks = []
if file_ext == ".csv":
# existing CSV reading logic
with open(start_task.input_file, "r", encoding="utf-8") as f:
# Try as simple CSV first
reader = csv.reader(f)
previous_task = None
for i, row in enumerate(reader):
if row: # Skip empty rows
task_desc = row[0] # Take first column
row_task = Task(
description=task_desc, # Keep full row as description
agent=start_task.agent,
name=task_desc, # Use first column as name
is_start=(i == 0),
task_type="task",
condition={
"complete": ["next"],
"retry": ["current"]
}
)
self.tasks[row_task.id] = row_task
new_tasks.append(row_task)
if previous_task:
previous_task.next_tasks = [row_task.name]
previous_task.condition["complete"] = [row_task.name]
previous_task = row_task
else:
# If not CSV, read lines
with open(start_task.input_file, "r", encoding="utf-8") as f:
lines = f.read().splitlines()
previous_task = None
for i, line in enumerate(lines):
row_task = Task(
description=line.strip(),
agent=start_task.agent,
name=line.strip(),
is_start=(i == 0),
task_type="task",
condition={
"complete": ["next"],
"retry": ["current"]
}
)
self.tasks[row_task.id] = row_task
new_tasks.append(row_task)
if previous_task:
previous_task.next_tasks = [row_task.name]
previous_task.condition["complete"] = [row_task.name]
previous_task = row_task
if new_tasks:
start_task = new_tasks[0]
logging.info(f"Created {len(new_tasks)} tasks from: {start_task.input_file}")
except Exception as e:
logging.error(f"Failed to read file tasks: {e}")
# end of the new block
current_task = start_task
visited_tasks = set()
loop_data = {} # Store loop-specific data
@@ -346,40 +422,41 @@ Provide a JSON with the structure:
if prev_task and prev_task.result:
# Handle loop data
if current_task.task_type == "loop":
# create a loop manager Agent
loop_manager = Agent(
name="Loop Manager",
role="Loop data processor",
goal="Process loop data and convert it to list format",
backstory="Expert at handling loop data and converting it to proper format",
llm=self.manager_llm,
verbose=self.verbose,
markdown=True
)
# # create a loop manager Agent
# loop_manager = Agent(
# name="Loop Manager",
# role="Loop data processor",
# goal="Process loop data and convert it to list format",
# backstory="Expert at handling loop data and converting it to proper format",
# llm=self.manager_llm,
# verbose=self.verbose,
# markdown=True
# )
# get the loop data convert it to list using calling Agent class chat
loop_prompt = f"""
Process this data into a list format:
{prev_task.result.raw}
# # get the loop data convert it to list using calling Agent class chat
# loop_prompt = f"""
# Process this data into a list format:
# {prev_task.result.raw}
Return a JSON object with an 'items' array containing the items to process.
"""
loop_data_str = loop_manager.chat(
prompt=loop_prompt,
output_json=LoopItems
)
# Return a JSON object with an 'items' array containing the items to process.
# """
# loop_data_str = loop_manager.chat(
# prompt=loop_prompt,
# output_json=LoopItems
# )
try:
# The response will already be parsed into LoopItems model
loop_data[f"loop_{current_task.name}"] = {
"items": loop_data_str.items,
"index": 0,
"remaining": len(loop_data_str.items)
}
context += f"\nCurrent loop item: {loop_data_str.items[0]}"
except Exception as e:
display_error(f"Failed to process loop data: {e}")
context += f"\n{prev_name}: {prev_task.result.raw}"
# try:
# # The response will already be parsed into LoopItems model
# loop_data[f"loop_{current_task.name}"] = {
# "items": loop_data_str.items,
# "index": 0,
# "remaining": len(loop_data_str.items)
# }
# context += f"\nCurrent loop item: {loop_data_str.items[0]}"
# except Exception as e:
# display_error(f"Failed to process loop data: {e}")
# context += f"\n{prev_name}: {prev_task.result.raw}"
context += f"\n{prev_name}: {prev_task.result.raw}"
else:
context += f"\n{prev_name}: {prev_task.result.raw}"
@@ -396,7 +473,7 @@ Return a JSON object with an 'items' array containing the items to process.
yield task_id
visited_tasks.add(task_id)
# Reset completed task to "not started" so it can run again
# Reset completed task to "not started" so it can run again: Only for workflow because some tasks may be revisited
if self.tasks[task_id].status == "completed":
logging.debug(f"Task {task_id} was completed, resetting to 'not started' for next iteration.")
self.tasks[task_id].status = "not started"
@@ -422,13 +499,17 @@ Return a JSON object with an 'items' array containing the items to process.
next_task = None
if current_task and current_task.result:
if current_task.task_type in ["decision", "loop"]:
result = current_task.result.raw.lower()
# MINIMAL CHANGE: use pydantic decision if present
decision_str = current_task.result.raw.lower()
if current_task.result.pydantic and hasattr(current_task.result.pydantic, "decision"):
decision_str = current_task.result.pydantic.decision.lower()
# Check conditions
for condition, tasks in current_task.condition.items():
if condition.lower() in result:
if condition.lower() == decision_str:
# Handle both list and direct string values
task_value = tasks[0] if isinstance(tasks, list) else tasks
if not task_value or task_value == "exit": # If empty or explicit exit
if not task_value or task_value == "exit":
logging.info("Workflow exit condition met, ending workflow")
current_task = None
break
+104 -4
View File
@@ -1,6 +1,6 @@
import logging
import asyncio
from typing import List, Optional, Dict, Any, Type, Callable, Union, Coroutine
from typing import List, Optional, Dict, Any, Type, Callable, Union, Coroutine, Literal
from pydantic import BaseModel
from ..main import TaskOutput
from ..agent.agent import Agent
@@ -19,7 +19,7 @@ class Task:
agent: Optional[Agent] = None,
name: Optional[str] = None,
tools: Optional[List[Any]] = None,
context: Optional[List["Task"]] = None,
context: Optional[List[Union[str, List, 'Task']]] = None,
async_execution: Optional[bool] = False,
config: Optional[Dict[str, Any]] = None,
output_file: Optional[str] = None,
@@ -37,8 +37,21 @@ class Task:
is_start: bool = False,
loop_state: Optional[Dict[str, Union[str, int]]] = None,
memory=None,
quality_check=True
quality_check=True,
input_file: Optional[str] = None
):
# Add check if memory config is provided
if memory is not None or (config and config.get('memory_config')):
try:
from ..memory.memory import Memory
MEMORY_AVAILABLE = True
except ImportError:
raise ImportError(
"Memory features requested in Task but memory dependencies not installed. "
"Please install with: pip install \"praisonaiagents[memory]\""
)
self.input_file = input_file
self.id = str(uuid.uuid4()) if id is None else str(id)
self.name = name
self.description = description
@@ -83,6 +96,47 @@ class Task:
# Track previous tasks based on next_tasks relationships
self.previous_tasks = []
# If task_type="decision" and output_pydantic is not set
if self.task_type == "decision" and not self.output_pydantic:
from pydantic import BaseModel
from typing import Literal
# Gather condition keys for the "decision" field
condition_keys = list(self.condition.keys())
if not condition_keys:
# Fall back to placeholders if nothing is specified
condition_keys = ["next_task", "exit"]
# Create a dynamic literal type from condition keys
DecisionLiteral = Literal.__getitem__(tuple(condition_keys))
class DecisionModel(BaseModel):
response: str
decision: DecisionLiteral
self.output_pydantic = DecisionModel
# If task_type="loop" and output_pydantic is not set
if self.task_type == "loop" and not self.output_pydantic:
from pydantic import BaseModel
from typing import Literal
# Gather condition keys for the "decision" field
condition_keys = list(self.condition.keys())
if not condition_keys:
# Fall back to placeholders if nothing is specified
condition_keys = ["next_item", "exit"]
# Create a dynamic literal type
LoopLiteral = Literal.__getitem__(tuple(condition_keys))
class LoopModel(BaseModel):
response: str
decision: LoopLiteral
loop_id: str # Additional field for loop
self.output_pydantic = LoopModel
def __str__(self):
return f"Task(name='{self.name if self.name else 'None'}', description='{self.description}', agent='{self.agent.name if self.agent else 'None'}', status='{self.status}')"
@@ -219,4 +273,50 @@ class Task:
self.callback(task_output)
except Exception as e:
logger.error(f"Task {self.id}: Failed to execute callback: {e}")
logger.exception(e)
logger.exception(e)
task_prompt = f"""
You need to do the following task: {self.description}.
Expected Output: {self.expected_output}.
"""
if self.context:
context_results = [] # Use list to avoid duplicates
for context_item in self.context:
if isinstance(context_item, str):
context_results.append(f"Input Content:\n{context_item}")
elif isinstance(context_item, list):
context_results.append(f"Input Content: {' '.join(str(x) for x in context_item)}")
elif hasattr(context_item, 'result'): # Task object
if context_item.result:
context_results.append(
f"Result of previous task {context_item.name if context_item.name else context_item.description}:\n{context_item.result.raw}"
)
else:
context_results.append(
f"Previous task {context_item.name if context_item.name else context_item.description} has no result yet."
)
# Join unique context results
unique_contexts = list(dict.fromkeys(context_results)) # Remove duplicates
task_prompt += f"""
Context:
{' '.join(unique_contexts)}
"""
def execute_callback_sync(self, task_output: TaskOutput) -> None:
"""
Synchronous wrapper to ensure that execute_callback is awaited,
preventing 'Task was destroyed but pending!' warnings if called
from non-async code.
"""
import asyncio
try:
loop = asyncio.get_running_loop()
if loop.is_running():
loop.create_task(self.execute_callback(task_output))
else:
loop.run_until_complete(self.execute_callback(task_output))
except RuntimeError:
# If no loop is running in this context
asyncio.run(self.execute_callback(task_output))
@@ -160,6 +160,9 @@ class PandasTools:
Dict: Summary statistics and information
"""
try:
if not isinstance(df, pd.DataFrame):
raise TypeError(f"Expected pandas DataFrame, got {type(df).__name__}")
numeric_summary = df.describe().to_dict()
# Convert numpy types to native Python types
for col in numeric_summary:
@@ -145,7 +145,15 @@ class YFinanceTools:
return [{"error": "yfinance package not available"}]
hist = ticker.history(period=period, interval=interval, start=start, end=end)
return hist.reset_index().to_dict('records')
data = hist.reset_index().to_dict('records')
# Convert timestamps to ISO format strings
for record in data:
if 'Date' in record and hasattr(record['Date'], 'isoformat'):
record['Date'] = record['Date'].isoformat()
if 'Datetime' in record and hasattr(record['Datetime'], 'isoformat'):
record['Datetime'] = record['Datetime'].isoformat()
return data
except Exception as e:
error_msg = f"Error fetching historical data: {str(e)}"
logging.error(error_msg)
+19
View File
@@ -0,0 +1,19 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import execute_code, analyze_code, format_code, lint_code, disassemble_code # Code Tools
from praisonaiagents.tools import execute_command, list_processes, kill_process, get_system_info # Shell Tools
from praisonaiagents.tools import duckduckgo # Web Search Tool
agent = Agent(
instructions="You are a Programming Agent", self_reflect=True, min_reflect=5, max_reflect=10,
tools=[execute_code, analyze_code, format_code, lint_code, disassemble_code, execute_command, list_processes, kill_process, get_system_info, duckduckgo]
)
agent.start(
"Write a python script using yfinance to find the stock price of Tesla"
"First check if required packages are installed"
"Run it using execute_code"
"execute_command if you want to run any terminal command"
"search internet using duckduckgo if you want to know update python package information"
"Analyse the output using analyze_code and fix error if required"
"if no package is installed, install it"
"then run the code"
)
+23 -3
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "praisonaiagents"
version = "0.0.35"
version = "0.0.53"
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
authors = [
{ name="Mervin Praison" }
@@ -17,5 +17,25 @@ dependencies = [
[project.optional-dependencies]
memory = [
"chromadb>=0.6.0"
]
"chromadb>=0.5.23"
]
knowledge = [
"mem0ai>=0.1.0",
"chromadb==0.5.23",
"markitdown",
"chonkie"
]
# Add LLM dependencies
llm = [
"litellm>=1.50.0",
"pydantic>=2.4.2"
]
# Combined features
all = [
"praisonaiagents[memory]",
"praisonaiagents[knowledge]",
"praisonaiagents[llm]"
]
+5
View File
@@ -0,0 +1,5 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
agent = Agent(instructions="You are a Recommendation Agent", tools=[duckduckgo])
agent.start("Recommend me a good movie to watch in 2025")
+22
View File
@@ -0,0 +1,22 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
agent = Agent(
instructions="You are a loop agent that creating a loop of tasks.",
llm="gpt-4o-mini"
)
task = Task(
description="Create the list of tasks to be looped through.",
agent=agent,
task_type="loop",
input_file="tasks.csv"
)
agents = PraisonAIAgents(
agents=[agent],
tasks=[task],
process="workflow",
max_iter=30
)
agents.start()
+139
View File
@@ -0,0 +1,139 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from praisonaiagents.tools import read_csv, write_csv
import pandas as pd
def read_csv_smart(csv_path: str) -> pd.DataFrame:
"""Read CSV and use first column as task, handling both header/no-header cases"""
# Try reading with headers first
df = pd.read_csv(csv_path)
# Check if first row looks like data
if not any(col.lower() in ['task', 'description', 'status', 'state'] for col in df.columns):
# If no header-like names found, read without headers
df = pd.read_csv(csv_path, header=None)
# Rename columns consistently
df.columns = [*['task'], *[f'col_{i}' for i in range(1, len(df.columns))]]
if 'status' not in df.columns:
df['status'] = 'pending'
if 'loop_id' not in df.columns:
# Start loop_id from 1 instead of 0
df['loop_id'] = (df.index + 1).astype(str)
return df[['task', 'status', 'loop_id']]
def has_pending_tasks(df: pd.DataFrame) -> bool:
"""Check if there are any pending tasks in the DataFrame"""
return not df[df['status'] == 'pending'].empty
def check_task_status(csv_path: str) -> dict:
"""Read task status from CSV file"""
try:
# Always read directly from CSV file
df = pd.read_csv(csv_path, keep_default_na=False)
# Get only pending tasks from original status
pending_tasks = df[df['status'].str.lower() == 'pending']
if not pending_tasks.empty:
task_data = pending_tasks.iloc[0].to_dict()
return {
'has_pending': True,
'next_task': task_data
}
return {'has_pending': False, 'next_task': None}
except Exception as e:
print(f"Error reading CSV: {e}")
return {'has_pending': False, 'next_task': None, 'error': str(e)}
def get_next_task() -> dict:
"""Get the next pending task from CSV"""
status = check_task_status("tasks.csv")
if status['has_pending'] and status['next_task']:
task = status['next_task']
if task['status'].lower() == 'pending':
return {
'loop_data': {
'task': task['task'],
'loop_id': task['loop_id'],
'status': task['status']
}
}
return None
def update_task_status(loop_id: str, new_status: str) -> bool:
"""Update task status in CSV file using loop_id as identifier"""
try:
# Read directly from CSV file
df = pd.read_csv("tasks.csv", keep_default_na=False)
df['loop_id'] = df['loop_id'].astype(str)
mask = df['loop_id'] == str(loop_id)
if mask.any():
df.loc[mask, 'status'] = new_status
df.to_csv("tasks.csv", index=False)
return True
print(f"No task found with loop_id: {loop_id}")
return False
except Exception as e:
print(f"Error updating status: {e}")
return False
identify_agent = Agent(
name="Identify Agent",
role="Pending Task Identifier",
goal="Identify the next pending task",
tools=[get_next_task],
llm="gpt-4o-mini"
)
# Create the repetitive agent
repetitive_agent = Agent(
name="TaskProcessor",
role="Task Processing Specialist",
goal="Complete the task response",
llm="gpt-4o-mini"
)
update_status_agent = Agent(
name="UpdateStatusAgent",
role="Status Updater",
goal="Update the status of the task in CSV",
tools=[update_task_status],
llm="gpt-4o-mini"
)
# Define the repetitive task
identify_task = Task(
name="identify_task",
description="Identify the next pending task. If there are no pending tasks decision is completed.",
agent=identify_agent,
task_type="loop",
condition={
"pending": ["process_task"],
"completed": "exit"
}
)
process_task = Task(
name="process_task",
description="Complete the task mentioned in the response",
agent=repetitive_agent,
context=[identify_task],
task_type="loop",
next_tasks=["update_task"]
)
update_task = Task(
name="update_task",
description="Update the task status",
agent=update_status_agent,
next_tasks= ["identify_task"]
)
# Create and run agents manager
agents = PraisonAIAgents(
agents=[identify_agent, repetitive_agent],
tasks=[identify_task, process_task, update_task],
process="workflow"
)
agents.start()
+15
View File
@@ -0,0 +1,15 @@
# Core dependencies
pydantic
rich
openai>=1.30.0
# Memory dependencies
chromadb>=0.5.23
# Knowledge dependencies
mem0ai>=0.1.0
markitdown
chonkie
# Development dependencies
python-dotenv>=0.19.0
+5
View File
@@ -0,0 +1,5 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
agent = Agent(instructions="You are a Research Agent", tools=[duckduckgo])
agent.start("Research about AI 2024")
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
# Sample Markdown
## Section 1
This is a test markdown file.
## Section 2
It contains some formatted text and sections.
+3
View File
@@ -0,0 +1,3 @@
This is a sample text file.
It contains multiple lines.
This is for testing purposes.
+5
View File
@@ -0,0 +1,5 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
agent = Agent(instructions="You are a Shopping Agent", tools=[duckduckgo])
agent.start("I want to buy iPhone 16 Pro Max, check 5 stores and give me price in table")
+4
View File
@@ -0,0 +1,4 @@
from praisonaiagents import Agent
agent = Agent(instructions="You are a Markdown Agent, output in markdown format")
agent.start("Write a blog post about AI")
+21
View File
@@ -0,0 +1,21 @@
import streamlit as st
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
st.title("AI Research Assistant")
st.write("Enter your research query below to get started!")
# Initialize the research agent
agent = Agent(instructions="You are a Research Agent", tools=[duckduckgo])
# Create the input field
query = st.text_input("Research Query", placeholder="Enter your research topic...")
# Add a search button
if st.button("Search"):
if query:
with st.spinner("Researching..."):
result = agent.start(query)
st.write(result)
else:
st.warning("Please enter a research query")
View File
Whitespace-only changes.
+100
View File
@@ -0,0 +1,100 @@
Write a product description for a smartwatch in 2 lines.
Create a user manual for a blender in 2 lines.
Draft an apology email for delayed delivery in 2 lines.
Write a blog post on "Benefits of Meditation" in 2 lines.
Create a privacy policy for a website in 2 lines.
Write instructions for setting up a Wi-Fi router in 2 lines.
Draft an email to follow up after a job interview in 2 lines.
Create a FAQ page for an e-commerce store in 2 lines.
Write an invitation email for a webinar in 2 lines.
Create a terms and conditions page for an app in 2 lines.
Write a press release for a product launch in 2 lines.
Create a checklist for house cleaning tasks in 2 lines.
Draft a resignation letter template in 2 lines.
Write a cover letter for a software developer role in 2 lines.
Create onboarding instructions for new employees in 2 lines.
Write a memo announcing a new policy in a company in 2 lines.
Create a safety guidelines document for a workplace in 2 lines.
Write a pitch email to potential investors in 2 lines.
Draft a thank-you email for attending a conference in 2 lines.
Create a refund policy template for an online store in 2 lines.
Write a blog on "How to Improve Time Management" in 2 lines.
Create step-by-step instructions for changing a car tyre in 2 lines.
Write a welcome email for new subscribers in 2 lines.
Draft an event agenda template in 2 lines.
Create a code of conduct for an online forum in 2 lines.
Write a guide for beginners to start a blog in 2 lines.
Create a checklist for organising a party in 2 lines.
Draft an email to request a product review in 2 lines.
Write a policy for remote work in a company in 2 lines.
Create a simple tutorial for using Excel formulas in 2 lines.
Write a thank-you letter for a donation in 2 lines.
Draft a meeting minutes template in 2 lines.
Create an FAQ for a gym membership in 2 lines.
Write a blog post about "Healthy Snacks for Kids" in 2 lines.
Create a guide for securing your social media accounts in 2 lines.
Draft an email to request a testimonial from a client in 2 lines.
Write a safety checklist for camping trips in 2 lines.
Create a script for a customer service call in 2 lines.
Write a tutorial for creating a simple PowerPoint presentation in 2 lines.
Create a packing list for a beach vacation in 2 lines.
Draft an email to cancel a service subscription in 2 lines.
Write a personal statement for university admission in 2 lines.
Create a template for tracking monthly expenses in 2 lines.
Write a guide for planting and caring for succulents in 2 lines.
Create a simple user guide for a mobile app in 2 lines.
Draft an email to announce a team-building activity in 2 lines.
Write a step-by-step guide for baking a cake in 2 lines.
Create a list of house maintenance tasks in 2 lines.
Draft a partnership proposal email in 2 lines.
Write a guide for basic photography tips in 2 lines.
Create a feedback form template for an online course in 2 lines.
Write a blog on "Top 5 Budget Travel Destinations" in 2 lines.
Draft a letter of recommendation for a colleague in 2 lines.
Create a workout plan for beginners in 2 lines.
Write a guide for troubleshooting common tech issues in 2 lines.
Draft a reminder email for an upcoming appointment in 2 lines.
Create a guide for setting personal goals in 2 lines.
Write a blog post about "How to Start Freelancing" in 2 lines.
Create a template for event planning in 2 lines.
Draft an email to notify users about system maintenance in 2 lines.
Write a guide for choosing the right laptop in 2 lines.
Create a checklist for moving to a new house in 2 lines.
Draft an email to update a client on project status in 2 lines.
Write a guide for reducing screen time in 2 lines.
Create a shopping list template for weekly groceries in 2 lines.
Draft a thank-you email for completing a survey in 2 lines.
Write a blog on "Simple DIY Crafts for Beginners" in 2 lines.
Create a checklist for starting a small business in 2 lines.
Draft an email to apologise for a customer complaint in 2 lines.
Write a guide for setting up a personal budget in 2 lines.
Create a policy for using company-provided equipment in 2 lines.
Draft an email to notify about a price increase in 2 lines.
Write a tutorial for creating a resume using Word in 2 lines.
Create a simple guide for organising a charity event in 2 lines.
Draft a formal invitation letter for a conference in 2 lines.
Write a blog post about "Top Productivity Apps" in 2 lines.
Create a checklist for first-time pet owners in 2 lines.
Draft an email to confirm a service appointment in 2 lines.
Write a beginner’s guide for learning to code in 2 lines.
Create a guide for assembling a basic toolkit in 2 lines.
Draft a welcome email for a new team member in 2 lines.
Write a guide for preparing a home for winter in 2 lines.
Create a schedule template for meal planning in 2 lines.
Draft an email to request feedback from a customer in 2 lines.
Write a guide on "How to Build a Morning Routine" in 2 lines.
Create a checklist for hosting a virtual meeting in 2 lines.
Draft a newsletter for a non-profit organisation in 2 lines.
Write a guide for beginners to use Canva in 2 lines.
Create a guide for organising your workspace in 2 lines.
Draft an email to invite users to a beta program in 2 lines.
Write a step-by-step guide for creating a podcast in 2 lines.
Create a simple guide for buying your first car in 2 lines.
Draft an email to announce a new team member in 2 lines.
Write a tutorial on creating basic charts in Excel in 2 lines.
Create a guide for teaching basic first aid in 2 lines.
Draft an email to follow up after a sales call in 2 lines.
Write a blog post on "How to Save Money on Utilities" in 2 lines.
Create a guide for designing a basic website in 2 lines.
Draft a thank-you email for a business referral in 2 lines.
Write a guide for setting up a new smartphone in 2 lines.
Can't render this file because it contains an unexpected character in line 4 and column 22.
+758
View File
@@ -0,0 +1,758 @@
"date","close","volume","open","high","low"
"11:34","270.49","4,787,699","264.50","273.88","262.24"
"2018/10/15","259.5900","6189026.0000","259.0600","263.2800","254.5367"
"2018/10/12","258.7800","7189257.0000","261.0000","261.9900","252.0100"
"2018/10/11","252.2300","8128184.0000","257.5300","262.2500","249.0300"
"2018/10/10","256.8800","12781560.0000","264.6100","265.5100","247.7700"
"2018/10/09","262.8000","12037780.0000","255.2500","266.7700","253.3000"
"2018/10/08","250.5600","13371180.0000","264.5200","267.7599","249.0000"
"2018/10/05","261.9500","17900710.0000","274.6500","274.8800","260.0000"
"2018/10/04","281.8300","9638885.0000","293.9500","294.0000","277.6700"
"2018/10/03","294.8000","7982272.0000","303.3300","304.6000","291.5700"
"2018/10/02","301.0200","11699690.0000","313.9500","316.8400","299.1500"
"2018/10/01","310.7000","21714210.0000","305.7700","311.4400","301.0500"
"2018/09/28","264.7700","33597290.0000","270.2600","278.0000","260.5550"
"2018/09/27","307.5200","7337760.0000","312.9000","314.9600","306.9100"
"2018/09/26","309.5800","7835863.0000","301.9100","313.8900","301.1093"
"2018/09/25","300.9900","4472287.0000","300.0000","304.6000","296.5000"
"2018/09/24","299.6800","4834384.0000","298.4800","302.9993","293.5800"
"2018/09/21","299.1000","5038497.0000","297.7000","300.5800","295.3700"
"2018/09/20","298.3300","7332477.0000","303.5600","305.9800","293.3300"
"2018/09/19","299.0200","8264353.0000","280.5100","300.0000","280.5000"
"2018/09/18","284.9600","16494280.0000","296.6900","302.6400","275.5000"
"2018/09/17","294.8400","6866208.0000","290.0400","300.8700","288.1300"
"2018/09/14","295.2000","6757652.0000","288.7600","297.3256","286.5200"
"2018/09/13","289.4600","6333281.0000","288.0200","295.0000","285.1800"
"2018/09/12","290.5400","10002150.0000","281.4400","292.5000","278.6463"
"2018/09/11","279.4400","9161061.0000","279.4700","282.0000","273.5500"
"2018/09/10","285.5000","14232250.0000","273.2600","286.0300","271.0000"
"2018/09/07","263.2400","22442310.0000","260.1000","268.3500","252.2548"
"2018/09/06","280.9500","7472756.0000","284.8000","291.1700","278.8800"
"2018/09/05","280.7400","7707342.0000","285.0500","286.7800","277.1800"
"2018/09/04","288.9500","8304571.0000","296.9400","298.1900","288.0000"
"2018/08/31","301.6600","5367048.0000","302.0000","305.3082","298.6000"
"2018/08/30","303.1500","7210625.0000","302.2600","304.6000","297.7200"
"2018/08/29","305.0100","7410538.0000","310.2700","311.8500","303.6900"
"2018/08/28","311.8600","7639453.0000","318.4100","318.8800","311.1900"
"2018/08/27","319.2700","13062650.0000","318.0000","322.4350","308.8100"
"2018/08/24","322.8200","3592734.0000","320.7000","323.8500","319.4000"
"2018/08/23","320.1000","5138685.0000","319.1400","327.3200","318.1000"
"2018/08/22","321.6400","5935853.0000","320.8700","323.8800","314.6700"
"2018/08/21","321.9000","13147770.0000","310.6100","324.7900","309.0000"
"2018/08/20","308.4400","17380430.0000","291.7040","308.5000","288.2000"
"2018/08/17","305.5000","18895880.0000","323.5000","326.7700","303.5300"
"2018/08/16","335.4500","6045392.0000","339.9100","342.2800","333.8200"
"2018/08/15","338.6900","9073033.0000","341.9060","344.4900","332.1400"
"2018/08/14","347.6400","6948511.0000","358.4500","359.1995","347.1000"
"2018/08/13","356.4100","10444920.0000","361.1300","363.1900","349.0200"
"2018/08/10","355.4900","11530510.0000","354.0000","360.0000","346.0000"
"2018/08/09","352.4500","16951800.0000","365.5500","367.0100","345.7300"
"2018/08/08","370.3400","24535420.0000","369.0900","382.6400","367.1200"
"2018/08/07","379.5700","30596400.0000","343.8400","387.4600","339.1501"
"2018/08/06","341.9900","8536766.0000","345.4600","354.9800","341.8200"
"2018/08/03","348.1700","13646640.0000","347.8100","355.0000","342.5300"
"2018/08/02","349.5400","23159160.0000","328.4400","349.9900","323.1600"
"2018/08/01","300.8400","8768099.0000","297.9900","303.0000","293.0000"
"2018/07/31","298.1400","5055094.0000","292.2500","298.3200","289.0700"
"2018/07/30","290.1700","6799581.0000","295.9000","296.1000","286.1300"
"2018/07/27","297.1800","5694690.0000","307.2500","307.6933","295.3404"
"2018/07/26","306.6500","4619567.0000","304.8500","310.7000","303.6411"
"2018/07/25","308.7400","7031382.0000","296.7400","309.6200","294.5025"
"2018/07/24","297.4300","9586186.0000","304.4209","307.7171","292.5452"
"2018/07/23","303.2000","10974820.0000","301.8400","305.5000","292.8601"
"2018/07/20","313.5800","5159831.0000","321.2300","323.2400","311.7093"
"2018/07/19","320.2300","5907116.0000","316.3300","323.5400","314.0100"
"2018/07/18","323.8500","5610085.0000","325.0000","325.5000","316.2500"
"2018/07/17","322.6900","6987782.0000","308.8100","324.7400","308.5000"
"2018/07/16","310.1000","7800454.0000","311.7100","315.1600","306.2500"
"2018/07/13","318.8700","5866776.0000","315.5800","319.5849","309.2500"
"2018/07/12","316.7100","5711851.0000","321.4300","323.2300","312.7700"
"2018/07/11","318.9600","4878595.0000","315.8000","321.9400","315.0700"
"2018/07/10","322.4700","9437557.0000","324.5600","327.6771","319.2000"
"2018/07/09","318.5100","7579541.0000","311.9900","318.5200","308.0000"
"2018/07/06","308.9000","8860198.0000","304.9550","312.0700","302.0000"
"2018/07/05","309.1600","17457570.0000","313.7600","314.3900","296.2200"
"2018/07/03","310.8600","12282640.0000","331.7500","332.4900","309.6900"
"2018/07/02","335.0700","18732710.0000","360.0700","364.7800","329.8500"
"2018/06/29","342.9500","6475903.0000","353.3300","353.8600","342.4100"
"2018/06/28","349.9300","8388172.0000","348.6600","357.0200","346.1100"
"2018/06/27","344.5000","8313817.0000","345.0000","350.7900","339.5000"
"2018/06/26","342.0000","7434749.0000","336.0540","343.5500","325.7990"
"2018/06/25","333.0100","6925089.0000","330.1200","338.4700","327.5000"
"2018/06/22","333.6300","10253770.0000","351.5400","352.2500","332.0000"
"2018/06/21","347.5100","7949846.0000","362.0000","366.2139","346.2700"
"2018/06/20","362.2200","8370268.0000","358.0400","364.3800","352.0000"
"2018/06/19","352.5500","12734840.0000","365.1600","370.0000","346.2500"
"2018/06/18","370.8300","12025450.0000","355.4000","373.7300","354.5000"
"2018/06/15","358.1700","10827560.0000","353.8400","364.6700","351.2500"
"2018/06/14","357.7200","10961150.0000","347.6300","358.7500","346.6000"
"2018/06/13","344.7800","9401467.0000","346.7060","347.2000","339.8000"
"2018/06/12","342.7700","22256430.0000","344.7000","354.9700","338.0000"
"2018/06/11","332.1000","13166050.0000","322.5100","334.6600","322.5000"
"2018/06/08","317.6600","8192175.0000","319.0000","324.4800","317.1500"
"2018/06/07","316.0900","14336110.0000","316.1500","330.0000","313.5800"
"2018/06/06","319.5000","18742400.0000","300.5000","322.1700","297.4800"
"2018/06/05","291.1300","5877873.0000","297.7000","297.8000","286.7400"
"2018/06/04","296.7400","4793787.0000","294.3400","299.0000","293.5480"
"2018/06/01","291.8200","5417984.0000","285.8600","291.9500","283.8390"
"2018/05/31","284.7300","5912825.0000","287.2100","290.3700","282.9300"
"2018/05/30","291.7200","7473590.0000","283.2900","295.0050","281.6000"
"2018/05/29","283.7600","5657153.0000","278.5100","286.5000","276.1500"
"2018/05/25","278.8500","3872621.0000","277.6250","279.6400","275.6100"
"2018/05/24","277.8500","4170789.0000","278.4000","281.1100","274.8900"
"2018/05/23","279.0700","5972237.0000","277.7600","279.9099","274.0000"
"2018/05/22","275.0100","8938501.0000","287.7620","288.0000","273.4220"
"2018/05/21","284.4900","9167844.0000","281.3300","291.4900","281.3000"
"2018/05/18","276.8200","7243699.0000","284.6500","284.6500","274.0000"
"2018/05/17","284.5400","4418258.0000","285.9000","289.1873","283.9700"
"2018/05/16","286.4800","5669644.0000","283.8300","288.8100","281.5600"
"2018/05/15","284.1800","9509753.0000","285.0100","286.9600","280.5000"
"2018/05/14","291.9700","7265501.0000","303.3200","304.9400","291.6200"
"2018/05/11","301.0600","4665321.0000","307.7000","308.8800","299.0800"
"2018/05/10","305.0200","5642771.0000","307.4997","312.9900","304.1119"
"2018/05/09","306.8500","5712255.0000","300.4100","307.0100","300.0500"
"2018/05/08","301.9700","5927447.0000","300.7950","307.7500","299.0000"
"2018/05/07","302.7700","8673090.0000","297.5000","305.9588","295.1700"
"2018/05/04","294.0900","8565506.0000","283.0000","296.8600","279.5200"
"2018/05/03","284.4500","17339090.0000","278.7900","288.0400","275.2300"
"2018/05/02","301.1500","8346176.0000","298.5700","306.8500","297.7844"
"2018/05/01","299.9200","4614946.0000","293.5100","300.8200","293.2200"
"2018/04/30","293.9000","4224068.0000","293.6100","298.7300","292.5000"
"2018/04/27","294.0750","4346854.0000","285.3700","294.4700","283.8300"
"2018/04/26","285.4800","4348108.0000","278.7500","285.7900","276.5000"
"2018/04/25","280.6900","4000421.0000","283.5000","285.1600","277.2500"
"2018/04/24","283.4600","5678242.0000","285.0000","287.0900","278.4600"
"2018/04/23","283.3700","4880743.0000","291.2900","291.6200","282.3300"
"2018/04/20","290.2400","5622630.0000","295.1700","299.9800","289.7500"
"2018/04/19","300.0800","6083800.0000","291.0800","301.0100","288.5500"
"2018/04/18","293.3500","6531563.0000","291.0800","300.2400","288.1600"
"2018/04/17","287.6900","6931152.0000","288.8700","292.1700","282.5100"
"2018/04/16","291.2100","6289497.0000","299.0000","299.6600","289.0100"
"2018/04/13","300.3400","7319225.0000","303.6000","303.9499","295.9800"
"2018/04/12","294.0800","7595525.0000","302.3200","303.9500","293.6800"
"2018/04/11","300.9300","7470204.0000","300.7400","308.9800","299.6600"
"2018/04/10","304.7000","11017010.0000","298.9700","307.1000","293.6800"
"2018/04/09","289.6600","10241410.0000","300.3700","309.5000","289.2100"
"2018/04/06","299.3000","13516530.0000","301.0000","309.2800","295.5000"
"2018/04/05","305.7200","19025860.0000","289.3400","306.2600","288.2000"
"2018/04/04","286.9400","19880180.0000","252.7800","288.3700","252.0000"
"2018/04/03","267.5300","18829650.0000","269.8200","273.3500","254.4900"
"2018/04/02","252.4800","16093290.0000","256.2600","260.3318","244.5901"
"2018/03/29","266.1300","15014440.0000","256.4900","270.9599","248.2100"
"2018/03/28","257.7800","20962280.0000","264.5800","268.6800","252.1000"
"2018/03/27","279.1800","13787060.0000","304.0000","304.2700","277.1800"
"2018/03/26","304.1800","8364937.0000","307.3400","307.5900","291.3600"
"2018/03/23","301.5400","6639960.0000","311.2500","311.6100","300.4500"
"2018/03/22","309.1000","4924928.0000","313.8900","318.8200","308.1800"
"2018/03/21","316.5300","5954247.0000","310.2500","322.4400","310.1900"
"2018/03/20","310.5500","4761031.0000","314.8700","316.2500","308.7600"
"2018/03/19","313.5600","7467890.0000","316.5000","320.7500","309.6700"
"2018/03/16","321.3500","6113365.0000","325.9600","327.4000","319.0700"
"2018/03/15","325.6000","6554568.0000","329.3800","332.8500","321.1000"
"2018/03/14","326.6300","7952152.0000","336.7600","339.8100","323.9300"
"2018/03/13","341.8400","5960636.0000","344.9200","345.1200","336.2635"
"2018/03/12","345.5100","8252919.0000","328.6100","347.2100","326.5000"
"2018/03/09","327.1700","5502779.0000","324.1000","328.4900","322.3700"
"2018/03/08","329.1000","3514367.0000","332.8600","333.3000","326.2740"
"2018/03/07","332.3000","5001940.0000","325.4400","332.5000","321.7400"
"2018/03/06","328.2000","4236483.0000","333.7500","336.3700","327.0300"
"2018/03/05","333.3500","3820702.0000","332.3900","337.7500","329.2929"
"2018/03/02","335.1200","5088789.0000","326.9800","335.2200","322.9700"
"2018/03/01","330.9300","6872552.0000","345.0100","348.6700","330.0700"
"2018/02/28","343.0600","6066044.0000","352.5700","355.2400","342.2200"
"2018/02/27","350.9900","4785022.0000","356.2500","359.9900","350.0100"
"2018/02/26","357.4200","4334500.0000","353.5000","359.0000","352.3550"
"2018/02/23","352.0500","5814177.0000","347.8300","354.9900","347.1000"
"2018/02/22","346.1700","6961880.0000","335.5300","347.4400","334.7501"
"2018/02/21","333.3000","3207250.0000","336.0300","339.6929","333.1700"
"2018/02/20","334.7700","4005962.0000","334.4700","340.8400","331.5000"
"2018/02/16","335.4900","5640184.0000","332.5000","343.1200","331.6400"
"2018/02/15","334.0650","5909823.0000","324.5000","334.1200","322.4000"
"2018/02/14","322.3100","3948077.0000","320.8400","326.1700","318.5200"
"2018/02/13","323.6600","4554631.0000","315.0200","324.1900","312.5105"
"2018/02/12","315.7300","6224479.0000","316.1300","318.0800","306.2500"
"2018/02/09","310.4200","12924430.0000","319.9300","320.9845","294.7600"
"2018/02/08","315.2300","10296420.0000","343.3100","348.6200","314.6000"
"2018/02/07","345.0000","6729682.0000","338.9900","346.0000","335.6600"
"2018/02/06","333.9700","5080032.0000","325.2100","336.2200","323.5000"
"2018/02/05","333.1300","4441166.0000","337.9700","344.4700","333.0000"
"2018/02/02","343.7500","3696157.0000","348.4400","351.9500","340.5100"
"2018/02/01","349.2500","4187440.0000","351.0000","359.6600","348.6300"
"2018/01/31","354.3100","6199373.0000","347.5100","356.1900","345.1900"
"2018/01/30","345.8200","4710684.0000","345.1400","348.2700","342.1700"
"2018/01/29","349.5300","4738208.0000","339.8500","350.8500","338.2800"
"2018/01/26","342.8500","4535457.0000","341.5000","344.0000","335.7100"
"2018/01/25","337.6400","6725208.0000","348.2700","349.2000","336.4000"
"2018/01/24","345.8900","5277386.0000","354.5800","354.7500","343.5200"
"2018/01/23","352.7900","5447622.0000","360.0000","360.5000","351.0000"
"2018/01/22","351.5600","6199777.0000","349.4000","357.8300","349.2000"
"2018/01/19","350.0200","4871181.0000","345.0000","350.5899","342.6000"
"2018/01/18","344.5700","5679629.0000","345.6700","352.3000","343.7400"
"2018/01/17","347.1600","7092554.0000","340.4700","349.0000","339.7500"
"2018/01/16","340.0600","6429234.0000","337.5400","345.0000","334.8000"
"2018/01/12","336.2200","4822509.0000","338.6300","340.4100","333.6700"
"2018/01/11","337.9500","6640863.0000","335.2400","344.8099","333.2600"
"2018/01/10","334.8000","4303053.0000","332.2000","337.0000","330.0000"
"2018/01/09","333.6900","7134525.0000","335.1600","338.8000","327.4050"
"2018/01/08","336.4100","9832610.0000","316.0000","337.0199","315.5000"
"2018/01/05","316.5800","4588728.0000","316.6200","317.2400","312.0000"
"2018/01/04","314.6200","9944593.0000","312.8700","318.5500","305.6800"
"2018/01/03","317.2500","4438520.0000","321.0000","325.2500","315.5500"
"2018/01/02","320.5300","4345615.0000","312.0000","322.1099","311.0000"
"2017/12/29","311.3500","3769504.0000","316.1800","316.4100","310.0000"
"2017/12/28","315.3600","4306746.0000","311.7500","315.8200","309.5400"
"2017/12/27","311.6400","4705084.0000","316.0000","317.6800","310.7500"
"2017/12/26","317.2900","4368699.0000","323.8300","323.9400","316.5800"
"2017/12/22","325.2000","4207602.0000","329.5100","330.9214","324.8200"
"2017/12/21","331.6600","4369994.0000","329.5900","333.7400","327.2100"
"2017/12/20","328.9800","5907378.0000","332.6900","333.1000","325.0400"
"2017/12/19","331.1000","6820868.0000","340.2600","341.4925","330.3000"
"2017/12/18","338.8700","5466546.0000","344.9000","346.7300","337.5800"
"2017/12/15","343.4500","6921246.0000","342.0400","343.9000","335.7600"
"2017/12/14","337.8900","5792024.0000","341.0100","347.4400","336.9000"
"2017/12/13","339.0300","6217701.0000","340.9300","344.2200","336.5000"
"2017/12/12","341.0300","8715570.0000","330.4500","341.4400","330.0300"
"2017/12/11","328.9100","7926090.0000","314.6300","329.0100","313.7500"
"2017/12/08","315.1300","3466088.0000","314.6000","316.9800","311.2600"
"2017/12/07","311.2400","4779590.0000","312.0000","318.6341","311.0500"
"2017/12/06","313.2600","7184477.0000","300.1000","313.3900","300.0000"
"2017/12/05","303.7000","4643708.0000","302.0000","308.0000","301.0000"
"2017/12/04","305.2000","5834227.0000","306.5000","308.2650","300.6100"
"2017/12/01","306.5300","4286082.0000","305.4400","310.3200","305.0500"
"2017/11/30","308.8500","4345434.0000","308.5600","310.7000","304.5400"
"2017/11/29","307.5400","8757463.0000","317.3000","318.0000","301.2300"
"2017/11/28","317.5500","4941703.0000","316.3600","320.0000","313.9200"
"2017/11/27","316.8100","4537779.0000","313.2500","317.3400","309.5100"
"2017/11/24","315.5500","3244065.0000","313.7900","316.4100","311.0000"
"2017/11/22","312.6000","4913283.0000","316.7700","317.4200","311.8400"
"2017/11/21","317.8100","7256381.0000","310.8600","318.2300","308.7100"
"2017/11/20","308.7400","8241821.0000","313.7900","315.5000","304.7500"
"2017/11/17","315.0500","13720830.0000","325.6700","326.6700","313.1500"
"2017/11/16","312.5000","5794409.0000","313.9900","318.1400","311.3000"
"2017/11/15","311.3000","5951835.0000","306.0100","312.4900","301.5000"
"2017/11/14","308.7000","5661904.0000","315.0000","316.3500","306.9000"
"2017/11/13","315.4000","7565242.0000","300.1300","316.8000","299.1100"
"2017/11/10","302.9900","4621080.0000","302.5000","308.3600","301.8500"
"2017/11/09","302.9900","5440173.0000","302.5000","304.4600","296.3000"
"2017/11/08","304.3900","4725355.0000","305.5000","306.8900","301.3001"
"2017/11/07","306.0500","5284844.0000","301.0200","306.5000","300.0300"
"2017/11/06","302.7800","6480689.0000","307.0000","307.5000","299.0100"
"2017/11/03","306.0900","8885933.0000","299.5000","306.2500","295.1300"
"2017/11/02","299.2600","19771280.0000","300.1300","308.6900","292.6300"
"2017/11/01","321.0800","8242487.0000","332.2500","332.6089","320.2600"
"2017/10/31","331.5300","5650062.0000","320.2300","331.9500","320.1800"
"2017/10/30","320.0800","4247619.0000","319.1800","323.7800","317.2500"
"2017/10/27","320.8700","6968365.0000","319.7500","324.5900","316.6600"
"2017/10/26","326.1700","5010087.0000","327.7800","330.2300","323.2000"
"2017/10/25","325.8400","8583619.0000","336.7000","337.5000","323.5600"
"2017/10/24","337.3400","4485692.0000","338.8000","342.8000","336.1600"
"2017/10/23","337.0200","5739598.0000","349.8800","349.9500","336.2500"
"2017/10/20","345.1000","4925657.0000","352.6900","354.5500","344.3400"
"2017/10/19","351.8100","5055715.0000","355.5600","357.1465","348.2000"
"2017/10/18","359.6500","4936024.0000","355.9700","363.0000","354.1300"
"2017/10/17","355.7500","3290290.0000","350.9100","356.2200","350.0700"
"2017/10/16","350.6000","5373090.0000","353.7600","354.4800","347.1600"
"2017/10/13","355.5700","3538807.0000","356.9800","358.4900","353.6800"
"2017/10/12","355.6800","4073552.0000","352.9500","359.7800","352.6400"
"2017/10/11","354.6000","4494733.0000","353.8900","357.6000","351.1500"
"2017/10/10","355.5900","6972263.0000","346.8000","355.6300","345.5305"
"2017/10/09","342.9400","7461461.0000","349.6500","351.7500","342.6700"
"2017/10/06","356.8800","4272866.0000","353.1000","360.0992","352.2500"
"2017/10/05","355.3300","4167913.0000","356.0000","357.4350","351.3500"
"2017/10/04","355.0100","8147995.0000","351.2500","358.6200","349.6000"
"2017/10/03","348.1400","10122550.0000","335.9000","348.5500","331.2800"
"2017/10/02","341.5300","5227547.0000","342.5200","343.7000","335.5100"
"2017/09/29","341.1000","5099051.0000","341.8600","344.6800","338.6010"
"2017/09/28","339.6000","5309779.0000","339.8800","342.7500","335.4000"
"2017/09/27","340.9700","6027375.0000","349.9000","351.4890","340.5000"
"2017/09/26","345.2500","7149649.0000","350.9300","351.2400","340.9000"
"2017/09/25","344.9900","7587158.0000","353.1500","357.4690","342.8800"
"2017/09/22","351.0900","8142895.0000","366.4900","369.8999","350.8800"
"2017/09/21","366.4800","4610872.0000","374.9000","376.8300","364.5100"
"2017/09/20","373.9100","4909958.0000","373.0000","378.2490","371.0700"
"2017/09/19","375.1000","6435208.0000","380.0000","382.3900","373.5700"
"2017/09/18","385.0000","7177773.0000","380.2500","389.6100","377.6800"
"2017/09/15","379.8100","5407227.0000","374.5100","380.0000","372.7000"
"2017/09/14","377.6400","7170263.0000","364.3300","377.9600","362.6300"
"2017/09/13","366.2300","4171185.0000","363.8200","368.0700","359.5900"
"2017/09/12","362.7500","5966204.0000","364.4900","368.7600","360.4000"
"2017/09/11","363.6900","7651000.0000","351.3500","363.7100","350.0000"
"2017/09/08","343.4000","3261333.0000","348.9900","349.7800","342.3000"
"2017/09/07","350.6100","4235045.0000","345.9800","352.4800","343.4500"
"2017/09/06","344.5300","4082001.0000","349.5000","350.9790","341.5600"
"2017/09/05","349.5900","3836402.0000","353.8000","355.4900","345.8900"
"2017/09/01","355.4000","3048550.0000","356.1200","357.5900","353.6902"
"2017/08/31","355.9000","4063330.0000","353.5500","358.4400","352.8200"
"2017/08/30","353.1800","3404165.0000","349.6700","353.4700","347.0000"
"2017/08/29","347.3600","4069303.0000","339.4800","349.0500","338.7500"
"2017/08/28","345.6600","3746240.0000","347.2800","347.3500","339.7200"
"2017/08/25","348.0500","3475186.0000","354.2400","355.6900","347.3000"
"2017/08/24","352.9300","4571574.0000","352.5200","356.6600","349.7400"
"2017/08/23","352.7700","4941947.0000","338.9900","353.4900","338.3041"
"2017/08/22","341.3500","4314268.0000","341.1300","342.2400","337.3725"
"2017/08/21","337.8600","6489850.0000","345.8200","345.8200","331.8500"
"2017/08/18","347.4600","5390805.0000","352.9100","354.0000","345.8000"
"2017/08/17","351.9200","5010825.0000","361.2100","363.3000","351.5900"
"2017/08/16","362.9100","3406173.0000","363.0000","366.5000","362.5200"
"2017/08/15","362.3300","3084601.0000","365.2000","365.4900","359.3700"
"2017/08/14","363.8000","4507969.0000","364.6300","367.6600","362.6000"
"2017/08/11","357.8700","4357562.0000","356.9700","361.2600","353.6200"
"2017/08/10","355.4000","7063054.0000","361.6000","366.6504","354.6600"
"2017/08/09","363.5300","6881182.0000","361.0000","370.0000","358.9500"
"2017/08/08","365.2200","7431838.0000","357.5300","368.5800","357.4000"
"2017/08/07","355.1700","6309331.0000","357.3500","359.4800","352.7500"
"2017/08/04","356.9100","9233295.0000","347.0000","357.2700","343.3000"
"2017/08/03","347.0900","13524270.0000","345.3300","350.0000","343.1500"
"2017/08/02","325.8900","11942350.0000","318.9400","327.1200","311.2200"
"2017/08/01","319.5700","8284997.0000","323.0000","324.4500","316.1300"
"2017/07/31","323.4700","8525454.0000","335.5000","341.4900","321.0400"
"2017/07/28","335.0700","4869891.0000","336.8900","339.6000","332.5100"
"2017/07/27","334.4600","8285879.0000","346.0000","347.5000","326.2900"
"2017/07/26","343.8500","4809514.0000","340.3600","345.5000","338.1200"
"2017/07/25","339.6000","6977932.0000","345.0000","345.6000","334.1500"
"2017/07/24","342.5200","8598292.0000","330.2400","343.3990","330.0100"
"2017/07/21","328.4000","4871708.0000","329.4600","331.2575","325.8000"
"2017/07/20","329.9200","5142516.0000","326.9000","330.2200","324.2000"
"2017/07/19","325.2600","6345884.0000","328.2300","331.6500","323.2193"
"2017/07/18","328.2400","6360710.0000","317.5000","329.1300","315.6600"
"2017/07/17","319.5700","9827506.0000","325.5400","327.1000","313.4500"
"2017/07/14","327.7800","5607924.0000","323.1900","328.4200","321.2200"
"2017/07/13","323.4100","8582315.0000","330.1100","331.6000","319.9700"
"2017/07/12","329.5200","10317240.0000","330.4000","333.1000","324.5000"
"2017/07/11","327.2200","11526760.0000","316.0000","327.2800","314.3000"
"2017/07/10","316.0500","13760290.0000","312.9000","317.9400","303.1300"
"2017/07/07","313.2200","14129950.0000","313.5000","317.0000","307.3800"
"2017/07/06","308.8300","19258040.0000","317.2600","320.7899","306.3000"
"2017/07/05","327.0900","16998300.0000","347.2000","347.2400","326.3300"
"2017/07/03","352.6200","6305401.0000","370.2400","371.3500","351.5000"
"2017/06/30","361.6100","5823046.0000","363.7100","366.7674","359.6187"
"2017/06/29","360.7500","8202463.0000","370.6100","371.0000","354.1000"
"2017/06/28","371.2400","6290323.0000","366.6800","371.7400","362.5200"
"2017/06/27","362.3700","6977494.0000","376.4000","376.4000","362.0200"
"2017/06/26","377.4900","6596854.0000","386.6900","386.9500","373.1000"
"2017/06/23","383.4500","6425180.0000","382.4500","386.9900","379.3450"
"2017/06/22","382.6100","7510406.0000","377.9900","385.0000","373.5700"
"2017/06/21","376.4000","4916770.0000","374.3500","376.9900","368.0200"
"2017/06/20","372.2400","7419110.0000","376.6700","378.8800","369.7300"
"2017/06/19","369.8000","6433434.0000","375.0000","376.7000","367.8000"
"2017/06/16","371.4000","6347450.0000","377.9750","378.0100","370.1000"
"2017/06/15","375.3400","10412650.0000","372.5000","375.4600","366.4900"
"2017/06/14","380.6600","12778480.0000","381.0850","384.2500","376.3100"
"2017/06/13","375.9500","11773370.0000","367.6200","376.0000","366.6100"
"2017/06/12","359.0100","10507860.0000","357.9900","364.5000","350.6200"
"2017/06/09","357.3200","17250060.0000","374.4200","376.8700","354.8000"
"2017/06/08","370.0000","9028677.0000","363.7500","371.9000","360.2200"
"2017/06/07","359.6500","9348692.0000","356.3400","360.5000","355.1400"
"2017/06/06","352.8500","11031920.0000","344.7000","359.4929","339.9700"
"2017/06/05","347.3200","6769174.0000","338.5000","348.4400","334.2100"
"2017/06/02","339.8500","5583952.0000","339.7700","342.8800","335.9300"
"2017/06/01","340.3700","7601764.0000","344.0000","344.8800","337.2900"
"2017/05/31","341.0100","9937556.0000","337.6900","342.8900","335.1600"
"2017/05/30","335.1000","7771536.0000","326.0000","336.2800","325.7600"
"2017/05/26","325.1400","7793009.0000","317.2800","325.4900","316.3100"
"2017/05/25","316.8300","5000432.0000","311.0200","316.9700","307.8100"
"2017/05/24","310.2200","5035192.0000","306.5100","311.0000","305.4000"
"2017/05/23","303.8600","4314267.0000","310.4600","310.7300","303.4800"
"2017/05/22","310.3500","4324305.0000","312.8000","314.3700","306.8000"
"2017/05/19","310.8300","4654580.0000","315.5000","316.5000","310.2000"
"2017/05/18","313.0600","5609153.0000","307.0000","313.9400","305.3100"
"2017/05/17","306.1100","6695657.0000","314.3900","314.6300","305.5000"
"2017/05/16","317.0100","4141066.0000","317.5900","320.0600","315.1400"
"2017/05/15","315.8800","7606854.0000","318.3800","320.2000","312.5300"
"2017/05/12","324.8100","4118613.0000","325.4800","327.0000","321.5300"
"2017/05/11","323.1000","4747172.0000","323.4000","326.0000","319.6000"
"2017/05/10","325.2200","5734524.0000","321.5600","325.5000","318.1200"
"2017/05/09","321.2600","9663374.0000","309.3800","321.9900","309.1000"
"2017/05/08","307.1900","7002907.0000","310.9000","313.7900","305.8200"
"2017/05/05","308.3500","8117449.0000","298.0000","308.5500","296.8000"
"2017/05/04","295.4600","14135990.0000","307.4350","307.7700","290.7601"
"2017/05/03","311.0200","6879259.0000","317.6700","321.5300","310.4500"
"2017/05/02","318.8900","5316551.0000","324.0000","327.6599","316.5601"
"2017/05/01","322.8300","8819888.0000","314.8800","327.2500","314.8100"
"2017/04/28","314.0700","4496659.0000","309.8300","314.8000","308.0000"
"2017/04/27","308.6300","3462663.0000","311.6900","313.0900","307.5000"
"2017/04/26","310.1700","4683131.0000","312.3700","314.5000","309.0000"
"2017/04/25","313.7900","6734162.0000","308.0000","313.9800","305.8600"
"2017/04/24","308.0300","5077771.0000","309.2200","310.5500","306.0215"
"2017/04/21","305.6000","4501958.0000","302.0000","306.4000","300.4200"
"2017/04/20","302.5100","6145961.0000","306.5100","309.1500","300.2300"
"2017/04/19","305.5200","3891145.0000","302.4600","306.6200","302.1100"
"2017/04/18","300.2500","3034225.0000","299.7000","300.8399","297.9000"
"2017/04/17","301.4400","4128067.0000","302.7000","304.0000","298.6800"
"2017/04/13","304.0000","9275682.0000","296.7000","307.3900","295.3000"
"2017/04/12","296.8400","6043648.0000","306.3400","308.4481","296.3200"
"2017/04/11","308.7100","5718053.0000","313.3800","313.4700","305.5000"
"2017/04/10","312.3900","7653623.0000","309.1500","313.7299","308.7100"
"2017/04/07","302.5400","4566632.0000","297.5000","302.6900","297.1500"
"2017/04/06","298.7000","5517731.0000","296.8800","301.9400","294.1000"
"2017/04/05","295.0000","7858565.0000","302.0400","304.8800","294.2000"
"2017/04/04","303.7000","10108230.0000","296.8900","304.8100","294.5300"
"2017/04/03","298.5200","13864850.0000","286.9000","299.0000","284.5800"
"2017/03/31","278.3000","3293698.0000","278.7300","279.6800","276.3197"
"2017/03/30","277.9200","4141437.0000","278.0400","282.0000","277.2100"
"2017/03/29","277.3800","3672526.0000","278.3400","279.6000","275.5400"
"2017/03/28","277.4500","7978665.0000","277.0200","280.6800","275.0000"
"2017/03/27","270.2200","6221361.0000","260.6000","270.5700","259.7500"
"2017/03/24","263.1600","5637668.0000","255.7000","263.8900","255.0100"
"2017/03/23","254.7800","3309844.0000","255.3900","257.6720","253.3000"
"2017/03/22","255.0100","4056735.0000","251.5600","255.0700","250.5100"
"2017/03/21","250.6800","6901555.0000","262.8300","264.8000","250.2400"
"2017/03/20","261.9200","3601616.0000","260.6000","264.5500","258.8210"
"2017/03/17","261.5000","6491018.0000","264.0000","265.3300","261.2000"
"2017/03/16","262.0500","7127180.0000","262.4000","265.7500","259.0600"
"2017/03/15","255.7300","5233365.0000","257.0000","261.0000","254.2700"
"2017/03/14","258.0000","7581719.0000","246.1100","258.1200","246.0200"
"2017/03/13","246.1700","3011280.0000","244.8200","246.8500","242.7810"
"2017/03/10","243.6900","3062785.0000","246.2100","246.5000","243.0000"
"2017/03/09","244.9000","3876494.0000","247.6300","248.6600","243.0000"
"2017/03/08","246.8700","3726746.0000","247.0000","250.0700","245.3200"
"2017/03/07","248.5900","3452587.0000","251.9200","253.8900","248.3200"
"2017/03/06","251.2100","3353601.0000","247.9100","251.7000","247.5100"
"2017/03/03","251.5700","2925481.0000","250.7400","251.9000","249.0000"
"2017/03/02","250.4800","3345751.0000","249.7100","253.2800","248.2700"
"2017/03/01","250.0200","4804963.0000","254.1800","254.8500","249.1100"
"2017/02/28","249.9900","6073890.0000","244.1900","251.0000","243.9000"
"2017/02/27","246.2300","11450160.0000","248.1700","248.3600","242.0100"
"2017/02/24","257.0000","8166869.0000","252.6600","258.2500","250.2000"
"2017/02/23","255.9900","14877090.0000","264.0000","264.6600","255.5600"
"2017/02/22","273.5100","8537811.0000","280.3100","283.4500","272.6000"
"2017/02/21","277.3900","5647575.0000","275.4500","281.4000","274.0100"
"2017/02/17","272.2300","6251469.0000","265.8000","272.8900","264.1500"
"2017/02/16","268.9500","7063860.0000","277.6000","280.0000","268.5000"
"2017/02/15","279.7600","4943879.0000","280.0000","282.2400","276.4400"
"2017/02/14","280.9800","7341450.0000","279.0300","287.3900","278.6100"
"2017/02/13","280.6000","7023072.0000","270.7400","280.7899","270.5100"
"2017/02/10","269.2300","3618336.0000","269.7900","270.9500","266.1100"
"2017/02/09","269.2000","7812600.0000","266.2500","271.1800","266.1500"
"2017/02/08","262.0800","3912428.0000","257.3500","263.3600","256.2000"
"2017/02/07","257.4800","4244063.0000","258.1900","260.0000","256.4200"
"2017/02/06","257.7700","3557600.0000","251.0000","257.8200","250.6300"
"2017/02/03","251.3300","2185230.0000","251.9100","252.1790","249.6800"
"2017/02/02","251.5500","2498799.0000","248.3400","252.4200","247.7100"
"2017/02/01","249.2400","3953105.0000","253.0500","253.2000","249.0500"
"2017/01/31","251.9300","4112013.0000","249.2400","255.8900","247.7000"
"2017/01/30","250.6300","3798638.0000","252.5300","255.2899","247.1000"
"2017/01/27","252.9500","3161774.0000","251.3800","253.0000","248.5200"
"2017/01/26","252.5100","3143717.0000","254.2900","255.7400","250.7500"
"2017/01/25","254.4700","5145301.0000","257.3100","258.4600","251.8000"
"2017/01/24","254.6100","4958144.0000","250.0000","254.8000","249.6500"
"2017/01/23","248.9200","6262097.0000","245.8500","250.8899","245.5000"
"2017/01/20","244.7300","4199720.0000","245.4600","246.0000","243.0100"
"2017/01/19","243.7600","7717244.0000","247.2500","248.6800","240.7500"
"2017/01/18","238.3600","3767272.0000","236.6500","239.7100","235.5800"
"2017/01/17","235.5800","4614731.0000","236.7000","239.9600","234.3700"
"2017/01/13","237.7500","6085610.0000","230.0000","237.8500","229.5900"
"2017/01/12","229.5900","3787547.0000","229.0600","230.7000","225.5800"
"2017/01/11","229.7300","3649910.0000","229.0700","229.9800","226.6800"
"2017/01/10","229.8700","3658981.0000","232.0000","232.0000","226.8900"
"2017/01/09","231.2800","3972716.0000","228.9700","231.9200","228.0000"
"2017/01/06","229.0100","5524153.0000","226.9300","230.3100","225.4500"
"2017/01/05","226.7500","5908927.0000","226.4200","227.4800","221.9500"
"2017/01/04","226.9900","11204560.0000","214.7500","228.0000","214.3100"
"2017/01/03","216.9900","5901494.0000","214.8600","220.3300","210.9600"
"2016/12/30","213.6900","4641288.0000","216.3000","217.5000","211.6800"
"2016/12/29","214.6800","4043086.0000","218.5600","219.2000","214.1225"
"2016/12/28","219.7400","3778544.0000","221.5300","223.8000","217.2000"
"2016/12/27","219.5300","5913335.0000","214.8800","222.2500","214.4200"
"2016/12/23","213.3400","4668263.0000","208.0000","213.4500","207.7100"
"2016/12/22","208.4500","3108427.0000","208.2200","209.9900","206.5000"
"2016/12/21","207.7000","5206143.0000","208.4500","212.2300","207.4100"
"2016/12/20","208.7900","4684269.0000","203.0500","209.0000","202.5000"
"2016/12/19","202.7300","3486937.0000","202.4900","204.4500","199.8400"
"2016/12/16","202.4900","3795444.0000","198.0800","202.5900","197.6000"
"2016/12/15","197.5800","3218653.0000","198.4100","200.7400","197.3900"
"2016/12/14","198.6900","4147314.0000","198.7400","203.0000","196.7600"
"2016/12/13","198.1500","6819322.0000","193.1800","201.2800","193.0000"
"2016/12/12","192.4300","2436428.0000","192.8000","194.4200","191.0400"
"2016/12/09","192.1800","2720937.0000","190.8700","193.8360","190.8100"
"2016/12/08","192.2900","3193684.0000","192.0500","192.5000","189.5400"
"2016/12/07","193.1500","5457071.0000","186.1500","193.4000","185.0000"
"2016/12/06","185.8500","3389365.0000","185.5200","186.5800","182.6825"
"2016/12/05","186.8000","4069480.0000","182.5100","188.8900","182.5100"
"2016/12/02","181.4700","4040201.0000","182.8800","184.8800","180.0000"
"2016/12/01","181.8800","5119105.0000","188.2500","188.5300","181.0000"
"2016/11/30","189.4000","3544891.0000","191.0000","191.8900","187.5000"
"2016/11/29","189.5700","4435312.0000","195.5600","196.7300","189.5000"
"2016/11/28","196.1200","4521082.0000","195.4800","199.3500","194.5500"
"2016/11/25","196.6500","2366098.0000","193.6400","197.2372","193.6400"
"2016/11/23","193.1400","4890285.0000","190.6100","195.6440","189.0000"
"2016/11/22","191.1700","5601238.0000","185.8400","191.4700","183.7100"
"2016/11/21","184.5200","4355872.0000","185.0400","188.8900","184.4100"
"2016/11/18","185.0200","5206473.0000","190.6500","193.0000","185.0000"
"2016/11/17","188.6600","4880969.0000","183.4900","189.4900","182.1101"
"2016/11/16","183.9300","3432668.0000","182.6500","184.7300","181.2100"
"2016/11/15","183.7700","3899743.0000","182.7800","186.4300","182.0500"
"2016/11/14","181.4500","6547913.0000","188.0000","188.2500","178.1900"
"2016/11/11","188.5600","3987091.0000","184.2400","188.8800","183.0000"
"2016/11/10","185.3500","6746290.0000","191.0500","191.6100","180.4200"
"2016/11/09","190.0600","8166447.0000","186.8750","192.0000","183.9500"
"2016/11/08","194.9400","3252927.0000","193.7900","197.4900","191.2600"
"2016/11/07","193.2100","3857682.0000","193.5900","194.2900","190.0500"
"2016/11/04","190.5600","5143915.0000","189.0000","193.4600","185.9600"
"2016/11/03","187.4200","2644550.0000","189.0000","191.4700","187.0401"
"2016/11/02","188.0200","4242250.0000","190.0500","192.6951","187.5050"
"2016/11/01","190.7900","7023674.0000","198.0400","198.5000","188.1050"
"2016/10/31","197.7300","4691320.0000","202.4900","202.4900","195.8100"
"2016/10/28","199.9700","4273456.0000","204.0000","205.3200","199.8300"
"2016/10/27","204.0100","13070990.0000","211.3400","213.7000","201.6500"
"2016/10/26","202.2400","5346893.0000","201.0000","203.1900","200.1000"
"2016/10/25","202.3400","2442118.0000","202.9000","204.6900","201.2000"
"2016/10/24","202.7600","2747344.0000","201.0000","203.9452","200.2500"
"2016/10/21","200.0900","2936908.0000","198.6000","201.5700","197.4100"
"2016/10/20","199.1000","5069410.0000","202.1200","203.0000","197.0500"
"2016/10/19","203.5600","6966185.0000","199.7400","206.6600","198.0600"
"2016/10/18","199.1000","5676046.0000","195.9900","199.4700","193.2600"
"2016/10/17","193.9600","4518331.0000","197.0500","198.3900","192.0000"
"2016/10/14","196.5100","4265471.0000","200.6600","201.4300","196.3000"
"2016/10/13","200.2400","2495140.0000","200.5000","200.8950","197.0500"
"2016/10/12","201.5100","1969099.0000","200.9500","203.8800","200.4200"
"2016/10/11","200.1000","2326754.0000","201.8500","202.2000","198.3100"
"2016/10/10","200.9500","3311340.0000","201.3500","204.1400","199.6600"
"2016/10/07","196.6100","3489480.0000","201.0000","201.3200","195.8000"
"2016/10/06","201.0000","4697937.0000","202.4600","204.2099","200.2100"
"2016/10/05","208.4600","1872456.0000","212.2400","213.1500","208.1200"
"2016/10/04","211.4100","3537953.0000","213.1000","213.3200","208.8200"
"2016/10/03","213.7000","5989342.0000","212.3000","215.6688","208.2500"
"2016/09/30","204.0300","2581730.0000","202.2100","204.9800","199.5500"
"2016/09/29","200.7000","2714040.0000","205.6000","207.3300","200.5800"
"2016/09/28","206.2700","2079324.0000","207.5100","208.2500","205.2600"
"2016/09/27","205.8100","3367907.0000","209.6500","209.9818","204.6093"
"2016/09/26","208.9900","2393373.0000","206.5000","211.0000","206.5000"
"2016/09/23","207.4500","2904125.0000","205.9900","210.1800","205.6700"
"2016/09/22","206.4300","2381600.0000","206.4000","207.2800","203.0000"
"2016/09/21","205.2200","2631285.0000","206.3700","207.0000","201.5600"
"2016/09/20","204.6400","2408556.0000","206.8500","207.7500","203.9100"
"2016/09/19","206.3400","2298318.0000","207.0000","209.4300","205.0000"
"2016/09/16","205.4000","3104266.0000","200.4200","205.7000","199.0000"
"2016/09/15","200.4200","3082942.0000","196.4900","202.5193","196.4000"
"2016/09/14","196.4100","2256143.0000","195.7500","197.9248","194.8562"
"2016/09/13","196.0500","3583140.0000","197.0600","198.4900","193.4500"
"2016/09/12","198.3000","3714049.0000","195.0000","201.3690","194.1000"
"2016/09/09","194.4700","3753734.0000","199.0900","199.9200","193.7000"
"2016/09/08","197.3600","3372293.0000","199.5500","199.8900","196.3600"
"2016/09/07","201.7100","3637918.0000","205.5000","206.4968","200.7100"
"2016/09/06","202.8300","4386193.0000","199.0200","203.2500","199.0000"
"2016/09/02","197.7800","5970154.0000","202.3300","203.2000","196.2000"
"2016/09/01","200.7700","7932444.0000","209.0100","211.0999","200.5000"
"2016/08/31","212.0100","3274854.0000","210.4300","212.6000","208.6500"
"2016/08/30","211.3400","3164222.0000","216.1100","216.1100","210.5200"
"2016/08/29","215.2000","3261381.0000","220.1500","220.4000","215.0000"
"2016/08/26","219.9900","2238087.0000","222.1400","222.8550","218.8200"
"2016/08/25","220.9600","1760212.0000","223.1100","223.8000","220.7700"
"2016/08/24","222.6200","2566947.0000","227.0500","227.1500","222.2200"
"2016/08/23","224.8400","4747745.0000","224.3200","228.4900","222.8000"
"2016/08/22","222.9300","2061692.0000","224.1700","225.1100","222.6800"
"2016/08/19","225.0000","1658616.0000","223.5400","225.1690","222.5300"
"2016/08/18","223.5100","1699300.0000","223.8200","225.6600","222.2900"
"2016/08/17","223.2400","1786408.0000","224.3300","224.8300","222.8000"
"2016/08/16","223.6100","2251115.0000","225.4900","227.1900","223.4101"
"2016/08/15","225.5900","2017964.0000","226.0200","229.5000","224.9300"
"2016/08/12","225.6100","1811850.0000","225.4100","226.6500","224.0400"
"2016/08/11","224.9100","1876959.0000","226.1700","227.5700","223.4100"
"2016/08/10","225.6500","2336496.0000","228.2400","229.8700","224.6200"
"2016/08/09","229.0800","2199766.0000","226.8200","231.5375","226.6500"
"2016/08/08","226.1600","2259465.0000","228.0000","229.6000","226.0900"
"2016/08/05","230.0300","3190342.0000","230.0000","232.0000","227.4000"
"2016/08/04","230.6100","4142155.0000","225.6900","230.8600","222.0500"
"2016/08/03","225.7900","3808747.0000","227.3700","229.6990","224.2100"
"2016/08/02","227.2000","3928706.0000","229.3700","229.8700","221.4000"
"2016/08/01","230.0100","4014048.0000","235.5000","236.6300","229.3800"
"2016/07/29","234.7900","3061574.0000","230.7000","235.2800","230.2400"
"2016/07/28","230.6100","2415462.0000","227.9500","230.7600","226.6000"
"2016/07/27","228.4900","2887028.0000","229.3400","233.3600","226.9200"
"2016/07/26","229.5100","3427251.0000","227.6900","230.0000","225.3000"
"2016/07/25","230.0100","4479483.0000","222.2700","231.3900","221.3715"
"2016/07/22","222.2700","2570462.0000","221.9900","224.5000","218.8800"
"2016/07/21","220.5000","4425756.0000","226.0000","227.8470","219.1000"
"2016/07/20","228.3600","2556119.0000","226.4700","229.8000","225.0000"
"2016/07/19","225.2600","3047535.0000","225.0000","229.1000","224.7500"
"2016/07/18","226.2500","3394588.0000","219.6400","227.0900","218.3000"
"2016/07/15","220.4000","2230821.0000","222.5200","222.7499","219.6400"
"2016/07/14","221.5300","2657899.0000","223.1200","224.9400","221.0500"
"2016/07/13","222.5300","3540699.0000","225.5000","225.5900","220.2900"
"2016/07/12","224.6500","4573875.0000","224.1000","227.5000","223.2200"
"2016/07/11","224.7800","5369066.0000","219.9600","226.7800","219.5100"
"2016/07/08","216.7800","4067131.0000","217.8000","219.8100","214.5000"
"2016/07/07","215.9400","3603385.0000","213.1000","218.1200","213.0100"
"2016/07/06","214.4400","4910285.0000","210.0000","215.2300","209.0000"
"2016/07/05","213.9800","5169832.0000","209.7300","214.5441","208.0000"
"2016/07/01","216.5000","5396030.0000","206.1400","218.2400","206.0000"
"2016/06/30","212.2800","4794440.0000","212.9700","213.4999","209.0200"
"2016/06/29","210.1900","5987120.0000","205.1300","211.7800","203.0000"
"2016/06/28","201.7900","6158996.0000","201.8900","204.0500","199.4100"
"2016/06/27","198.5500","7211823.0000","190.8600","198.8100","187.8700"
"2016/06/24","193.1500","6988949.0000","190.0500","195.1200","189.7300"
"2016/06/23","196.4000","10098190.0000","195.6900","197.5500","192.1300"
"2016/06/22","196.6600","23706100.0000","199.4700","205.9500","195.7500"
"2016/06/21","219.6100","2855619.0000","220.6800","222.5690","218.8100"
"2016/06/20","219.7000","3549768.0000","219.5000","223.7500","218.2300"
"2016/06/17","215.4700","3107734.0000","217.8100","219.9900","214.5000"
"2016/06/16","217.9300","2438692.0000","217.4200","218.0400","213.5000"
"2016/06/15","217.7000","2905002.0000","216.9500","221.9000","215.1300"
"2016/06/14","214.9600","3575822.0000","218.8800","222.2000","212.5300"
"2016/06/13","217.8700","4187833.0000","219.5000","225.7700","217.6600"
"2016/06/10","218.7900","5994548.0000","227.3900","227.9700","218.4217"
"2016/06/09","229.3600","4454222.0000","234.9800","235.3300","227.0600"
"2016/06/08","235.5200","5965110.0000","233.8000","240.8450","232.6050"
"2016/06/07","232.3400","6194154.0000","222.2400","234.4400","221.5200"
"2016/06/06","220.6800","2242634.0000","218.0000","220.9000","215.4500"
"2016/06/03","218.9900","2226110.0000","220.0000","221.9400","218.0100"
"2016/06/02","218.9600","2017279.0000","219.5900","219.9090","217.1100"
"2016/06/01","219.5600","2982270.0000","221.4800","222.4000","216.8900"
"2016/05/31","223.2300","2786682.0000","223.0400","224.7497","221.5001"
"2016/05/27","223.0400","3645792.0000","224.9900","225.9300","220.7500"
"2016/05/26","225.1200","4066512.0000","220.5000","225.2600","219.0500"
"2016/05/25","219.5800","3131279.0000","217.9100","221.3600","216.5100"
"2016/05/24","217.9100","3009327.0000","216.6000","218.7400","215.1800"
"2016/05/23","216.2200","5096751.0000","219.8700","222.6000","215.8600"
"2016/05/20","220.2800","8996546.0000","216.9900","220.5500","216.3500"
"2016/05/19","215.2100","6817922.0000","213.6200","216.7900","207.3000"
"2016/05/18","211.1700","5552692.0000","209.1500","215.3100","207.7500"
"2016/05/17","204.6600","2842028.0000","209.0500","209.8199","204.0200"
"2016/05/16","208.2900","2945754.0000","208.1500","213.1500","207.9200"
"2016/05/13","207.6100","2820616.0000","207.7800","211.2000","206.7000"
"2016/05/12","207.2800","3650075.0000","211.4400","211.6700","203.6572"
"2016/05/11","208.9600","5159640.0000","207.5900","215.4800","206.0500"
"2016/05/10","208.6900","4068053.0000","207.5500","209.4700","205.0000"
"2016/05/09","208.9200","4772992.0000","215.7200","216.1500","206.8000"
"2016/05/06","214.9300","5683675.0000","210.8700","216.3700","208.1100"
"2016/05/05","211.5300","11248340.0000","228.4600","228.6400","209.7900"
"2016/05/04","222.5600","8550004.0000","230.2900","234.4600","220.4000"
"2016/05/03","232.3200","4296325.0000","237.3600","238.9100","231.6200"
"2016/05/02","241.8000","3838958.0000","241.5000","243.1900","234.8200"
"2016/04/29","240.7600","5405164.0000","248.1400","248.4300","237.8100"
"2016/04/28","247.7100","2515595.0000","249.8500","253.4300","247.4400"
"2016/04/27","251.4700","3198105.0000","252.7500","255.0000","249.4000"
"2016/04/26","253.7400","3217779.0000","252.0500","255.7300","249.3900"
"2016/04/25","251.8200","3665088.0000","253.0100","257.3800","250.7600"
"2016/04/22","253.7500","3783126.0000","248.8900","254.0000","245.7100"
"2016/04/21","248.2900","2777079.0000","248.9900","250.9000","246.9100"
"2016/04/20","249.9700","5192343.0000","246.2600","253.6600","241.5000"
"2016/04/19","247.3700","6351360.0000","253.1200","254.3699","241.2510"
"2016/04/18","253.8800","4263246.0000","252.2300","258.3100","251.6600"
"2016/04/15","254.5100","3748593.0000","251.3100","254.6000","249.1200"
"2016/04/14","251.8600","4129258.0000","253.0000","256.8390","251.0501"
"2016/04/13","254.5300","4921554.0000","248.5100","255.5000","247.3300"
"2016/04/12","247.8200","5755351.0000","249.5000","251.8000","243.6300"
"2016/04/11","249.9200","9156404.0000","251.0000","258.9900","245.3000"
"2016/04/08","250.0700","7352707.0000","260.5000","260.8200","248.0201"
"2016/04/07","257.2000","8845567.0000","266.4500","269.3400","254.5100"
"2016/04/06","265.4200","11695760.0000","253.9700","267.7400","253.4500"
"2016/04/05","255.4700","9931470.0000","240.5000","256.5600","240.0000"
"2016/04/04","246.9900","13381160.0000","249.1200","252.1200","243.6400"
"2016/04/01","237.5900","15979910.0000","244.8250","247.9000","233.2500"
"2016/03/31","229.7700","7975638.0000","229.3400","237.4200","225.0100"
"2016/03/30","226.8900","4025670.0000","235.0900","235.5000","226.5000"
"2016/03/29","230.1300","4006037.0000","229.8900","232.3800","225.3300"
"2016/03/28","230.2600","3878599.0000","231.6100","234.8100","225.0000"
"2016/03/24","227.7500","4956604.0000","215.7800","228.8877","215.0000"
"2016/03/23","222.5800","4936203.0000","232.3700","234.7300","222.0300"
"2016/03/22","234.2400","4303052.0000","237.2100","238.9900","232.5580"
"2016/03/21","238.3200","5289014.0000","235.3400","239.8800","235.0000"
"2016/03/18","232.7400","4704761.0000","229.1000","234.4800","228.0600"
"2016/03/17","226.3800","3769083.0000","221.4700","228.5000","220.0000"
"2016/03/16","221.9300","3511873.0000","218.0000","222.5800","217.0200"
"2016/03/15","218.3400","3133230.0000","214.2700","218.9700","211.5000"
"2016/03/14","215.1500","4062304.0000","212.6500","216.7200","210.6400"
"2016/03/11","207.5000","3339148.0000","207.9300","209.4200","205.3300"
"2016/03/10","205.1800","5191602.0000","210.0000","213.2900","200.6710"
"2016/03/09","208.7200","3207597.0000","204.5200","209.3726","202.7900"
"2016/03/08","202.6000","4175498.0000","203.5000","207.5000","202.2000"
"2016/03/07","205.2900","5331097.0000","197.6800","209.7000","197.4000"
"2016/03/04","201.0400","6479858.0000","198.0000","204.0300","197.5001"
"2016/03/03","195.7400","4822993.0000","188.2800","197.4200","184.2200"
"2016/03/02","188.3400","4858631.0000","183.7300","188.5200","181.5000"
"2016/03/01","186.3500","6695704.0000","194.2500","195.9484","182.7000"
"2016/02/29","191.9300","4495402.0000","192.4000","196.3500","189.2220"
"2016/02/26","190.3400","6054061.0000","188.7000","192.0000","185.0000"
"2016/02/25","187.4300","5727008.0000","178.6500","188.5192","175.2000"
"2016/02/24","179.0000","5385369.0000","172.7500","179.5000","167.8400"
"2016/02/23","177.2100","5982993.0000","176.1600","181.7300","173.6800"
"2016/02/22","177.7400","5055340.0000","170.1200","178.9100","169.8500"
"2016/02/19","166.5800","2955832.0000","163.6600","167.4900","162.5000"
"2016/02/18","166.7700","3883107.0000","172.4200","172.9500","164.7700"
"2016/02/17","168.6800","5820264.0000","159.0000","169.3400","156.6800"
"2016/02/16","155.1700","5561638.0000","158.7000","162.9500","154.1100"
"2016/02/12","151.0400","7233264.0000","155.0000","157.0100","143.7000"
"2016/02/11","150.4700","14236900.0000","152.0000","163.2600","147.0000"
"2016/02/10","143.6700","10104690.0000","150.5000","154.9700","141.7400"
"2016/02/09","148.2500","8639661.0000","142.3200","159.7900","141.0500"
"2016/02/08","147.9900","9306754.0000","157.1050","157.1500","146.0000"
"2016/02/05","162.6000","9434495.0000","171.3000","173.0000","157.7442"
"2016/02/04","175.3300","4379442.0000","170.7000","175.9800","166.9900"
"2016/02/03","173.4800","7927640.0000","183.5900","183.9400","170.1800"
"2016/02/02","182.7800","5764817.0000","192.4200","193.1200","180.2300"
"2016/02/01","196.9400","5295685.0000","188.7600","199.5200","182.7500"
"2016/01/29","191.2000","2848929.0000","189.9500","193.7400","188.0800"
"2016/01/28","189.7000","4586328.0000","190.7900","191.2800","182.4100"
"2016/01/27","188.0700","3577353.0000","192.3800","193.2600","185.7700"
"2016/01/26","193.5600","4956918.0000","196.7000","197.8200","188.8800"
"2016/01/25","196.3800","2695408.0000","200.0600","203.5700","195.8800"
"2016/01/22","202.5500","3122066.0000","204.8010","205.5000","199.0300"
"2016/01/21","199.9700","3164424.0000","201.5500","203.2300","195.0200"
"2016/01/20","198.7000","5826110.0000","199.4000","201.2800","191.2500"
"2016/01/19","204.7200","4031271.0000","208.7100","210.4700","200.7800"
"2016/01/15","204.9900","5325773.0000","198.9700","205.0700","197.2500"
"2016/01/14","206.1800","6490579.0000","202.2100","210.0000","193.3800"
"2016/01/13","200.3100","4120993.0000","212.0100","212.6500","200.0000"
"2016/01/12","209.9700","3079051.0000","211.6000","213.7395","205.3100"
"2016/01/11","207.8500","4090843.0000","214.0100","214.4500","203.0000"
"2016/01/08","211.0000","3572360.0000","217.8600","220.4400","210.7700"
"2016/01/07","215.6500","3550704.0000","214.1900","218.4400","213.6700"
"2016/01/06","219.0400","3774353.0000","220.0000","220.0500","215.9800"
"2016/01/05","223.4300","3185525.0000","226.3600","226.8900","220.0000"
"2016/01/04","223.4100","6823510.0000","230.7200","231.3800","219.0000"
"2015/12/31","240.0100","2713817.0000","238.5100","243.4500","238.3700"
"2015/12/30","238.0900","3694448.0000","236.6000","243.6340","235.6707"
"2015/12/29","237.1900","2402438.0000","230.0600","237.7200","229.5470"
"2015/12/28","228.9500","1900171.0000","231.4900","231.9800","225.5400"
"2015/12/24","230.5700","710277.0000","230.5600","231.8800","228.2800"
"2015/12/23","229.7000","1551031.0000","232.1800","233.4500","228.1300"
"2015/12/22","229.9500","1958836.0000","234.9900","236.5500","229.6300"
"2015/12/21","232.5600","1951581.0000","231.6900","235.8300","231.0800"
"2015/12/18","230.4600","3008057.0000","232.8900","235.9000","229.2900"
"2015/12/17","233.3900","3294460.0000","233.9400","237.7600","229.8149"
"2015/12/16","234.5100","5100443.0000","222.1000","234.8800","220.7300"
"2015/12/15","221.0900","2241686.0000","221.8200","222.2200","218.0000"
"2015/12/14","218.5800","2827797.0000","217.5100","220.9200","214.8700"
"2015/12/11","217.0200","3259114.0000","225.2400","225.7500","216.6400"
"2015/12/10","227.0700","2070088.0000","224.7100","228.4900","223.6400"
"2015/12/09","224.5200","3057036.0000","226.7000","227.5000","220.7200"
"2015/12/08","226.7200","2682259.0000","227.5200","228.8000","224.2000"
"2015/12/07","231.1300","3140864.0000","227.7000","235.6300","226.1500"
"2015/12/04","230.3800","2572014.0000","232.4600","233.2700","227.6600"
"2015/12/03","232.7100","2937233.0000","235.4800","237.4500","230.0000"
"2015/12/02","231.9900","2980644.0000","237.0000","238.6000","231.2300"
"2015/12/01","237.1900","3728562.0000","231.0600","238.0000","231.0500"
"2015/11/30","230.2600","2591205.0000","231.7900","234.2800","229.0800"
"2015/11/27","231.6100","1949353.0000","231.0600","232.2500","227.0100"
"2015/11/25","229.6400","3986945.0000","221.3400","230.8250","220.3750"
"2015/11/24","218.2500","2478389.0000","215.3700","221.0000","215.0000"
"2015/11/23","217.7500","2525196.0000","217.3500","219.1800","214.6798"
"2015/11/20","220.0100","4394199.0000","223.4900","225.0000","213.5800"
"2015/11/19","221.8000","2499593.0000","220.5400","226.1900","220.3000"
"2015/11/18","221.0700","2810200.0000","214.5000","221.3800","212.5200"
"2015/11/17","214.0000","2148326.0000","215.2000","216.0000","211.4000"
"2015/11/16","214.3100","2920362.0000","206.0900","214.9800","205.8000"
"2015/11/13","207.1900","3423139.0000","212.9500","212.9900","206.5200"
"2015/11/12","212.9400","2913511.0000","217.8500","219.0000","212.6600"
"2015/11/11","219.0800","3337501.0000","217.7700","219.4800","213.6300"
"2015/11/10","216.5000","4612408.0000","223.4800","223.7000","216.0800"
"2015/11/09","225.3300","3846179.0000","232.9900","232.9900","224.3100"
"2015/11/06","232.3600","2444264.0000","230.7000","233.3590","229.5000"
"2015/11/05","231.7700","4494944.0000","230.5800","234.5843","229.1900"
"2015/11/04","231.6300","12713530.0000","227.0000","232.7400","225.2000"
"2015/11/03","208.3500","8065091.0000","213.8500","214.4400","207.7500"
"2015/11/02","213.7900","3924514.0000","208.9200","215.8000","207.2200"
"2015/10/30","206.9300","4432433.0000","210.4000","211.6300","203.8900"
"2015/10/29","211.6300","1794743.0000","211.7500","213.7481","210.6400"
"2015/10/28","212.9600","2726880.0000","211.3100","213.4500","208.3000"
"2015/10/27","210.3500","3512832.0000","214.8400","217.1000","207.5100"
"2015/10/26","215.2600","3388227.0000","211.3800","215.8800","210.0000"
"2015/10/23","209.0900","4226411.0000","215.0000","215.3500","207.6900"
"2015/10/22","211.7200","2818801.0000","211.5600","215.7500","209.4000"
"2015/10/21","210.0900","4177956.0000","211.9900","214.8100","208.8000"
"2015/10/20","213.0300","14877020.0000","227.7200","228.6000","202.0000"
"2015/10/19","228.1000","2506836.0000","226.5000","231.1500","224.9400"
"2015/10/16","227.0100","4327574.0000","223.0400","230.4805","222.8700"
"2015/10/15","221.3100","2835920.0000","216.4300","221.7300","213.7000"
1 date close volume open high low
2 11:34 270.49 4,787,699 264.50 273.88 262.24
3 2018/10/15 259.5900 6189026.0000 259.0600 263.2800 254.5367
4 2018/10/12 258.7800 7189257.0000 261.0000 261.9900 252.0100
5 2018/10/11 252.2300 8128184.0000 257.5300 262.2500 249.0300
6 2018/10/10 256.8800 12781560.0000 264.6100 265.5100 247.7700
7 2018/10/09 262.8000 12037780.0000 255.2500 266.7700 253.3000
8 2018/10/08 250.5600 13371180.0000 264.5200 267.7599 249.0000
9 2018/10/05 261.9500 17900710.0000 274.6500 274.8800 260.0000
10 2018/10/04 281.8300 9638885.0000 293.9500 294.0000 277.6700
11 2018/10/03 294.8000 7982272.0000 303.3300 304.6000 291.5700
12 2018/10/02 301.0200 11699690.0000 313.9500 316.8400 299.1500
13 2018/10/01 310.7000 21714210.0000 305.7700 311.4400 301.0500
14 2018/09/28 264.7700 33597290.0000 270.2600 278.0000 260.5550
15 2018/09/27 307.5200 7337760.0000 312.9000 314.9600 306.9100
16 2018/09/26 309.5800 7835863.0000 301.9100 313.8900 301.1093
17 2018/09/25 300.9900 4472287.0000 300.0000 304.6000 296.5000
18 2018/09/24 299.6800 4834384.0000 298.4800 302.9993 293.5800
19 2018/09/21 299.1000 5038497.0000 297.7000 300.5800 295.3700
20 2018/09/20 298.3300 7332477.0000 303.5600 305.9800 293.3300
21 2018/09/19 299.0200 8264353.0000 280.5100 300.0000 280.5000
22 2018/09/18 284.9600 16494280.0000 296.6900 302.6400 275.5000
23 2018/09/17 294.8400 6866208.0000 290.0400 300.8700 288.1300
24 2018/09/14 295.2000 6757652.0000 288.7600 297.3256 286.5200
25 2018/09/13 289.4600 6333281.0000 288.0200 295.0000 285.1800
26 2018/09/12 290.5400 10002150.0000 281.4400 292.5000 278.6463
27 2018/09/11 279.4400 9161061.0000 279.4700 282.0000 273.5500
28 2018/09/10 285.5000 14232250.0000 273.2600 286.0300 271.0000
29 2018/09/07 263.2400 22442310.0000 260.1000 268.3500 252.2548
30 2018/09/06 280.9500 7472756.0000 284.8000 291.1700 278.8800
31 2018/09/05 280.7400 7707342.0000 285.0500 286.7800 277.1800
32 2018/09/04 288.9500 8304571.0000 296.9400 298.1900 288.0000
33 2018/08/31 301.6600 5367048.0000 302.0000 305.3082 298.6000
34 2018/08/30 303.1500 7210625.0000 302.2600 304.6000 297.7200
35 2018/08/29 305.0100 7410538.0000 310.2700 311.8500 303.6900
36 2018/08/28 311.8600 7639453.0000 318.4100 318.8800 311.1900
37 2018/08/27 319.2700 13062650.0000 318.0000 322.4350 308.8100
38 2018/08/24 322.8200 3592734.0000 320.7000 323.8500 319.4000
39 2018/08/23 320.1000 5138685.0000 319.1400 327.3200 318.1000
40 2018/08/22 321.6400 5935853.0000 320.8700 323.8800 314.6700
41 2018/08/21 321.9000 13147770.0000 310.6100 324.7900 309.0000
42 2018/08/20 308.4400 17380430.0000 291.7040 308.5000 288.2000
43 2018/08/17 305.5000 18895880.0000 323.5000 326.7700 303.5300
44 2018/08/16 335.4500 6045392.0000 339.9100 342.2800 333.8200
45 2018/08/15 338.6900 9073033.0000 341.9060 344.4900 332.1400
46 2018/08/14 347.6400 6948511.0000 358.4500 359.1995 347.1000
47 2018/08/13 356.4100 10444920.0000 361.1300 363.1900 349.0200
48 2018/08/10 355.4900 11530510.0000 354.0000 360.0000 346.0000
49 2018/08/09 352.4500 16951800.0000 365.5500 367.0100 345.7300
50 2018/08/08 370.3400 24535420.0000 369.0900 382.6400 367.1200
51 2018/08/07 379.5700 30596400.0000 343.8400 387.4600 339.1501
52 2018/08/06 341.9900 8536766.0000 345.4600 354.9800 341.8200
53 2018/08/03 348.1700 13646640.0000 347.8100 355.0000 342.5300
54 2018/08/02 349.5400 23159160.0000 328.4400 349.9900 323.1600
55 2018/08/01 300.8400 8768099.0000 297.9900 303.0000 293.0000
56 2018/07/31 298.1400 5055094.0000 292.2500 298.3200 289.0700
57 2018/07/30 290.1700 6799581.0000 295.9000 296.1000 286.1300
58 2018/07/27 297.1800 5694690.0000 307.2500 307.6933 295.3404
59 2018/07/26 306.6500 4619567.0000 304.8500 310.7000 303.6411
60 2018/07/25 308.7400 7031382.0000 296.7400 309.6200 294.5025
61 2018/07/24 297.4300 9586186.0000 304.4209 307.7171 292.5452
62 2018/07/23 303.2000 10974820.0000 301.8400 305.5000 292.8601
63 2018/07/20 313.5800 5159831.0000 321.2300 323.2400 311.7093
64 2018/07/19 320.2300 5907116.0000 316.3300 323.5400 314.0100
65 2018/07/18 323.8500 5610085.0000 325.0000 325.5000 316.2500
66 2018/07/17 322.6900 6987782.0000 308.8100 324.7400 308.5000
67 2018/07/16 310.1000 7800454.0000 311.7100 315.1600 306.2500
68 2018/07/13 318.8700 5866776.0000 315.5800 319.5849 309.2500
69 2018/07/12 316.7100 5711851.0000 321.4300 323.2300 312.7700
70 2018/07/11 318.9600 4878595.0000 315.8000 321.9400 315.0700
71 2018/07/10 322.4700 9437557.0000 324.5600 327.6771 319.2000
72 2018/07/09 318.5100 7579541.0000 311.9900 318.5200 308.0000
73 2018/07/06 308.9000 8860198.0000 304.9550 312.0700 302.0000
74 2018/07/05 309.1600 17457570.0000 313.7600 314.3900 296.2200
75 2018/07/03 310.8600 12282640.0000 331.7500 332.4900 309.6900
76 2018/07/02 335.0700 18732710.0000 360.0700 364.7800 329.8500
77 2018/06/29 342.9500 6475903.0000 353.3300 353.8600 342.4100
78 2018/06/28 349.9300 8388172.0000 348.6600 357.0200 346.1100
79 2018/06/27 344.5000 8313817.0000 345.0000 350.7900 339.5000
80 2018/06/26 342.0000 7434749.0000 336.0540 343.5500 325.7990
81 2018/06/25 333.0100 6925089.0000 330.1200 338.4700 327.5000
82 2018/06/22 333.6300 10253770.0000 351.5400 352.2500 332.0000
83 2018/06/21 347.5100 7949846.0000 362.0000 366.2139 346.2700
84 2018/06/20 362.2200 8370268.0000 358.0400 364.3800 352.0000
85 2018/06/19 352.5500 12734840.0000 365.1600 370.0000 346.2500
86 2018/06/18 370.8300 12025450.0000 355.4000 373.7300 354.5000
87 2018/06/15 358.1700 10827560.0000 353.8400 364.6700 351.2500
88 2018/06/14 357.7200 10961150.0000 347.6300 358.7500 346.6000
89 2018/06/13 344.7800 9401467.0000 346.7060 347.2000 339.8000
90 2018/06/12 342.7700 22256430.0000 344.7000 354.9700 338.0000
91 2018/06/11 332.1000 13166050.0000 322.5100 334.6600 322.5000
92 2018/06/08 317.6600 8192175.0000 319.0000 324.4800 317.1500
93 2018/06/07 316.0900 14336110.0000 316.1500 330.0000 313.5800
94 2018/06/06 319.5000 18742400.0000 300.5000 322.1700 297.4800
95 2018/06/05 291.1300 5877873.0000 297.7000 297.8000 286.7400
96 2018/06/04 296.7400 4793787.0000 294.3400 299.0000 293.5480
97 2018/06/01 291.8200 5417984.0000 285.8600 291.9500 283.8390
98 2018/05/31 284.7300 5912825.0000 287.2100 290.3700 282.9300
99 2018/05/30 291.7200 7473590.0000 283.2900 295.0050 281.6000
100 2018/05/29 283.7600 5657153.0000 278.5100 286.5000 276.1500
101 2018/05/25 278.8500 3872621.0000 277.6250 279.6400 275.6100
102 2018/05/24 277.8500 4170789.0000 278.4000 281.1100 274.8900
103 2018/05/23 279.0700 5972237.0000 277.7600 279.9099 274.0000
104 2018/05/22 275.0100 8938501.0000 287.7620 288.0000 273.4220
105 2018/05/21 284.4900 9167844.0000 281.3300 291.4900 281.3000
106 2018/05/18 276.8200 7243699.0000 284.6500 284.6500 274.0000
107 2018/05/17 284.5400 4418258.0000 285.9000 289.1873 283.9700
108 2018/05/16 286.4800 5669644.0000 283.8300 288.8100 281.5600
109 2018/05/15 284.1800 9509753.0000 285.0100 286.9600 280.5000
110 2018/05/14 291.9700 7265501.0000 303.3200 304.9400 291.6200
111 2018/05/11 301.0600 4665321.0000 307.7000 308.8800 299.0800
112 2018/05/10 305.0200 5642771.0000 307.4997 312.9900 304.1119
113 2018/05/09 306.8500 5712255.0000 300.4100 307.0100 300.0500
114 2018/05/08 301.9700 5927447.0000 300.7950 307.7500 299.0000
115 2018/05/07 302.7700 8673090.0000 297.5000 305.9588 295.1700
116 2018/05/04 294.0900 8565506.0000 283.0000 296.8600 279.5200
117 2018/05/03 284.4500 17339090.0000 278.7900 288.0400 275.2300
118 2018/05/02 301.1500 8346176.0000 298.5700 306.8500 297.7844
119 2018/05/01 299.9200 4614946.0000 293.5100 300.8200 293.2200
120 2018/04/30 293.9000 4224068.0000 293.6100 298.7300 292.5000
121 2018/04/27 294.0750 4346854.0000 285.3700 294.4700 283.8300
122 2018/04/26 285.4800 4348108.0000 278.7500 285.7900 276.5000
123 2018/04/25 280.6900 4000421.0000 283.5000 285.1600 277.2500
124 2018/04/24 283.4600 5678242.0000 285.0000 287.0900 278.4600
125 2018/04/23 283.3700 4880743.0000 291.2900 291.6200 282.3300
126 2018/04/20 290.2400 5622630.0000 295.1700 299.9800 289.7500
127 2018/04/19 300.0800 6083800.0000 291.0800 301.0100 288.5500
128 2018/04/18 293.3500 6531563.0000 291.0800 300.2400 288.1600
129 2018/04/17 287.6900 6931152.0000 288.8700 292.1700 282.5100
130 2018/04/16 291.2100 6289497.0000 299.0000 299.6600 289.0100
131 2018/04/13 300.3400 7319225.0000 303.6000 303.9499 295.9800
132 2018/04/12 294.0800 7595525.0000 302.3200 303.9500 293.6800
133 2018/04/11 300.9300 7470204.0000 300.7400 308.9800 299.6600
134 2018/04/10 304.7000 11017010.0000 298.9700 307.1000 293.6800
135 2018/04/09 289.6600 10241410.0000 300.3700 309.5000 289.2100
136 2018/04/06 299.3000 13516530.0000 301.0000 309.2800 295.5000
137 2018/04/05 305.7200 19025860.0000 289.3400 306.2600 288.2000
138 2018/04/04 286.9400 19880180.0000 252.7800 288.3700 252.0000
139 2018/04/03 267.5300 18829650.0000 269.8200 273.3500 254.4900
140 2018/04/02 252.4800 16093290.0000 256.2600 260.3318 244.5901
141 2018/03/29 266.1300 15014440.0000 256.4900 270.9599 248.2100
142 2018/03/28 257.7800 20962280.0000 264.5800 268.6800 252.1000
143 2018/03/27 279.1800 13787060.0000 304.0000 304.2700 277.1800
144 2018/03/26 304.1800 8364937.0000 307.3400 307.5900 291.3600
145 2018/03/23 301.5400 6639960.0000 311.2500 311.6100 300.4500
146 2018/03/22 309.1000 4924928.0000 313.8900 318.8200 308.1800
147 2018/03/21 316.5300 5954247.0000 310.2500 322.4400 310.1900
148 2018/03/20 310.5500 4761031.0000 314.8700 316.2500 308.7600
149 2018/03/19 313.5600 7467890.0000 316.5000 320.7500 309.6700
150 2018/03/16 321.3500 6113365.0000 325.9600 327.4000 319.0700
151 2018/03/15 325.6000 6554568.0000 329.3800 332.8500 321.1000
152 2018/03/14 326.6300 7952152.0000 336.7600 339.8100 323.9300
153 2018/03/13 341.8400 5960636.0000 344.9200 345.1200 336.2635
154 2018/03/12 345.5100 8252919.0000 328.6100 347.2100 326.5000
155 2018/03/09 327.1700 5502779.0000 324.1000 328.4900 322.3700
156 2018/03/08 329.1000 3514367.0000 332.8600 333.3000 326.2740
157 2018/03/07 332.3000 5001940.0000 325.4400 332.5000 321.7400
158 2018/03/06 328.2000 4236483.0000 333.7500 336.3700 327.0300
159 2018/03/05 333.3500 3820702.0000 332.3900 337.7500 329.2929
160 2018/03/02 335.1200 5088789.0000 326.9800 335.2200 322.9700
161 2018/03/01 330.9300 6872552.0000 345.0100 348.6700 330.0700
162 2018/02/28 343.0600 6066044.0000 352.5700 355.2400 342.2200
163 2018/02/27 350.9900 4785022.0000 356.2500 359.9900 350.0100
164 2018/02/26 357.4200 4334500.0000 353.5000 359.0000 352.3550
165 2018/02/23 352.0500 5814177.0000 347.8300 354.9900 347.1000
166 2018/02/22 346.1700 6961880.0000 335.5300 347.4400 334.7501
167 2018/02/21 333.3000 3207250.0000 336.0300 339.6929 333.1700
168 2018/02/20 334.7700 4005962.0000 334.4700 340.8400 331.5000
169 2018/02/16 335.4900 5640184.0000 332.5000 343.1200 331.6400
170 2018/02/15 334.0650 5909823.0000 324.5000 334.1200 322.4000
171 2018/02/14 322.3100 3948077.0000 320.8400 326.1700 318.5200
172 2018/02/13 323.6600 4554631.0000 315.0200 324.1900 312.5105
173 2018/02/12 315.7300 6224479.0000 316.1300 318.0800 306.2500
174 2018/02/09 310.4200 12924430.0000 319.9300 320.9845 294.7600
175 2018/02/08 315.2300 10296420.0000 343.3100 348.6200 314.6000
176 2018/02/07 345.0000 6729682.0000 338.9900 346.0000 335.6600
177 2018/02/06 333.9700 5080032.0000 325.2100 336.2200 323.5000
178 2018/02/05 333.1300 4441166.0000 337.9700 344.4700 333.0000
179 2018/02/02 343.7500 3696157.0000 348.4400 351.9500 340.5100
180 2018/02/01 349.2500 4187440.0000 351.0000 359.6600 348.6300
181 2018/01/31 354.3100 6199373.0000 347.5100 356.1900 345.1900
182 2018/01/30 345.8200 4710684.0000 345.1400 348.2700 342.1700
183 2018/01/29 349.5300 4738208.0000 339.8500 350.8500 338.2800
184 2018/01/26 342.8500 4535457.0000 341.5000 344.0000 335.7100
185 2018/01/25 337.6400 6725208.0000 348.2700 349.2000 336.4000
186 2018/01/24 345.8900 5277386.0000 354.5800 354.7500 343.5200
187 2018/01/23 352.7900 5447622.0000 360.0000 360.5000 351.0000
188 2018/01/22 351.5600 6199777.0000 349.4000 357.8300 349.2000
189 2018/01/19 350.0200 4871181.0000 345.0000 350.5899 342.6000
190 2018/01/18 344.5700 5679629.0000 345.6700 352.3000 343.7400
191 2018/01/17 347.1600 7092554.0000 340.4700 349.0000 339.7500
192 2018/01/16 340.0600 6429234.0000 337.5400 345.0000 334.8000
193 2018/01/12 336.2200 4822509.0000 338.6300 340.4100 333.6700
194 2018/01/11 337.9500 6640863.0000 335.2400 344.8099 333.2600
195 2018/01/10 334.8000 4303053.0000 332.2000 337.0000 330.0000
196 2018/01/09 333.6900 7134525.0000 335.1600 338.8000 327.4050
197 2018/01/08 336.4100 9832610.0000 316.0000 337.0199 315.5000
198 2018/01/05 316.5800 4588728.0000 316.6200 317.2400 312.0000
199 2018/01/04 314.6200 9944593.0000 312.8700 318.5500 305.6800
200 2018/01/03 317.2500 4438520.0000 321.0000 325.2500 315.5500
201 2018/01/02 320.5300 4345615.0000 312.0000 322.1099 311.0000
202 2017/12/29 311.3500 3769504.0000 316.1800 316.4100 310.0000
203 2017/12/28 315.3600 4306746.0000 311.7500 315.8200 309.5400
204 2017/12/27 311.6400 4705084.0000 316.0000 317.6800 310.7500
205 2017/12/26 317.2900 4368699.0000 323.8300 323.9400 316.5800
206 2017/12/22 325.2000 4207602.0000 329.5100 330.9214 324.8200
207 2017/12/21 331.6600 4369994.0000 329.5900 333.7400 327.2100
208 2017/12/20 328.9800 5907378.0000 332.6900 333.1000 325.0400
209 2017/12/19 331.1000 6820868.0000 340.2600 341.4925 330.3000
210 2017/12/18 338.8700 5466546.0000 344.9000 346.7300 337.5800
211 2017/12/15 343.4500 6921246.0000 342.0400 343.9000 335.7600
212 2017/12/14 337.8900 5792024.0000 341.0100 347.4400 336.9000
213 2017/12/13 339.0300 6217701.0000 340.9300 344.2200 336.5000
214 2017/12/12 341.0300 8715570.0000 330.4500 341.4400 330.0300
215 2017/12/11 328.9100 7926090.0000 314.6300 329.0100 313.7500
216 2017/12/08 315.1300 3466088.0000 314.6000 316.9800 311.2600
217 2017/12/07 311.2400 4779590.0000 312.0000 318.6341 311.0500
218 2017/12/06 313.2600 7184477.0000 300.1000 313.3900 300.0000
219 2017/12/05 303.7000 4643708.0000 302.0000 308.0000 301.0000
220 2017/12/04 305.2000 5834227.0000 306.5000 308.2650 300.6100
221 2017/12/01 306.5300 4286082.0000 305.4400 310.3200 305.0500
222 2017/11/30 308.8500 4345434.0000 308.5600 310.7000 304.5400
223 2017/11/29 307.5400 8757463.0000 317.3000 318.0000 301.2300
224 2017/11/28 317.5500 4941703.0000 316.3600 320.0000 313.9200
225 2017/11/27 316.8100 4537779.0000 313.2500 317.3400 309.5100
226 2017/11/24 315.5500 3244065.0000 313.7900 316.4100 311.0000
227 2017/11/22 312.6000 4913283.0000 316.7700 317.4200 311.8400
228 2017/11/21 317.8100 7256381.0000 310.8600 318.2300 308.7100
229 2017/11/20 308.7400 8241821.0000 313.7900 315.5000 304.7500
230 2017/11/17 315.0500 13720830.0000 325.6700 326.6700 313.1500
231 2017/11/16 312.5000 5794409.0000 313.9900 318.1400 311.3000
232 2017/11/15 311.3000 5951835.0000 306.0100 312.4900 301.5000
233 2017/11/14 308.7000 5661904.0000 315.0000 316.3500 306.9000
234 2017/11/13 315.4000 7565242.0000 300.1300 316.8000 299.1100
235 2017/11/10 302.9900 4621080.0000 302.5000 308.3600 301.8500
236 2017/11/09 302.9900 5440173.0000 302.5000 304.4600 296.3000
237 2017/11/08 304.3900 4725355.0000 305.5000 306.8900 301.3001
238 2017/11/07 306.0500 5284844.0000 301.0200 306.5000 300.0300
239 2017/11/06 302.7800 6480689.0000 307.0000 307.5000 299.0100
240 2017/11/03 306.0900 8885933.0000 299.5000 306.2500 295.1300
241 2017/11/02 299.2600 19771280.0000 300.1300 308.6900 292.6300
242 2017/11/01 321.0800 8242487.0000 332.2500 332.6089 320.2600
243 2017/10/31 331.5300 5650062.0000 320.2300 331.9500 320.1800
244 2017/10/30 320.0800 4247619.0000 319.1800 323.7800 317.2500
245 2017/10/27 320.8700 6968365.0000 319.7500 324.5900 316.6600
246 2017/10/26 326.1700 5010087.0000 327.7800 330.2300 323.2000
247 2017/10/25 325.8400 8583619.0000 336.7000 337.5000 323.5600
248 2017/10/24 337.3400 4485692.0000 338.8000 342.8000 336.1600
249 2017/10/23 337.0200 5739598.0000 349.8800 349.9500 336.2500
250 2017/10/20 345.1000 4925657.0000 352.6900 354.5500 344.3400
251 2017/10/19 351.8100 5055715.0000 355.5600 357.1465 348.2000
252 2017/10/18 359.6500 4936024.0000 355.9700 363.0000 354.1300
253 2017/10/17 355.7500 3290290.0000 350.9100 356.2200 350.0700
254 2017/10/16 350.6000 5373090.0000 353.7600 354.4800 347.1600
255 2017/10/13 355.5700 3538807.0000 356.9800 358.4900 353.6800
256 2017/10/12 355.6800 4073552.0000 352.9500 359.7800 352.6400
257 2017/10/11 354.6000 4494733.0000 353.8900 357.6000 351.1500
258 2017/10/10 355.5900 6972263.0000 346.8000 355.6300 345.5305
259 2017/10/09 342.9400 7461461.0000 349.6500 351.7500 342.6700
260 2017/10/06 356.8800 4272866.0000 353.1000 360.0992 352.2500
261 2017/10/05 355.3300 4167913.0000 356.0000 357.4350 351.3500
262 2017/10/04 355.0100 8147995.0000 351.2500 358.6200 349.6000
263 2017/10/03 348.1400 10122550.0000 335.9000 348.5500 331.2800
264 2017/10/02 341.5300 5227547.0000 342.5200 343.7000 335.5100
265 2017/09/29 341.1000 5099051.0000 341.8600 344.6800 338.6010
266 2017/09/28 339.6000 5309779.0000 339.8800 342.7500 335.4000
267 2017/09/27 340.9700 6027375.0000 349.9000 351.4890 340.5000
268 2017/09/26 345.2500 7149649.0000 350.9300 351.2400 340.9000
269 2017/09/25 344.9900 7587158.0000 353.1500 357.4690 342.8800
270 2017/09/22 351.0900 8142895.0000 366.4900 369.8999 350.8800
271 2017/09/21 366.4800 4610872.0000 374.9000 376.8300 364.5100
272 2017/09/20 373.9100 4909958.0000 373.0000 378.2490 371.0700
273 2017/09/19 375.1000 6435208.0000 380.0000 382.3900 373.5700
274 2017/09/18 385.0000 7177773.0000 380.2500 389.6100 377.6800
275 2017/09/15 379.8100 5407227.0000 374.5100 380.0000 372.7000
276 2017/09/14 377.6400 7170263.0000 364.3300 377.9600 362.6300
277 2017/09/13 366.2300 4171185.0000 363.8200 368.0700 359.5900
278 2017/09/12 362.7500 5966204.0000 364.4900 368.7600 360.4000
279 2017/09/11 363.6900 7651000.0000 351.3500 363.7100 350.0000
280 2017/09/08 343.4000 3261333.0000 348.9900 349.7800 342.3000
281 2017/09/07 350.6100 4235045.0000 345.9800 352.4800 343.4500
282 2017/09/06 344.5300 4082001.0000 349.5000 350.9790 341.5600
283 2017/09/05 349.5900 3836402.0000 353.8000 355.4900 345.8900
284 2017/09/01 355.4000 3048550.0000 356.1200 357.5900 353.6902
285 2017/08/31 355.9000 4063330.0000 353.5500 358.4400 352.8200
286 2017/08/30 353.1800 3404165.0000 349.6700 353.4700 347.0000
287 2017/08/29 347.3600 4069303.0000 339.4800 349.0500 338.7500
288 2017/08/28 345.6600 3746240.0000 347.2800 347.3500 339.7200
289 2017/08/25 348.0500 3475186.0000 354.2400 355.6900 347.3000
290 2017/08/24 352.9300 4571574.0000 352.5200 356.6600 349.7400
291 2017/08/23 352.7700 4941947.0000 338.9900 353.4900 338.3041
292 2017/08/22 341.3500 4314268.0000 341.1300 342.2400 337.3725
293 2017/08/21 337.8600 6489850.0000 345.8200 345.8200 331.8500
294 2017/08/18 347.4600 5390805.0000 352.9100 354.0000 345.8000
295 2017/08/17 351.9200 5010825.0000 361.2100 363.3000 351.5900
296 2017/08/16 362.9100 3406173.0000 363.0000 366.5000 362.5200
297 2017/08/15 362.3300 3084601.0000 365.2000 365.4900 359.3700
298 2017/08/14 363.8000 4507969.0000 364.6300 367.6600 362.6000
299 2017/08/11 357.8700 4357562.0000 356.9700 361.2600 353.6200
300 2017/08/10 355.4000 7063054.0000 361.6000 366.6504 354.6600
301 2017/08/09 363.5300 6881182.0000 361.0000 370.0000 358.9500
302 2017/08/08 365.2200 7431838.0000 357.5300 368.5800 357.4000
303 2017/08/07 355.1700 6309331.0000 357.3500 359.4800 352.7500
304 2017/08/04 356.9100 9233295.0000 347.0000 357.2700 343.3000
305 2017/08/03 347.0900 13524270.0000 345.3300 350.0000 343.1500
306 2017/08/02 325.8900 11942350.0000 318.9400 327.1200 311.2200
307 2017/08/01 319.5700 8284997.0000 323.0000 324.4500 316.1300
308 2017/07/31 323.4700 8525454.0000 335.5000 341.4900 321.0400
309 2017/07/28 335.0700 4869891.0000 336.8900 339.6000 332.5100
310 2017/07/27 334.4600 8285879.0000 346.0000 347.5000 326.2900
311 2017/07/26 343.8500 4809514.0000 340.3600 345.5000 338.1200
312 2017/07/25 339.6000 6977932.0000 345.0000 345.6000 334.1500
313 2017/07/24 342.5200 8598292.0000 330.2400 343.3990 330.0100
314 2017/07/21 328.4000 4871708.0000 329.4600 331.2575 325.8000
315 2017/07/20 329.9200 5142516.0000 326.9000 330.2200 324.2000
316 2017/07/19 325.2600 6345884.0000 328.2300 331.6500 323.2193
317 2017/07/18 328.2400 6360710.0000 317.5000 329.1300 315.6600
318 2017/07/17 319.5700 9827506.0000 325.5400 327.1000 313.4500
319 2017/07/14 327.7800 5607924.0000 323.1900 328.4200 321.2200
320 2017/07/13 323.4100 8582315.0000 330.1100 331.6000 319.9700
321 2017/07/12 329.5200 10317240.0000 330.4000 333.1000 324.5000
322 2017/07/11 327.2200 11526760.0000 316.0000 327.2800 314.3000
323 2017/07/10 316.0500 13760290.0000 312.9000 317.9400 303.1300
324 2017/07/07 313.2200 14129950.0000 313.5000 317.0000 307.3800
325 2017/07/06 308.8300 19258040.0000 317.2600 320.7899 306.3000
326 2017/07/05 327.0900 16998300.0000 347.2000 347.2400 326.3300
327 2017/07/03 352.6200 6305401.0000 370.2400 371.3500 351.5000
328 2017/06/30 361.6100 5823046.0000 363.7100 366.7674 359.6187
329 2017/06/29 360.7500 8202463.0000 370.6100 371.0000 354.1000
330 2017/06/28 371.2400 6290323.0000 366.6800 371.7400 362.5200
331 2017/06/27 362.3700 6977494.0000 376.4000 376.4000 362.0200
332 2017/06/26 377.4900 6596854.0000 386.6900 386.9500 373.1000
333 2017/06/23 383.4500 6425180.0000 382.4500 386.9900 379.3450
334 2017/06/22 382.6100 7510406.0000 377.9900 385.0000 373.5700
335 2017/06/21 376.4000 4916770.0000 374.3500 376.9900 368.0200
336 2017/06/20 372.2400 7419110.0000 376.6700 378.8800 369.7300
337 2017/06/19 369.8000 6433434.0000 375.0000 376.7000 367.8000
338 2017/06/16 371.4000 6347450.0000 377.9750 378.0100 370.1000
339 2017/06/15 375.3400 10412650.0000 372.5000 375.4600 366.4900
340 2017/06/14 380.6600 12778480.0000 381.0850 384.2500 376.3100
341 2017/06/13 375.9500 11773370.0000 367.6200 376.0000 366.6100
342 2017/06/12 359.0100 10507860.0000 357.9900 364.5000 350.6200
343 2017/06/09 357.3200 17250060.0000 374.4200 376.8700 354.8000
344 2017/06/08 370.0000 9028677.0000 363.7500 371.9000 360.2200
345 2017/06/07 359.6500 9348692.0000 356.3400 360.5000 355.1400
346 2017/06/06 352.8500 11031920.0000 344.7000 359.4929 339.9700
347 2017/06/05 347.3200 6769174.0000 338.5000 348.4400 334.2100
348 2017/06/02 339.8500 5583952.0000 339.7700 342.8800 335.9300
349 2017/06/01 340.3700 7601764.0000 344.0000 344.8800 337.2900
350 2017/05/31 341.0100 9937556.0000 337.6900 342.8900 335.1600
351 2017/05/30 335.1000 7771536.0000 326.0000 336.2800 325.7600
352 2017/05/26 325.1400 7793009.0000 317.2800 325.4900 316.3100
353 2017/05/25 316.8300 5000432.0000 311.0200 316.9700 307.8100
354 2017/05/24 310.2200 5035192.0000 306.5100 311.0000 305.4000
355 2017/05/23 303.8600 4314267.0000 310.4600 310.7300 303.4800
356 2017/05/22 310.3500 4324305.0000 312.8000 314.3700 306.8000
357 2017/05/19 310.8300 4654580.0000 315.5000 316.5000 310.2000
358 2017/05/18 313.0600 5609153.0000 307.0000 313.9400 305.3100
359 2017/05/17 306.1100 6695657.0000 314.3900 314.6300 305.5000
360 2017/05/16 317.0100 4141066.0000 317.5900 320.0600 315.1400
361 2017/05/15 315.8800 7606854.0000 318.3800 320.2000 312.5300
362 2017/05/12 324.8100 4118613.0000 325.4800 327.0000 321.5300
363 2017/05/11 323.1000 4747172.0000 323.4000 326.0000 319.6000
364 2017/05/10 325.2200 5734524.0000 321.5600 325.5000 318.1200
365 2017/05/09 321.2600 9663374.0000 309.3800 321.9900 309.1000
366 2017/05/08 307.1900 7002907.0000 310.9000 313.7900 305.8200
367 2017/05/05 308.3500 8117449.0000 298.0000 308.5500 296.8000
368 2017/05/04 295.4600 14135990.0000 307.4350 307.7700 290.7601
369 2017/05/03 311.0200 6879259.0000 317.6700 321.5300 310.4500
370 2017/05/02 318.8900 5316551.0000 324.0000 327.6599 316.5601
371 2017/05/01 322.8300 8819888.0000 314.8800 327.2500 314.8100
372 2017/04/28 314.0700 4496659.0000 309.8300 314.8000 308.0000
373 2017/04/27 308.6300 3462663.0000 311.6900 313.0900 307.5000
374 2017/04/26 310.1700 4683131.0000 312.3700 314.5000 309.0000
375 2017/04/25 313.7900 6734162.0000 308.0000 313.9800 305.8600
376 2017/04/24 308.0300 5077771.0000 309.2200 310.5500 306.0215
377 2017/04/21 305.6000 4501958.0000 302.0000 306.4000 300.4200
378 2017/04/20 302.5100 6145961.0000 306.5100 309.1500 300.2300
379 2017/04/19 305.5200 3891145.0000 302.4600 306.6200 302.1100
380 2017/04/18 300.2500 3034225.0000 299.7000 300.8399 297.9000
381 2017/04/17 301.4400 4128067.0000 302.7000 304.0000 298.6800
382 2017/04/13 304.0000 9275682.0000 296.7000 307.3900 295.3000
383 2017/04/12 296.8400 6043648.0000 306.3400 308.4481 296.3200
384 2017/04/11 308.7100 5718053.0000 313.3800 313.4700 305.5000
385 2017/04/10 312.3900 7653623.0000 309.1500 313.7299 308.7100
386 2017/04/07 302.5400 4566632.0000 297.5000 302.6900 297.1500
387 2017/04/06 298.7000 5517731.0000 296.8800 301.9400 294.1000
388 2017/04/05 295.0000 7858565.0000 302.0400 304.8800 294.2000
389 2017/04/04 303.7000 10108230.0000 296.8900 304.8100 294.5300
390 2017/04/03 298.5200 13864850.0000 286.9000 299.0000 284.5800
391 2017/03/31 278.3000 3293698.0000 278.7300 279.6800 276.3197
392 2017/03/30 277.9200 4141437.0000 278.0400 282.0000 277.2100
393 2017/03/29 277.3800 3672526.0000 278.3400 279.6000 275.5400
394 2017/03/28 277.4500 7978665.0000 277.0200 280.6800 275.0000
395 2017/03/27 270.2200 6221361.0000 260.6000 270.5700 259.7500
396 2017/03/24 263.1600 5637668.0000 255.7000 263.8900 255.0100
397 2017/03/23 254.7800 3309844.0000 255.3900 257.6720 253.3000
398 2017/03/22 255.0100 4056735.0000 251.5600 255.0700 250.5100
399 2017/03/21 250.6800 6901555.0000 262.8300 264.8000 250.2400
400 2017/03/20 261.9200 3601616.0000 260.6000 264.5500 258.8210
401 2017/03/17 261.5000 6491018.0000 264.0000 265.3300 261.2000
402 2017/03/16 262.0500 7127180.0000 262.4000 265.7500 259.0600
403 2017/03/15 255.7300 5233365.0000 257.0000 261.0000 254.2700
404 2017/03/14 258.0000 7581719.0000 246.1100 258.1200 246.0200
405 2017/03/13 246.1700 3011280.0000 244.8200 246.8500 242.7810
406 2017/03/10 243.6900 3062785.0000 246.2100 246.5000 243.0000
407 2017/03/09 244.9000 3876494.0000 247.6300 248.6600 243.0000
408 2017/03/08 246.8700 3726746.0000 247.0000 250.0700 245.3200
409 2017/03/07 248.5900 3452587.0000 251.9200 253.8900 248.3200
410 2017/03/06 251.2100 3353601.0000 247.9100 251.7000 247.5100
411 2017/03/03 251.5700 2925481.0000 250.7400 251.9000 249.0000
412 2017/03/02 250.4800 3345751.0000 249.7100 253.2800 248.2700
413 2017/03/01 250.0200 4804963.0000 254.1800 254.8500 249.1100
414 2017/02/28 249.9900 6073890.0000 244.1900 251.0000 243.9000
415 2017/02/27 246.2300 11450160.0000 248.1700 248.3600 242.0100
416 2017/02/24 257.0000 8166869.0000 252.6600 258.2500 250.2000
417 2017/02/23 255.9900 14877090.0000 264.0000 264.6600 255.5600
418 2017/02/22 273.5100 8537811.0000 280.3100 283.4500 272.6000
419 2017/02/21 277.3900 5647575.0000 275.4500 281.4000 274.0100
420 2017/02/17 272.2300 6251469.0000 265.8000 272.8900 264.1500
421 2017/02/16 268.9500 7063860.0000 277.6000 280.0000 268.5000
422 2017/02/15 279.7600 4943879.0000 280.0000 282.2400 276.4400
423 2017/02/14 280.9800 7341450.0000 279.0300 287.3900 278.6100
424 2017/02/13 280.6000 7023072.0000 270.7400 280.7899 270.5100
425 2017/02/10 269.2300 3618336.0000 269.7900 270.9500 266.1100
426 2017/02/09 269.2000 7812600.0000 266.2500 271.1800 266.1500
427 2017/02/08 262.0800 3912428.0000 257.3500 263.3600 256.2000
428 2017/02/07 257.4800 4244063.0000 258.1900 260.0000 256.4200
429 2017/02/06 257.7700 3557600.0000 251.0000 257.8200 250.6300
430 2017/02/03 251.3300 2185230.0000 251.9100 252.1790 249.6800
431 2017/02/02 251.5500 2498799.0000 248.3400 252.4200 247.7100
432 2017/02/01 249.2400 3953105.0000 253.0500 253.2000 249.0500
433 2017/01/31 251.9300 4112013.0000 249.2400 255.8900 247.7000
434 2017/01/30 250.6300 3798638.0000 252.5300 255.2899 247.1000
435 2017/01/27 252.9500 3161774.0000 251.3800 253.0000 248.5200
436 2017/01/26 252.5100 3143717.0000 254.2900 255.7400 250.7500
437 2017/01/25 254.4700 5145301.0000 257.3100 258.4600 251.8000
438 2017/01/24 254.6100 4958144.0000 250.0000 254.8000 249.6500
439 2017/01/23 248.9200 6262097.0000 245.8500 250.8899 245.5000
440 2017/01/20 244.7300 4199720.0000 245.4600 246.0000 243.0100
441 2017/01/19 243.7600 7717244.0000 247.2500 248.6800 240.7500
442 2017/01/18 238.3600 3767272.0000 236.6500 239.7100 235.5800
443 2017/01/17 235.5800 4614731.0000 236.7000 239.9600 234.3700
444 2017/01/13 237.7500 6085610.0000 230.0000 237.8500 229.5900
445 2017/01/12 229.5900 3787547.0000 229.0600 230.7000 225.5800
446 2017/01/11 229.7300 3649910.0000 229.0700 229.9800 226.6800
447 2017/01/10 229.8700 3658981.0000 232.0000 232.0000 226.8900
448 2017/01/09 231.2800 3972716.0000 228.9700 231.9200 228.0000
449 2017/01/06 229.0100 5524153.0000 226.9300 230.3100 225.4500
450 2017/01/05 226.7500 5908927.0000 226.4200 227.4800 221.9500
451 2017/01/04 226.9900 11204560.0000 214.7500 228.0000 214.3100
452 2017/01/03 216.9900 5901494.0000 214.8600 220.3300 210.9600
453 2016/12/30 213.6900 4641288.0000 216.3000 217.5000 211.6800
454 2016/12/29 214.6800 4043086.0000 218.5600 219.2000 214.1225
455 2016/12/28 219.7400 3778544.0000 221.5300 223.8000 217.2000
456 2016/12/27 219.5300 5913335.0000 214.8800 222.2500 214.4200
457 2016/12/23 213.3400 4668263.0000 208.0000 213.4500 207.7100
458 2016/12/22 208.4500 3108427.0000 208.2200 209.9900 206.5000
459 2016/12/21 207.7000 5206143.0000 208.4500 212.2300 207.4100
460 2016/12/20 208.7900 4684269.0000 203.0500 209.0000 202.5000
461 2016/12/19 202.7300 3486937.0000 202.4900 204.4500 199.8400
462 2016/12/16 202.4900 3795444.0000 198.0800 202.5900 197.6000
463 2016/12/15 197.5800 3218653.0000 198.4100 200.7400 197.3900
464 2016/12/14 198.6900 4147314.0000 198.7400 203.0000 196.7600
465 2016/12/13 198.1500 6819322.0000 193.1800 201.2800 193.0000
466 2016/12/12 192.4300 2436428.0000 192.8000 194.4200 191.0400
467 2016/12/09 192.1800 2720937.0000 190.8700 193.8360 190.8100
468 2016/12/08 192.2900 3193684.0000 192.0500 192.5000 189.5400
469 2016/12/07 193.1500 5457071.0000 186.1500 193.4000 185.0000
470 2016/12/06 185.8500 3389365.0000 185.5200 186.5800 182.6825
471 2016/12/05 186.8000 4069480.0000 182.5100 188.8900 182.5100
472 2016/12/02 181.4700 4040201.0000 182.8800 184.8800 180.0000
473 2016/12/01 181.8800 5119105.0000 188.2500 188.5300 181.0000
474 2016/11/30 189.4000 3544891.0000 191.0000 191.8900 187.5000
475 2016/11/29 189.5700 4435312.0000 195.5600 196.7300 189.5000
476 2016/11/28 196.1200 4521082.0000 195.4800 199.3500 194.5500
477 2016/11/25 196.6500 2366098.0000 193.6400 197.2372 193.6400
478 2016/11/23 193.1400 4890285.0000 190.6100 195.6440 189.0000
479 2016/11/22 191.1700 5601238.0000 185.8400 191.4700 183.7100
480 2016/11/21 184.5200 4355872.0000 185.0400 188.8900 184.4100
481 2016/11/18 185.0200 5206473.0000 190.6500 193.0000 185.0000
482 2016/11/17 188.6600 4880969.0000 183.4900 189.4900 182.1101
483 2016/11/16 183.9300 3432668.0000 182.6500 184.7300 181.2100
484 2016/11/15 183.7700 3899743.0000 182.7800 186.4300 182.0500
485 2016/11/14 181.4500 6547913.0000 188.0000 188.2500 178.1900
486 2016/11/11 188.5600 3987091.0000 184.2400 188.8800 183.0000
487 2016/11/10 185.3500 6746290.0000 191.0500 191.6100 180.4200
488 2016/11/09 190.0600 8166447.0000 186.8750 192.0000 183.9500
489 2016/11/08 194.9400 3252927.0000 193.7900 197.4900 191.2600
490 2016/11/07 193.2100 3857682.0000 193.5900 194.2900 190.0500
491 2016/11/04 190.5600 5143915.0000 189.0000 193.4600 185.9600
492 2016/11/03 187.4200 2644550.0000 189.0000 191.4700 187.0401
493 2016/11/02 188.0200 4242250.0000 190.0500 192.6951 187.5050
494 2016/11/01 190.7900 7023674.0000 198.0400 198.5000 188.1050
495 2016/10/31 197.7300 4691320.0000 202.4900 202.4900 195.8100
496 2016/10/28 199.9700 4273456.0000 204.0000 205.3200 199.8300
497 2016/10/27 204.0100 13070990.0000 211.3400 213.7000 201.6500
498 2016/10/26 202.2400 5346893.0000 201.0000 203.1900 200.1000
499 2016/10/25 202.3400 2442118.0000 202.9000 204.6900 201.2000
500 2016/10/24 202.7600 2747344.0000 201.0000 203.9452 200.2500
501 2016/10/21 200.0900 2936908.0000 198.6000 201.5700 197.4100
502 2016/10/20 199.1000 5069410.0000 202.1200 203.0000 197.0500
503 2016/10/19 203.5600 6966185.0000 199.7400 206.6600 198.0600
504 2016/10/18 199.1000 5676046.0000 195.9900 199.4700 193.2600
505 2016/10/17 193.9600 4518331.0000 197.0500 198.3900 192.0000
506 2016/10/14 196.5100 4265471.0000 200.6600 201.4300 196.3000
507 2016/10/13 200.2400 2495140.0000 200.5000 200.8950 197.0500
508 2016/10/12 201.5100 1969099.0000 200.9500 203.8800 200.4200
509 2016/10/11 200.1000 2326754.0000 201.8500 202.2000 198.3100
510 2016/10/10 200.9500 3311340.0000 201.3500 204.1400 199.6600
511 2016/10/07 196.6100 3489480.0000 201.0000 201.3200 195.8000
512 2016/10/06 201.0000 4697937.0000 202.4600 204.2099 200.2100
513 2016/10/05 208.4600 1872456.0000 212.2400 213.1500 208.1200
514 2016/10/04 211.4100 3537953.0000 213.1000 213.3200 208.8200
515 2016/10/03 213.7000 5989342.0000 212.3000 215.6688 208.2500
516 2016/09/30 204.0300 2581730.0000 202.2100 204.9800 199.5500
517 2016/09/29 200.7000 2714040.0000 205.6000 207.3300 200.5800
518 2016/09/28 206.2700 2079324.0000 207.5100 208.2500 205.2600
519 2016/09/27 205.8100 3367907.0000 209.6500 209.9818 204.6093
520 2016/09/26 208.9900 2393373.0000 206.5000 211.0000 206.5000
521 2016/09/23 207.4500 2904125.0000 205.9900 210.1800 205.6700
522 2016/09/22 206.4300 2381600.0000 206.4000 207.2800 203.0000
523 2016/09/21 205.2200 2631285.0000 206.3700 207.0000 201.5600
524 2016/09/20 204.6400 2408556.0000 206.8500 207.7500 203.9100
525 2016/09/19 206.3400 2298318.0000 207.0000 209.4300 205.0000
526 2016/09/16 205.4000 3104266.0000 200.4200 205.7000 199.0000
527 2016/09/15 200.4200 3082942.0000 196.4900 202.5193 196.4000
528 2016/09/14 196.4100 2256143.0000 195.7500 197.9248 194.8562
529 2016/09/13 196.0500 3583140.0000 197.0600 198.4900 193.4500
530 2016/09/12 198.3000 3714049.0000 195.0000 201.3690 194.1000
531 2016/09/09 194.4700 3753734.0000 199.0900 199.9200 193.7000
532 2016/09/08 197.3600 3372293.0000 199.5500 199.8900 196.3600
533 2016/09/07 201.7100 3637918.0000 205.5000 206.4968 200.7100
534 2016/09/06 202.8300 4386193.0000 199.0200 203.2500 199.0000
535 2016/09/02 197.7800 5970154.0000 202.3300 203.2000 196.2000
536 2016/09/01 200.7700 7932444.0000 209.0100 211.0999 200.5000
537 2016/08/31 212.0100 3274854.0000 210.4300 212.6000 208.6500
538 2016/08/30 211.3400 3164222.0000 216.1100 216.1100 210.5200
539 2016/08/29 215.2000 3261381.0000 220.1500 220.4000 215.0000
540 2016/08/26 219.9900 2238087.0000 222.1400 222.8550 218.8200
541 2016/08/25 220.9600 1760212.0000 223.1100 223.8000 220.7700
542 2016/08/24 222.6200 2566947.0000 227.0500 227.1500 222.2200
543 2016/08/23 224.8400 4747745.0000 224.3200 228.4900 222.8000
544 2016/08/22 222.9300 2061692.0000 224.1700 225.1100 222.6800
545 2016/08/19 225.0000 1658616.0000 223.5400 225.1690 222.5300
546 2016/08/18 223.5100 1699300.0000 223.8200 225.6600 222.2900
547 2016/08/17 223.2400 1786408.0000 224.3300 224.8300 222.8000
548 2016/08/16 223.6100 2251115.0000 225.4900 227.1900 223.4101
549 2016/08/15 225.5900 2017964.0000 226.0200 229.5000 224.9300
550 2016/08/12 225.6100 1811850.0000 225.4100 226.6500 224.0400
551 2016/08/11 224.9100 1876959.0000 226.1700 227.5700 223.4100
552 2016/08/10 225.6500 2336496.0000 228.2400 229.8700 224.6200
553 2016/08/09 229.0800 2199766.0000 226.8200 231.5375 226.6500
554 2016/08/08 226.1600 2259465.0000 228.0000 229.6000 226.0900
555 2016/08/05 230.0300 3190342.0000 230.0000 232.0000 227.4000
556 2016/08/04 230.6100 4142155.0000 225.6900 230.8600 222.0500
557 2016/08/03 225.7900 3808747.0000 227.3700 229.6990 224.2100
558 2016/08/02 227.2000 3928706.0000 229.3700 229.8700 221.4000
559 2016/08/01 230.0100 4014048.0000 235.5000 236.6300 229.3800
560 2016/07/29 234.7900 3061574.0000 230.7000 235.2800 230.2400
561 2016/07/28 230.6100 2415462.0000 227.9500 230.7600 226.6000
562 2016/07/27 228.4900 2887028.0000 229.3400 233.3600 226.9200
563 2016/07/26 229.5100 3427251.0000 227.6900 230.0000 225.3000
564 2016/07/25 230.0100 4479483.0000 222.2700 231.3900 221.3715
565 2016/07/22 222.2700 2570462.0000 221.9900 224.5000 218.8800
566 2016/07/21 220.5000 4425756.0000 226.0000 227.8470 219.1000
567 2016/07/20 228.3600 2556119.0000 226.4700 229.8000 225.0000
568 2016/07/19 225.2600 3047535.0000 225.0000 229.1000 224.7500
569 2016/07/18 226.2500 3394588.0000 219.6400 227.0900 218.3000
570 2016/07/15 220.4000 2230821.0000 222.5200 222.7499 219.6400
571 2016/07/14 221.5300 2657899.0000 223.1200 224.9400 221.0500
572 2016/07/13 222.5300 3540699.0000 225.5000 225.5900 220.2900
573 2016/07/12 224.6500 4573875.0000 224.1000 227.5000 223.2200
574 2016/07/11 224.7800 5369066.0000 219.9600 226.7800 219.5100
575 2016/07/08 216.7800 4067131.0000 217.8000 219.8100 214.5000
576 2016/07/07 215.9400 3603385.0000 213.1000 218.1200 213.0100
577 2016/07/06 214.4400 4910285.0000 210.0000 215.2300 209.0000
578 2016/07/05 213.9800 5169832.0000 209.7300 214.5441 208.0000
579 2016/07/01 216.5000 5396030.0000 206.1400 218.2400 206.0000
580 2016/06/30 212.2800 4794440.0000 212.9700 213.4999 209.0200
581 2016/06/29 210.1900 5987120.0000 205.1300 211.7800 203.0000
582 2016/06/28 201.7900 6158996.0000 201.8900 204.0500 199.4100
583 2016/06/27 198.5500 7211823.0000 190.8600 198.8100 187.8700
584 2016/06/24 193.1500 6988949.0000 190.0500 195.1200 189.7300
585 2016/06/23 196.4000 10098190.0000 195.6900 197.5500 192.1300
586 2016/06/22 196.6600 23706100.0000 199.4700 205.9500 195.7500
587 2016/06/21 219.6100 2855619.0000 220.6800 222.5690 218.8100
588 2016/06/20 219.7000 3549768.0000 219.5000 223.7500 218.2300
589 2016/06/17 215.4700 3107734.0000 217.8100 219.9900 214.5000
590 2016/06/16 217.9300 2438692.0000 217.4200 218.0400 213.5000
591 2016/06/15 217.7000 2905002.0000 216.9500 221.9000 215.1300
592 2016/06/14 214.9600 3575822.0000 218.8800 222.2000 212.5300
593 2016/06/13 217.8700 4187833.0000 219.5000 225.7700 217.6600
594 2016/06/10 218.7900 5994548.0000 227.3900 227.9700 218.4217
595 2016/06/09 229.3600 4454222.0000 234.9800 235.3300 227.0600
596 2016/06/08 235.5200 5965110.0000 233.8000 240.8450 232.6050
597 2016/06/07 232.3400 6194154.0000 222.2400 234.4400 221.5200
598 2016/06/06 220.6800 2242634.0000 218.0000 220.9000 215.4500
599 2016/06/03 218.9900 2226110.0000 220.0000 221.9400 218.0100
600 2016/06/02 218.9600 2017279.0000 219.5900 219.9090 217.1100
601 2016/06/01 219.5600 2982270.0000 221.4800 222.4000 216.8900
602 2016/05/31 223.2300 2786682.0000 223.0400 224.7497 221.5001
603 2016/05/27 223.0400 3645792.0000 224.9900 225.9300 220.7500
604 2016/05/26 225.1200 4066512.0000 220.5000 225.2600 219.0500
605 2016/05/25 219.5800 3131279.0000 217.9100 221.3600 216.5100
606 2016/05/24 217.9100 3009327.0000 216.6000 218.7400 215.1800
607 2016/05/23 216.2200 5096751.0000 219.8700 222.6000 215.8600
608 2016/05/20 220.2800 8996546.0000 216.9900 220.5500 216.3500
609 2016/05/19 215.2100 6817922.0000 213.6200 216.7900 207.3000
610 2016/05/18 211.1700 5552692.0000 209.1500 215.3100 207.7500
611 2016/05/17 204.6600 2842028.0000 209.0500 209.8199 204.0200
612 2016/05/16 208.2900 2945754.0000 208.1500 213.1500 207.9200
613 2016/05/13 207.6100 2820616.0000 207.7800 211.2000 206.7000
614 2016/05/12 207.2800 3650075.0000 211.4400 211.6700 203.6572
615 2016/05/11 208.9600 5159640.0000 207.5900 215.4800 206.0500
616 2016/05/10 208.6900 4068053.0000 207.5500 209.4700 205.0000
617 2016/05/09 208.9200 4772992.0000 215.7200 216.1500 206.8000
618 2016/05/06 214.9300 5683675.0000 210.8700 216.3700 208.1100
619 2016/05/05 211.5300 11248340.0000 228.4600 228.6400 209.7900
620 2016/05/04 222.5600 8550004.0000 230.2900 234.4600 220.4000
621 2016/05/03 232.3200 4296325.0000 237.3600 238.9100 231.6200
622 2016/05/02 241.8000 3838958.0000 241.5000 243.1900 234.8200
623 2016/04/29 240.7600 5405164.0000 248.1400 248.4300 237.8100
624 2016/04/28 247.7100 2515595.0000 249.8500 253.4300 247.4400
625 2016/04/27 251.4700 3198105.0000 252.7500 255.0000 249.4000
626 2016/04/26 253.7400 3217779.0000 252.0500 255.7300 249.3900
627 2016/04/25 251.8200 3665088.0000 253.0100 257.3800 250.7600
628 2016/04/22 253.7500 3783126.0000 248.8900 254.0000 245.7100
629 2016/04/21 248.2900 2777079.0000 248.9900 250.9000 246.9100
630 2016/04/20 249.9700 5192343.0000 246.2600 253.6600 241.5000
631 2016/04/19 247.3700 6351360.0000 253.1200 254.3699 241.2510
632 2016/04/18 253.8800 4263246.0000 252.2300 258.3100 251.6600
633 2016/04/15 254.5100 3748593.0000 251.3100 254.6000 249.1200
634 2016/04/14 251.8600 4129258.0000 253.0000 256.8390 251.0501
635 2016/04/13 254.5300 4921554.0000 248.5100 255.5000 247.3300
636 2016/04/12 247.8200 5755351.0000 249.5000 251.8000 243.6300
637 2016/04/11 249.9200 9156404.0000 251.0000 258.9900 245.3000
638 2016/04/08 250.0700 7352707.0000 260.5000 260.8200 248.0201
639 2016/04/07 257.2000 8845567.0000 266.4500 269.3400 254.5100
640 2016/04/06 265.4200 11695760.0000 253.9700 267.7400 253.4500
641 2016/04/05 255.4700 9931470.0000 240.5000 256.5600 240.0000
642 2016/04/04 246.9900 13381160.0000 249.1200 252.1200 243.6400
643 2016/04/01 237.5900 15979910.0000 244.8250 247.9000 233.2500
644 2016/03/31 229.7700 7975638.0000 229.3400 237.4200 225.0100
645 2016/03/30 226.8900 4025670.0000 235.0900 235.5000 226.5000
646 2016/03/29 230.1300 4006037.0000 229.8900 232.3800 225.3300
647 2016/03/28 230.2600 3878599.0000 231.6100 234.8100 225.0000
648 2016/03/24 227.7500 4956604.0000 215.7800 228.8877 215.0000
649 2016/03/23 222.5800 4936203.0000 232.3700 234.7300 222.0300
650 2016/03/22 234.2400 4303052.0000 237.2100 238.9900 232.5580
651 2016/03/21 238.3200 5289014.0000 235.3400 239.8800 235.0000
652 2016/03/18 232.7400 4704761.0000 229.1000 234.4800 228.0600
653 2016/03/17 226.3800 3769083.0000 221.4700 228.5000 220.0000
654 2016/03/16 221.9300 3511873.0000 218.0000 222.5800 217.0200
655 2016/03/15 218.3400 3133230.0000 214.2700 218.9700 211.5000
656 2016/03/14 215.1500 4062304.0000 212.6500 216.7200 210.6400
657 2016/03/11 207.5000 3339148.0000 207.9300 209.4200 205.3300
658 2016/03/10 205.1800 5191602.0000 210.0000 213.2900 200.6710
659 2016/03/09 208.7200 3207597.0000 204.5200 209.3726 202.7900
660 2016/03/08 202.6000 4175498.0000 203.5000 207.5000 202.2000
661 2016/03/07 205.2900 5331097.0000 197.6800 209.7000 197.4000
662 2016/03/04 201.0400 6479858.0000 198.0000 204.0300 197.5001
663 2016/03/03 195.7400 4822993.0000 188.2800 197.4200 184.2200
664 2016/03/02 188.3400 4858631.0000 183.7300 188.5200 181.5000
665 2016/03/01 186.3500 6695704.0000 194.2500 195.9484 182.7000
666 2016/02/29 191.9300 4495402.0000 192.4000 196.3500 189.2220
667 2016/02/26 190.3400 6054061.0000 188.7000 192.0000 185.0000
668 2016/02/25 187.4300 5727008.0000 178.6500 188.5192 175.2000
669 2016/02/24 179.0000 5385369.0000 172.7500 179.5000 167.8400
670 2016/02/23 177.2100 5982993.0000 176.1600 181.7300 173.6800
671 2016/02/22 177.7400 5055340.0000 170.1200 178.9100 169.8500
672 2016/02/19 166.5800 2955832.0000 163.6600 167.4900 162.5000
673 2016/02/18 166.7700 3883107.0000 172.4200 172.9500 164.7700
674 2016/02/17 168.6800 5820264.0000 159.0000 169.3400 156.6800
675 2016/02/16 155.1700 5561638.0000 158.7000 162.9500 154.1100
676 2016/02/12 151.0400 7233264.0000 155.0000 157.0100 143.7000
677 2016/02/11 150.4700 14236900.0000 152.0000 163.2600 147.0000
678 2016/02/10 143.6700 10104690.0000 150.5000 154.9700 141.7400
679 2016/02/09 148.2500 8639661.0000 142.3200 159.7900 141.0500
680 2016/02/08 147.9900 9306754.0000 157.1050 157.1500 146.0000
681 2016/02/05 162.6000 9434495.0000 171.3000 173.0000 157.7442
682 2016/02/04 175.3300 4379442.0000 170.7000 175.9800 166.9900
683 2016/02/03 173.4800 7927640.0000 183.5900 183.9400 170.1800
684 2016/02/02 182.7800 5764817.0000 192.4200 193.1200 180.2300
685 2016/02/01 196.9400 5295685.0000 188.7600 199.5200 182.7500
686 2016/01/29 191.2000 2848929.0000 189.9500 193.7400 188.0800
687 2016/01/28 189.7000 4586328.0000 190.7900 191.2800 182.4100
688 2016/01/27 188.0700 3577353.0000 192.3800 193.2600 185.7700
689 2016/01/26 193.5600 4956918.0000 196.7000 197.8200 188.8800
690 2016/01/25 196.3800 2695408.0000 200.0600 203.5700 195.8800
691 2016/01/22 202.5500 3122066.0000 204.8010 205.5000 199.0300
692 2016/01/21 199.9700 3164424.0000 201.5500 203.2300 195.0200
693 2016/01/20 198.7000 5826110.0000 199.4000 201.2800 191.2500
694 2016/01/19 204.7200 4031271.0000 208.7100 210.4700 200.7800
695 2016/01/15 204.9900 5325773.0000 198.9700 205.0700 197.2500
696 2016/01/14 206.1800 6490579.0000 202.2100 210.0000 193.3800
697 2016/01/13 200.3100 4120993.0000 212.0100 212.6500 200.0000
698 2016/01/12 209.9700 3079051.0000 211.6000 213.7395 205.3100
699 2016/01/11 207.8500 4090843.0000 214.0100 214.4500 203.0000
700 2016/01/08 211.0000 3572360.0000 217.8600 220.4400 210.7700
701 2016/01/07 215.6500 3550704.0000 214.1900 218.4400 213.6700
702 2016/01/06 219.0400 3774353.0000 220.0000 220.0500 215.9800
703 2016/01/05 223.4300 3185525.0000 226.3600 226.8900 220.0000
704 2016/01/04 223.4100 6823510.0000 230.7200 231.3800 219.0000
705 2015/12/31 240.0100 2713817.0000 238.5100 243.4500 238.3700
706 2015/12/30 238.0900 3694448.0000 236.6000 243.6340 235.6707
707 2015/12/29 237.1900 2402438.0000 230.0600 237.7200 229.5470
708 2015/12/28 228.9500 1900171.0000 231.4900 231.9800 225.5400
709 2015/12/24 230.5700 710277.0000 230.5600 231.8800 228.2800
710 2015/12/23 229.7000 1551031.0000 232.1800 233.4500 228.1300
711 2015/12/22 229.9500 1958836.0000 234.9900 236.5500 229.6300
712 2015/12/21 232.5600 1951581.0000 231.6900 235.8300 231.0800
713 2015/12/18 230.4600 3008057.0000 232.8900 235.9000 229.2900
714 2015/12/17 233.3900 3294460.0000 233.9400 237.7600 229.8149
715 2015/12/16 234.5100 5100443.0000 222.1000 234.8800 220.7300
716 2015/12/15 221.0900 2241686.0000 221.8200 222.2200 218.0000
717 2015/12/14 218.5800 2827797.0000 217.5100 220.9200 214.8700
718 2015/12/11 217.0200 3259114.0000 225.2400 225.7500 216.6400
719 2015/12/10 227.0700 2070088.0000 224.7100 228.4900 223.6400
720 2015/12/09 224.5200 3057036.0000 226.7000 227.5000 220.7200
721 2015/12/08 226.7200 2682259.0000 227.5200 228.8000 224.2000
722 2015/12/07 231.1300 3140864.0000 227.7000 235.6300 226.1500
723 2015/12/04 230.3800 2572014.0000 232.4600 233.2700 227.6600
724 2015/12/03 232.7100 2937233.0000 235.4800 237.4500 230.0000
725 2015/12/02 231.9900 2980644.0000 237.0000 238.6000 231.2300
726 2015/12/01 237.1900 3728562.0000 231.0600 238.0000 231.0500
727 2015/11/30 230.2600 2591205.0000 231.7900 234.2800 229.0800
728 2015/11/27 231.6100 1949353.0000 231.0600 232.2500 227.0100
729 2015/11/25 229.6400 3986945.0000 221.3400 230.8250 220.3750
730 2015/11/24 218.2500 2478389.0000 215.3700 221.0000 215.0000
731 2015/11/23 217.7500 2525196.0000 217.3500 219.1800 214.6798
732 2015/11/20 220.0100 4394199.0000 223.4900 225.0000 213.5800
733 2015/11/19 221.8000 2499593.0000 220.5400 226.1900 220.3000
734 2015/11/18 221.0700 2810200.0000 214.5000 221.3800 212.5200
735 2015/11/17 214.0000 2148326.0000 215.2000 216.0000 211.4000
736 2015/11/16 214.3100 2920362.0000 206.0900 214.9800 205.8000
737 2015/11/13 207.1900 3423139.0000 212.9500 212.9900 206.5200
738 2015/11/12 212.9400 2913511.0000 217.8500 219.0000 212.6600
739 2015/11/11 219.0800 3337501.0000 217.7700 219.4800 213.6300
740 2015/11/10 216.5000 4612408.0000 223.4800 223.7000 216.0800
741 2015/11/09 225.3300 3846179.0000 232.9900 232.9900 224.3100
742 2015/11/06 232.3600 2444264.0000 230.7000 233.3590 229.5000
743 2015/11/05 231.7700 4494944.0000 230.5800 234.5843 229.1900
744 2015/11/04 231.6300 12713530.0000 227.0000 232.7400 225.2000
745 2015/11/03 208.3500 8065091.0000 213.8500 214.4400 207.7500
746 2015/11/02 213.7900 3924514.0000 208.9200 215.8000 207.2200
747 2015/10/30 206.9300 4432433.0000 210.4000 211.6300 203.8900
748 2015/10/29 211.6300 1794743.0000 211.7500 213.7481 210.6400
749 2015/10/28 212.9600 2726880.0000 211.3100 213.4500 208.3000
750 2015/10/27 210.3500 3512832.0000 214.8400 217.1000 207.5100
751 2015/10/26 215.2600 3388227.0000 211.3800 215.8800 210.0000
752 2015/10/23 209.0900 4226411.0000 215.0000 215.3500 207.6900
753 2015/10/22 211.7200 2818801.0000 211.5600 215.7500 209.4000
754 2015/10/21 210.0900 4177956.0000 211.9900 214.8100 208.8000
755 2015/10/20 213.0300 14877020.0000 227.7200 228.6000 202.0000
756 2015/10/19 228.1000 2506836.0000 226.5000 231.1500 224.9400
757 2015/10/16 227.0100 4327574.0000 223.0400 230.4805 222.8700
758 2015/10/15 221.3100 2835920.0000 216.4300 221.7300 213.7000
+115
View File
@@ -0,0 +1,115 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
import os
import requests
from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field
class EXASearchTool(BaseModel):
"""Wrapper for EXA Search API."""
search_url: str = "https://api.exa.ai/search"
headers: Dict = {
"accept": "application/json",
"content-type": "application/json",
}
max_results: Optional[int] = None
def run(self, query: str) -> str:
"""Run query through EXA and return concatenated results.
Args:
query (str): The search query to use
Returns:
str: The concatenated search results
"""
payload = {
"query": query,
"type": "magic",
}
headers = self.headers.copy()
headers["x-api-key"] = os.environ['EXA_API_KEY']
response = requests.post(self.search_url, json=payload, headers=headers)
results = response.json()
if 'results' in results:
return self._parse_results(results['results'])
return ""
def results(self, query: str, max_results: Optional[int] = None) -> List[Dict[str, Any]]:
"""Run query through EXA and return metadata.
Args:
query (str): The search query to use
max_results (Optional[int]): Maximum number of results to return
Returns:
List[Dict[str, Any]]: List of result dictionaries
"""
payload = {
"query": query,
"type": "magic",
}
headers = self.headers.copy()
headers["x-api-key"] = os.environ['EXA_API_KEY']
response = requests.post(self.search_url, json=payload, headers=headers)
results = response.json()
if 'results' in results:
return results['results'][:max_results] if max_results else results['results']
return []
def _parse_results(self, results: List[Dict[str, Any]]) -> str:
"""Parse results into a readable string format.
Args:
results (List[Dict[str, Any]]): List of result dictionaries
Returns:
str: Formatted string of results
"""
strings = []
for result in results:
try:
strings.append('\n'.join([
f"Title: {result['title']}",
f"Score: {result['score']}",
f"Url: {result['url']}",
f"ID: {result['id']}",
"---"
]))
except KeyError:
continue
content = '\n'.join(strings)
return f"\nSearch results: {content}\n"
# Create an agent with the tool
agent = Agent(
name="SearchAgent",
role="Research Assistant",
goal="Search for information about 'AI Agents Framework'",
backstory="I am an AI assistant that can search GitHub.",
tools=[EXASearchTool],
self_reflect=False
)
# Create tasks to demonstrate both tools
task = Task(
name="search_task",
description="Search for information about 'AI Agents Framework'",
expected_output="Information about AI Agents Framework",
agent=agent
)
# Create and start the workflow
agents = PraisonAIAgents(
agents=[agent],
tasks=[task],
verbose=True
)
agents.start()
+1434 -24
View File
File diff suppressed because it is too large. Load diff
+39
View File
@@ -0,0 +1,39 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
# Define the configuration for the Knowledge instance
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "praison",
"path": ".praison"
}
}
}
# Create an agent
rag_agent = Agent(
name="RAG Agent",
role="Information Specialist",
goal="Retrieve knowledge efficiently",
llm="gpt-4o-mini"
)
# Define a task for the agent
rag_task = Task(
name="RAG Task",
description="What is KAG?",
expected_output="Answer to the question",
agent=rag_agent,
context=[config] # Vector Database provided as context
)
# Build Agents
agents = PraisonAIAgents(
agents=[rag_agent],
tasks=[rag_task],
user_id="user1"
)
# Start Agents
agents.start()
+36
View File
@@ -0,0 +1,36 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
# Create Video Analysis Agent
video_agent = Agent(
name="VideoAnalyst",
role="Video Analysis Specialist",
goal="Analyze images and videos to extract meaningful information",
backstory="""You are an expert in computer vision and image analysis.
You excel at describing images, detecting objects, and understanding visual content.""",
llm="gpt-4o-mini",
self_reflect=False
)
# Task with Video File
task1 = Task(
name="analyze_video",
description="""Watch this video and provide:
1. A summary of the main events
2. Key objects and people visible
3. Any text or important information shown
4. The overall context and setting""",
expected_output="Comprehensive analysis of the video content",
agent=video_agent,
images=["video.mp4"]
)
# Create PraisonAIAgents instance
agents = PraisonAIAgents(
agents=[video_agent],
tasks=[task1],
process="sequential",
verbose=1
)
# Run all tasks
agents.start()
+5
View File
@@ -0,0 +1,5 @@
from praisonaiagents import Agent, Tools
from praisonaiagents.tools import duckduckgo
agent = Agent(instructions="You are a Web Search Agent", tools=[duckduckgo])
agent.start("Search about AI 2024")
+16
View File
@@ -0,0 +1,16 @@
from praisonaiagents import Agent, Task, PraisonAIAgents
from praisonaiagents.tools import wiki_search, wiki_summary, wiki_page, wiki_random, wiki_language
agent = Agent(
instructions="You are a Wikipedia Agent",
tools=[wiki_search, wiki_summary, wiki_page, wiki_random, wiki_language],
self_reflect=True,
min_reflect=3,
max_reflect=5,
)
agent.start(
"What is the history of AI?"
"First search the history of AI"
"Read the page of the history of AI"
"Get the summary of the page"
)
+1 -1
View File
@@ -1,6 +1,6 @@
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install flask praisonai==2.0.45 gunicorn markdown
RUN pip install flask praisonai==2.0.58 gunicorn markdown
EXPOSE 8080
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 276 files, more files were not shown because too many files have changed in this diff. Show more